0%

Apache RocketMQ 远程代码执行(CVE-2023-33246)

CVE-2023-33246

产品介绍

RocketMQ是阿里巴巴在2012年开发的分布式消息中间件,后捐献给Apache软件基金会并成为Apache的顶级项目。RocketMQ专为万亿级超大规模的消息处理而设计,具有高吞吐量、低延迟、海量堆积、顺序收发等特点。

漏洞概述

RocketMQ 5.1.0及以下版本,在一定条件下,存在远程命令执行风险。漏洞源于RocketMQ的NameServer、Broker、Controller等多个组件暴露在公网中且缺乏权限校验。攻击者可以利用该漏洞利用更新配置功能以RocketMQ运行的系统用户身份执行任意操作系统命令。

受影响版本

5.0.0 <= Apache RocketMQ < 5.1.1

4.0.0 <= Apache RocketMQ < 4.9.6

漏洞分析

测试环境搭建

调试环境

访问项目官方仓库获取受影响漏洞版本源码

1
https://github.com/apache/rocketmq/releases

使用idea导入项目后配置运行时环境变量ROCKETMQ_HOME

image-20230720155335454

ROCKETMQ_HOME为ROCKETMQ运行家目录,配置好环境变量后在ROCKETMQ_HOME指向的目录行新建文件夹conf,进入conf目录并新建文件logback_broker.xml,将以下内容复制到该文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?xml version="1.0" encoding="UTF-8"?>

<!-- 配置文件修改时重新加载,默认true -->
<configuration scan="true">

<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="CATALINA_BASE" value="**/logs"></property>

<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="UTF-8">
<!-- 输出日志记录格式 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<!-- 第一个文件输出,每天产生一个文件 -->
<appender name="FILE1" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 输出文件路径+文件名 -->
<fileNamePattern>${CATALINA_BASE}/aa.%d{yyyyMMdd}.log</fileNamePattern>
<!-- 保存30天的日志 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder charset="UTF-8">
<!-- 输出日志记录格式 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<!-- 第二个文件输出,每天产生一个文件 -->
<appender name="FILE2" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${CATALINA_BASE}/bb.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${CATALINA_BASE}/bb.%d{yyyyMMdd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<appender name="CUSTOM" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${CATALINA_BASE}/custom.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${CATALINA_BASE}/custom.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<!-- 设置日志输出级别 -->
<root level="ERROR">
<appender-ref ref="CONSOLE" />
</root>
<logger name="file1" level="DEBUG">
<appender-ref ref="FILE1" />
</logger>
<logger name="file1" level="INFO">
<appender-ref ref="FILE2" />
</logger>
<!-- 自定义logger -->
<logger name="custom" level="INFO">
<appender-ref ref="CUSTOM" />
</logger>
</configuration>

环境配置完成后运行主类org.apache.rocketmq.broker.BrokerStartup启动ROCKETMQ Brocker,控制台输出以下内容则Brocker启动成功

image-20230720155841681

靶场搭建

使用vulhub靶场一键搭建

https://github.com/vulhub/vulhub/tree/master/rocketmq/CVE-2023-33246

详情

Broker在启动时会首先创建一个BrokerController然后运行它

image-20230720164935939

BrockerController创建过程中主要进行了配置文件解析、命令行解析、网络服务配置、日志配置等操作。

Controller启动时相继启动以下服务,其中在启动remotingServer服务时会启动broker监听在默认的10911端口

image-20230720165303285

在进行filterServerManager启动过程中会以30S的频率轮询创建filterServer

image-20230720165452954

创建filterServer时调用方法org.apache.rocketmq.broker.filtersrv.FilterServerManager#buildStartCommand解析数据拼接参数

image-20230720165739570

在进行参数拼接过程中会从brokerConfig中获取rocketmqHomenamesrvAddr两个值。

我们可以通过模拟RocketMQ协议向10911端口发送特制的数据包来影响rocketmqHome的值为可控的值,又因应用在进行命令拼接过程中未对用户的输入值进行有效的过滤,从而导致任意命令执行,此时我们使用网络上公开的PoC向10911端口发送数据然后调试

image-20230720170706116

image-20230720170558173

可以看到,此时获取的rocketmqHome值已经变更为我们输入的Payload

buildStartCommand方法调用完毕后,会返回拼接的字符串然后调用org.apache.rocketmq.broker.filtersrv.FilterServerUtil#callShell方法进行命令执行

整个流程的调用栈为

image-20230720171016289

修复措施

1、非必须勿向互联网开放不必要的服务端口,控制暴露面;

2、关键服务增加用户权限校验;

3、升级软件到不受影响的版本或最新版。

参考链接

软安解决方案

Buy me a coffee.

欢迎关注我的其它发布渠道