MySQL高权限账号是重大安全风险,攻击者可借此导出数据、删除表、读取服务器文件甚至提权;需重点检查Super_priv、Repl_slave_priv和File_priv权限,限制host为具体CIDR而非'%',并结合role_edges等表全面审计真实权限。

MySQL权限过大不是“功能强”,而是给攻击者递刀子。一旦账号被撞库、钓鱼或会话劫持,高权限账户能直接导出全库、删除核心表、读取服务器文件,甚至提权到操作系统层面。真实攻防演练中,70%以上的数据库横向渗透都始于一个 root@'%' 或误配的 app_user 拥有 FILE 和 SUPER 权限。
查谁有越权能力:别只看 GRANT OPTION,重点盯 Super_priv 和 Repl_slave_priv
很多人以为只要没开 WITH GRANT OPTION 就安全了,其实更危险的是那些能绕过权限检查的管理类权限:
-
SUPER权限允许 kill 任意连接、修改sql_mode、绕过只读限制——等于数据库里的“root shell” -
Repl_slave_priv常被忽略,但它能让攻击者伪装成从库,配合LOAD DATA LOCAL INFILE读取服务器任意文件(如/etc/shadow) -
FILE权限不只用于导出,还能写入 Web 目录造成 GetShell,或覆盖配置文件
执行这条语句快速定位:
SELECT user, host, Super_priv, Repl_slave_priv, File_priv FROM mysql.user WHERE Super_priv='Y' OR Repl_slave_priv='Y' OR File_priv='Y';
业务账号为何不能用 % 通配 host?DNS 欺骗和防火墙失效时它就是后门
把 'app_user'@'%' 当作“方便运维”的捷径,实际等于放弃网络层第一道防线:
- host 为
'%'时,即使绑定了内网 IP,只要 MySQL 配置了bind-address = 0.0.0.0,且防火墙规则松动,就可能被公网直连 - 若使用域名(如
'admin'@'db.company.com'),DNS 解析被污染或缓存投毒后,攻击者可将流量引向自己控制的服务器 - 正确做法是限定 CIDR 范围,例如
'app_user'@'10.20.0.0/16',并确保该段 IP 真实属于可信内网
SHOW GRANTS 结果不准:权限叠加、角色继承、动态权限全都不显示
运行 SHOW GRANTS FOR 'dev'@'localhost' 看到的只是显式授予的权限,但真实权限可能是三重叠加的结果:
- 角色继承:如果
dev被赋予了analyst_role,而该角色又有SELECT权限,SHOW GRANTS不会体现 - 动态权限(MySQL 8.0.16+):如
BACKUP_ADMIN、CLONE_ADMIN存在mysql.role_edges和mysql.default_roles表中,不在mysql.user字段里 - 代理用户(PROXY):通过
CREATE USER 'u'@'h' PROXY 'p'@'h';授予的间接权限,完全不会出现在常规查询中
要查完整权限链,得组合执行:
SELECT * FROM mysql.role_edges WHERE FROM_HOST = 'dev';
SELECT * FROM mysql.default_roles WHERE HOST = 'dev';
真正难的不是设权限,而是持续验证“此刻这个账号到底能干什么”。一次上线改配置、一次外包交接、一次临时提权修 bug,都可能留下僵尸权限。定期跑脚本比等审计报告更管用,尤其当你的 mysql.user 表里还躺着 ''@'localhost' 这种空用户名的时候。










