mysql提权本质是权限失控,真实路径包括file/udf/系统表篡改等;须定期审计grants、禁用file权限、清理udf、限制secure-file-priv,并关注8.0角色与create user风险。

MySQL提权漏洞的本质是权限失控,不是版本旧
MySQL本身不“自带提权”,但root账号长期裸奔、任意用户拥有FILE或SELECT ... INTO OUTFILE权限、甚至被授予CREATE FUNCTION或INSERT/UPDATE系统表权限时,攻击者就能绕过认证写入动态库、加载UDF、篡改mysql.user表——这才是真实提权路径。
版本更新只是堵已知利用链(比如5.7.21前的LOAD DATA LOCAL INFILE服务端协议缺陷),但如果你给开发账号开了GRANT OPTION,再新的8.0.33也拦不住他给自己加SUPER。
-
SHOW GRANTS FOR 'app_user'@'%'必须定期跑,重点查是否含FILE、PROCESS、GRANT OPTION、CREATE ROUTINE、ALTER ROUTINE - 禁止用
%通配符授权,尤其是root@%——生产环境只允许root@127.0.0.1或跳板机IP - 删除所有空密码账号:
SELECT user,host FROM mysql.user WHERE authentication_string = '' OR password_expired = 'Y';
如何安全关闭FILE权限与危险函数
FILE权限是绝大多数Web层提权的起点:PHP/Python应用一旦SQL注入成功,配合SELECT ... INTO OUTFILE就能写/var/lib/mysql/xxx.php,或者读取/etc/passwd辅助爆破。它和LOAD_FILE()函数一样,不该出现在业务账号里。
- 回收权限用:
REVOKE FILE ON *.* FROM 'app_user'@'10.20.30.%';(注意ON后面不能是database.*,必须是*.*) - 禁用
LOAD_FILE()函数?不行——它是内置函数,无法单独禁用;只能靠权限控制+应用层过滤输入 - 真正要删的是UDF(用户自定义函数):
DROP FUNCTION IF EXISTS sys_eval;,并检查SELECT name FROM mysql.func;是否为空 - 启动时加
--secure-file-priv=/tmp能限制读写路径,但别设成/或空值,否则形同虚设
MySQL 8.0权限模型变化带来的审核盲区
8.0用role替代了部分权限组合,但CREATE ROLE本身是高危权限——一个有CREATE ROLE的账号,可以建角色、赋SUPER、再把角色给普通用户。很多DBA只扫GRANTS,漏掉了SHOW ROLES和SELECT * FROM role_edges;。
- 查谁有角色管理权:
SELECT * FROM mysql.role_edges WHERE TO_HOST = '%'; - 查角色实际拥有的权限:
SELECT * FROM mysql.role_edges r JOIN mysql.role_edges e ON r.FROM_HOST = e.TO_HOST;(需连表分析) -
CREATE USER权限也要警惕——它允许创建新账号,配合SET PASSWORD可重置任意用户密码(只要没开password_history策略) - 8.0默认开启
caching_sha2_password插件,但老客户端连不上时有人会降级为mysql_native_password,这反而削弱了密码强度校验
自动化权限审计该盯住哪几个表和命令
人工SHOW GRANTS太慢,且看不到历史变更。真正在意风险的人,会在备份脚本里顺手抓三张表+一个状态变量:
- 核心表:
mysql.user(账号、密码哈希、过期时间)、mysql.db(库级权限)、mysql.tables_priv(表级权限) - 关键变量:
SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'secure_file_priv'; - 权限扩散检查:
SELECT host,user,Select_priv,Insert_priv,Update_priv,Delete_priv,Grant_priv,Super_priv,File_priv FROM mysql.user WHERE Grant_priv='Y' OR Super_priv='Y' OR File_priv='Y'; - 别忘了
information_schema.PLUGINS——如果看到lib_mysqludf_sys.so这类第三方UDF,立刻DROP FUNCTION并查来源
最常被忽略的是:权限变更不会自动记录到binlog(除非开了log_builtin_as_dynamic且用ROW格式),所以靠从库日志审计行不通。得靠mysql.general_log或外部代理层埋点。











