前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >rocketmq nameserver远程执行漏洞分析

rocketmq nameserver远程执行漏洞分析

作者头像
叔牙
发布2024-11-23 16:20:10
发布2024-11-23 16:20:10
14600
代码可运行
举报
运行总次数:0
代码可运行

提示: 靶场来自个人云服务器,真实网络环境渗透测试请严格遵守《中国网络信息安全法》,请勿轻易用于他人线上网络环境安全测试,本人不承担任何法律责任。

一、概述

CVE-2023-37582之所以存在,是由于CVE-2023-33246的补丁中并未对DefaultRequestProcessor#updateConfig方法中的configStorePath属性值进行过滤,所以在低版本中,当NameServer地址暴露在公网并且缺乏权限校验,未经授权的攻击者可payload注入到 configStorePath中,调用NameServer的更新配置函数将恶意文件上传到RocketMQ服务器中实现远程代码执行。

受影响版本
  • Apache RocketMQ <= 5.1.1
  • Apache RocketMQ <= 4.9.6

二、漏洞复现与利用

1.部署rocketmq

下载安装包

我们简单汇总分析一下scheduler和shedlock的核心能力,以及我们融合的想法。

代码语言:javascript
代码运行次数:0
复制
wget https://archive.apache.org/dist/rocketmq/4.9.6/rocketmq-all-4.9.6-bin-release.zip

broker.conf配置文件中都写成公网ip,便于测试。

公网开放端口(默认9876),至少开放nameserver端口:

然后使用root账户到rocketmq的bin目录执行启动命令:

代码语言:javascript
代码运行次数:0
复制
#启动nameserver
nohup sh mqnamesrv >/dev/null 2>&1 &
#启动broker
nohup sh mqbroker -c /usr/local/rocketmq/rocketmq4.9.6/conf/broker.conf autoCreateTopicEnable=true >/dev/null 2>&1 &

之所以用root启动,是为了模拟最高权限启动的服务给渗透getshell成功后操作最危险的事情。

通过命令看到端口监听成功,服务启动成功:

通过nc命令,检查nameserver端口通畅。

2.EXP

编写python脚本:

  • json中code填写318,代表UPDATE_NAMESRV_CONFIG
  • body填写要更新的属性,此处填写/var/spool/cron/root,盲猜是root启动nameserver,添加root的crontab任务
  • client.connect填入自己测试的nameserver ip地址或者开源靶场ip

此处我们是想要通过漏洞注入,添加crontab任务执行RCE,执行成功后会把所有的配置也都写到/var/spool/cron/root文件中,crontab会自动忽略不符合语法的任务,并且这种通过修改文件的方式添加,与crontab -e交互式添加任务不同的是,这种方式不需要重启crontab,而crontab -e交互式添加的任务需要重启crontab,也就是说我们只要写入到/var/spool/cron/root中并且格式合法,那么在下一个周期就会自动执行。

在执行python脚本之前,检查确认没有crontab任务:

上述添加的任务是每分钟执行在tmp目录创建success文件,确认该目录没有success文件。然后执行python脚本:

代码语言:javascript
代码运行次数:0
复制
python3 exploit.py

没有报错,命令执行成功,然后到/var/spool/cron/看一下root文件:

和我们预期的一样,把配置内容都写到了root账户的调度配置文件中,上述内容除了*/1 * * * * touch /tmp/success其他全部非法,前边说过crontab会自动过滤,不再赘述。

我们再看一下任务有没有添加成功:

很明显,任务已经添加成功。等个一分钟到tmp目录看一下success文件有没有创建成功。

到这里还不算完,那倘若我在一台测试机上执行命令启动一个tcp服务:

代码语言:javascript
代码运行次数:0
复制
nc -nvlp 4444

然后我把前边的python测试脚本稍作修改:

这样在执行python脚本会发生什么事情呢?很明显shell反弹,机器被控制。具体原理可自行研究。

3.EXP前置条件
  • root启动,对于非工具类服务,并且频繁爆出漏洞的的服务或者工具,应该用root启动吗?当然非root启动也能被渗透,只不过活动范围受限。
  • nameserver端口公网开放
  • rocketmq非安全版本

三、漏洞分析

CVE-2023-37582的本质是漏洞本质上是CVE-2023-33246的补丁绕过,看一下修复了什么东西:

修复的地方在namesrv,在updateconfig这个地方,这里可以用RocketMQ自己的协议,用不同的code调用过来实现不同的功能。

借别人抓取的一段tcp流量包分析:

提取tcp通信请求内容:

重点截取通信过程:

代码语言:javascript
代码运行次数:0
复制
...c..._{"code":0,"flag":1,"language":"JAVA","opaque":0,"serializeTypeCurrentRPC":"JSON","version":435}...d...

协议主要包含四部分,协议总长度+json长度+json+body,前后两段的c、d对应的是ascii编码。

在上述json数据包当中,比较重要的是"code":25,不同的code代表了不同的业务,根据数据包当中的code字段,程序会进行不同的业务处理,对于nameserver,code是318:

处理业务在 org.apache.rocketmq.namesrv.processor.DefaultRequestProcessor#processRequest方法中。

我们以4.9.6为例分析,看一下上述processRequest方法:

然后进入updateConfig更新配置:

代码语言:javascript
代码运行次数:0
复制
private RemotingCommand updateConfig(ChannelHandlerContext ctx, RemotingCommand request) {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    byte[] body = request.getBody();
    if (body != null) {
        String bodyStr;
        try {
            bodyStr = new String(body, MixAll.DEFAULT_CHARSET);
        } catch (UnsupportedEncodingException e) {}
        Properties properties = MixAll.string2Properties(bodyStr);
        if (properties == null) {
            log.error("updateConfig MixAll.string2Properties error {}", bodyStr);
            response.setCode(ResponseCode.SYSTEM_ERROR);
            response.setRemark("string2Properties error");
            return response;
        }
        if (properties.containsKey("kvConfigPath") || properties.containsKey("configStorePathName")) {
            response.setCode(ResponseCode.NO_PERMISSION);
            response.setRemark("Can not update config path");
            return response;
        }
        this.namesrvController.getConfiguration().update(properties);
    }
    response.setCode(ResponseCode.SUCCESS);
    response.setRemark(null);
    return response;
}

这里把请求体重的属性转换成Properties然后更新,继续看 this.namesrvController.getConfiguration().update(properties)方法:

代码语言:javascript
代码运行次数:0
复制
public void update(Properties properties) {
    try {
        readWriteLock.writeLock().lockInterruptibly();
        try {
            // the property must be exist when update
            mergeIfExist(properties, this.allConfigs);
            for (Object configObject : configObjectList) {
                // not allConfigs to update...
                MixAll.properties2Object(properties, configObject);
            }
            this.dataVersion.nextVersion();
        } finally {
            readWriteLock.writeLock().unlock();
        }
    } catch (InterruptedException e) {}
    persist();
}

此处会从传入body解析的configStorePath替换掉默认的配置。

这里会遍历所有配置并更新配置,然后调用方法persist持久化:

代码语言:javascript
代码运行次数:0
复制
public void persist() {
    try {
        readWriteLock.readLock().lockInterruptibly();
        try {
            String allConfigs = getAllConfigsInternal();
            MixAll.string2File(allConfigs, getStorePath());
        } catch (IOException e) {
            log.error("persist string2File error, ", e);
        } finally {
            readWriteLock.readLock().unlock();
        }
    } catch (InterruptedException e) {}
}

此方法的目的其实是将configObjectList写入进对应的配置文件当中。

其实这个漏洞的本质就是从传入的configStorePath替换了默认的路径并实现了任意文件写,导致的远程RCE。

四、漏洞修复与思考

1.修复与防护
  • 内网访问,慎重开启公网端口
  • 服务启动使用非root账户,并限制其操作权限
  • 升级到安全版本;>=5.1.2,>=4.9.7
2.思考

从漏洞库搜索到rocketmq还有挺多其他漏洞,有很多人吐槽大厂不用的东西开源出来坑别人,其实不然,对于工具类开源项目,其他的大厂人家也有能力自研,就算用他的也会开源+二开,然后主要是中小厂图简单省事儿用它,这些企业和项目对安全、运维的投入相对较少,专业度相对较弱,也基本没有内网环境,所以公网裸奔,之前内网运行的东西,放到公网环境运行,可以想象会有多少bug和漏洞。另外它bug和漏洞多,不代表其他中间件漏洞少,比如一个中间件10个人用,用了一年发现一个漏洞,另外一个中间件 10000个人用,可能每天都能发现bug。

所以对于开源软件,不要排斥,也不要一股脑地接受,理性看待,对于一两个人维护的项目你用它干干啥,复杂一些、规模大一些的项目,选择中间件也是个相对慎重的过程,并且也会有专人专项时刻观察市面上各大漏洞库的公布内容,一旦发现有严重bug那么就及时修复或者升级。

另外对于本篇内容,如果感兴趣的,可以一起沟通交流,如果需要工具或者上述脚本的可以自行搜索或者联系作者,最后还要强调一下,不要去尝试访问非自己持有的机器。

参考

https://github.com/apache/rocketmq/pull/6843

https://lists.apache.org/thread/m614czxtpvlztd7mfgcs2xcsg36rdbnc

https://github.com/Malayke/CVE-2023-37582_EXPLOIT

https://drun1baby.top/2023/11/21/CVE-2023-37582-Apache-RocketMQ-RCE-%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/

https://avd.aliyun.com/detail?id=AVD-2023-37582

https://www.cnblogs.com/spmonkey/p/17767846.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-11-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PersistentCoder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、概述
    • 受影响版本
  • 二、漏洞复现与利用
    • 1.部署rocketmq
    • 2.EXP
    • 3.EXP前置条件
  • 三、漏洞分析
  • 四、漏洞修复与思考
    • 1.修复与防护
    • 2.思考
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档