项目简介
Apache ActiveMQ是最流行的开源、多协议、基于 Java 的消息代理。它支持行业标准协议,用户可以从多种语言和平台的客户端使用AMQP协议集成多平台应用程序。
厂商信息
https://github.com/apache/activemq
漏洞描述
Apache ActiveMQ官方发布新版本,修复了一个远程代码执行漏洞,攻击者可构造恶意请求通过Apache ActiveMQ的61616端口发送恶意数据导致远程代码执行,从而完全控制Apache ActiveMQ服务器。
受影响范围
Apache ActiveMQ < 5.18.3
Apache ActiveMQ < 5.17.6
Apache ActiveMQ < 5.16.7
Apache ActiveMQ < 5.15.16
本地调试
1、下载漏洞版本的activemq
https://archive.apache.org/dist/activemq/5.16.6/apache-activemq-5.16.6-bin.tar.gz
2、启动应用
./bin/activemq start
代码调试
1、加载activemq-all-5.16.6.jar,编写测试demo
2、成功返回shell
细节
通过diff发现改动的代码位于activemq-client和activemq-openwire-legacy两大模块,如下
进一步分析,发现上述改动基本相同,都是在实例化可抛出异常类之前对其类型进行了判断
在validateIsThrowable方法中判断了该类是否是Throwable类型
综上分析,该漏洞的成因是由于没有判断类是否是Throwable类型,就直接实例化,从而造成了代码执行。
通过分析调用流程,发现如下调用链,doUnmarshal会最终调用createThrowable方法。
在编写一个简单的activemq producer客户端,并发送消息。通过分析调用堆栈,发现下面核心代码。
但通过对比上述调用链可知,只有ConnectionErrorMarshaller;ExceptionResponseMarshaller的tightUnmarshal方法才会调用createThrowable。但是调试的时候,dsm为ConnectionInfoMarshaller。进一步分析发现,dsm的对象有下列选项
只需要让databtype为31或者16即可,而该值可以由攻击者控制
有多种方法可以构造恶意payload,我们可以分析数据流直接生成恶意payload,但必须熟悉openwire协议。这里选择直接分析客户端序列化流程。
分析发现activemq 客户端在执行多个动作的时候,都会触发上述断点,比如创建connection、创建session、创建队列等。因此选择任意一个进行分析。
根据客户端连接超时的异常信息,可以分析出activemq在发送请求时的处理逻辑
最后发现最终序列化的代码
接下来尝试修改command为ExceptionResponse
在createThrowable函数中成功触发断点
综上,我们只需要构造恶意的对象即可。参考相关资料发现ClassPathXmlApplicationContext 可以根据指定xml实例化类
由于activemq默认包含spring 框架,因此可以利用 ClassPathXmlApplicationContext 加载 XML 实现 RCE。
启动简单的http server
将下面payload保存为poc.xml并放到server根目录,得到payload地址http://127.0.0.1/poc.xml
测试发现,由于ExceptionResponse实例化的时候必须传入Throwable类型,但是ClassPathXmlApplicationContext并不是该类型,因此需要修改ClassPathXmlApplicationContext继承Throwable。直接在测试的源码目录下生成如下代码,覆盖原始ClassPathXmlApplicationContext
参考漏洞复现一节,可以成功rce。值得思考的点有很多,比如该漏洞绕过了activemq的验证机制,那么会不会存在其他的绕过验证的漏洞呢?修复方案中仅仅判断了是否是Throwable类型,那么能否找到符合条件的类并绕过补丁呢?
原文始发于微信公众号(jacky安全):Apache ActiveMQ远程代码执行漏洞
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论