SUPER和FILE权限组合等于授予服务器管理员权限,因SUPER可绕过运行时限制、FILE可读写文件系统,二者叠加能写Webshell或窃取敏感文件。
为什么SUPER和FILE权限一组合就等于送钥匙
普通应用账号一旦同时拿到 super 和 file 权限,攻击者在sql注入得手后,基本可以秒变服务器管理员。不是夸张——super 能绕过几乎所有运行时限制(比如改全局变量、杀任意会话),而 file 能读写服务器文件系统;两者叠加,就能用 select ... into outfile 写 webshell 到网站目录,或用 load_file() 直接偷取 /etc/shadow 或 mysql 自身的配置文件。
-
SUPER不该出现在业务账号里,哪怕只给一条SET GLOBAL max_connections=1000的权限,也等于开了个后门 -
FILE权限本身不依赖认证强度,只要 SQL 语句能执行,就能读写磁盘——且路径不受用户当前数据库影响 - 很多团队误以为“只给了 SELECT 权限就没风险”,却忘了
LOAD_FILE()是 SELECT 的一部分,不需要额外 INSERT/UPDATE 权限
如何立刻检查并回收危险权限
别靠记忆或文档,直接连上 MySQL 执行这条命令,查出所有带高危权限的账号:
SELECT user, host, Super_priv, File_priv FROM mysql.user WHERE Super_priv = 'Y' OR File_priv = 'Y';
重点看返回结果里有没有非 DBA 账号(比如 'appuser'@'%' 或 'report'@'10.20.%')。确认后,用 DROP USER 或 REVOKE 清理:
- 回收权限:
REVOKE SUPER, FILE ON *.* FROM 'appuser'@'%'; - 彻底删除(推荐):
DROP USER 'appuser'@'%';,再重建最小权限账号 - 注意:MySQL 8.0+ 中
REVOKE不会自动FLUSH PRIVILEGES,但修改mysql.user表后必须手动执行
secure_file_priv 是最后一道物理栅栏
即使误留了 FILE 权限,也可以靠 secure_file_priv 把危害锁死在指定目录。这个参数在 my.cnf 里设置,重启生效:
- 严格模式(推荐):
secure_file_priv = ""—— MySQL 8.0+ 支持,直接禁用所有LOAD_FILE/INTO OUTFILE - 受限模式:
secure_file_priv = "/var/tmp/"—— 只允许读写该目录,记得确保该目录权限为mysql:mysql且无执行位 - 千万别留空或设成
/、/tmp这类开放路径,否则形同虚设
改完务必验证:SELECT @@secure_file_priv; 返回值必须是你设的路径或空字符串,不能是 NULL。
替代方案比硬扛权限更可靠
业务真需要导入导出?别妥协开 FILE,换安全路径:
- 导出数据改用客户端工具:
mysqldump或mysqlpump,全程在客户端生成文件,服务端不碰磁盘 - 导入数据启用
LOAD DATA LOCAL INFILE,但前提是服务端local_infile = OFF(默认就是关的),且客户端明确加--local-infile=1 - 临时提权走运维通道:比如用 Ansible + sudo 执行一次
mysql -e "SELECT ... INTO OUTFILE",脚本执行完立即回收
最常被忽略的一点:测试环境的 '%'@'%' 账号往往带着 SUPER 混进生产备份镜像里——上线前不扫权限,等于把钥匙塞进交付包。

















