ActiveMQ(<5.18.3)RCE

ActiveMQ(<5.18.3)RCE

背景信息

影响版本:

  • Apache ActiveMQ < 5.18.3
  • Apache ActiveMQ < 5.17.6
  • Apache ActiveMQ < 5.16.7
  • Apache ActiveMQ < 5.15.16

参考:

AMQ-9370 - Openwire marshaller should validate Throwable class type · apache/activemq@958330d (github.com)

activemq/activemq-openwire-legacy/src/main/java/org/apache/activemq/openwire/v4/ExceptionResponseMarshaller.java at 1d0a6d647e468334132161942c1442eed7708ad2 · apache/activemq (github.com)

[Apache ActiveMQ CVE-2023-46604 RCE 分析 - Boogiepop Doesn't Laugh (boogipop.com)](https://boogipop.com/2023/11/03/Apache ActiveMQ CVE-2023-46604 RCE 分析/)

其实有个疑问,该漏洞的source点看了很多一直不是很清楚具体是哪些点?MQ的通信是只要和服务端通信就会触发还是有相关的逻辑?

漏洞分析

通过之前版本差异可看出问题出在下面这里(V12只是其中一个版本,还有另外三个)

org.apache.activemq.openwire.v12.BaseDataStreamMarshaller#createThrowable

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);
    }
}

从中可以看到className和message若是可控则会任意类构造方法调用,而其中spring自带的org.springframework.context.support.ClassPathXmlApplicationContext则是符合这样的利用链CPX;因此问题则是找到对应的触发点;

选取tightUnmarsalThrowable方法跟踪:

org.apache.activemq.openwire.v12.BaseDataStreamMarshaller#tightUnmarsalThrowable

image-20240226142634018

发现ExceptionResponseMarshaller等四个存在调用,网上基本利用的是ExceptionResponseMarshaller,其他的类应该也可以利用,比如ConnectionErrorMarshaller、MessageAckMarshaller等。出漏洞的createThrowable方法实际在这些Marshallers的父类BaseDataStreamMarshaller中,只要调用了这个函数来反序列化数据流就会导致漏洞。

image-20240226142729312

选择常用的ExceptionResponseMarshaller这个跟踪;

org.apache.activemq.openwire.v12.ExceptionResponseMarshaller#tightUnmarshal

会发现OpenWireFormat文件中存在两处方法调用了,而openwire就是ActiveMQ内置默认协议,61616端口,生产者和消费者交互的端口;

image-20240226143415460

而其中doUnmarshal方法则是

org.apache.activemq.openwire.OpenWireFormat#doUnmarshal

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;
    }
}

因此问题关键则是发送一个ExceptionResponse对象,之后调用其unmarshal方法,最后触发createThrowable;

环境调试准备

测试程序demo:

package com.yglearnsec.javasec.activemq;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQObjectMessage;

import javax.jms.*;

public class ActiveMQOpenWrite {
    public static void main(String[] args) throws JMSException {
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
        Connection connection = connectionFactory.createConnection();
        connection.start();

        Session session = connection.createSession();
        Destination destination = session.createQueue("testQueus");

        MessageProducer producer = session.createProducer(destination);
        //ActiveMQObjectMessage message001= session.createMessage();
        Message message = session.createObjectMessage("123");
        producer.send(message);
        //producer.send(message001);

        connection.close();
    }
}

往上基本都是根据此模拟序列化过程将序列化(客户端的过程还是不太一样)过程中的对象进行替换成对应的恶意类;

apachemq5.18.2的代码下载后基于wapper tomcat,修改添加debug参数

wrapper.java.additional.8=-Xdebug
wrapper.java.additional.9=-Xnoagent
wrapper.java.additional.10=-Djava.compiler=NONE

wrapper.java.additional.11=-Xrunjdwp:transport=dt_socket,server=y,address=2999,suspend=n

之后在IDEA中添加java remote debug配置

image-20240226153204342

之后通过相关方法发送恶意数据触发,在org.apache.activemq.openwire.OpenWireFormat#doUnmarshal中设置断点即可查看相关利用链;

image-20240226154202257

posted @ 2024-03-20 13:53  Yg~  阅读(216)  评论(0)    收藏  举报