真正的后门权限藏在角色继承、代理关系和残留空用户中,需连查三张系统表;空用户名(User = '')和 host = '%' 的组合构成高危后门,易被扫描器利用。

直接查 mysql.user 表只能看到“明面上”的账号,真正的后门权限往往藏在角色继承、代理关系和残留空用户里——不连查三张系统表,等于没审。
查空用户名和通配 host 的高危组合
空用户名(User = '')不是“没填”,是 MySQL 允许无用户名连接的后门;host = '%' 也不是“所有 IP 都能连”,而是匹配所有未被更精确规则覆盖的来源,极易被扫描器命中。这两类账号一旦存在,基本等于开放白名单。
- 执行
SELECT user, host, authentication_string FROM mysql.user WHERE user = '' OR host = '%' OR (authentication_string = '' OR LENGTH(authentication_string) -
authentication_string长度小于 40 说明不是标准 SHA256 哈希,大概率是空密码或降级为mysql_native_password插件 - 别只看
account_locked = 'Y'就放心——锁住≠删除,ALTER USER ... ACCOUNT UNLOCK一行就能复活
必须连查 mysql.role_edges 看权限继承链
MySQL 8.0+ 中,一个普通账号可能通过角色获得 SUPER、GRANT OPTION 等高危权限,但 SHOW GRANTS FOR 'u'@'h' 默认不展开角色内容,查出来全是“USAGE”,实际却能删库。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 先查谁绑了角色:
SELECT FROM_USER, FROM_HOST, TO_ROLE FROM mysql.role_edges; - 再查角色本身有哪些权限:
SHOW GRANTS FOR ROLE 'role_name'; - 特别注意
TO_HOST = '%'的记录——这意味着该角色被授予给任意主机的账号,权限扩散失控
检查 mysql.proxies_priv 防代理绕过
代理机制允许一个低权限账号伪装成另一个高权限账号登录,比如 'monitor'@'%' PROXY 'dba'@'%',只要 With_grant = 'Y',还能把代理权再转授出去。
- 执行
SELECT * FROM mysql.proxies_priv WHERE Proxied_user != ''; - 重点看
Proxied_user = 'root'或Proxied_user = ''(空代理用户)的条目,后者是更隐蔽的绕过方式 - 这类账号不会出现在
mysql.user里,也不会在SHOW GRANTS中暴露真实能力
别信 CURRENT_USER(),用 SHOW GRANTS FOR 'u'@'h' 实锤
CURRENT_USER() 只返回当前连接身份,对审计毫无意义;而 SHOW GRANTS 是唯一反映账号“真实能力”的命令——但它只显示显式授权,不自动展开角色和代理,所以必须手动补查。
- 对每个可疑账号,必须带完整 host 执行:
SHOW GRANTS FOR 'username'@'host';(漏掉@'host'会报ERROR 1141) - 如果输出含
GRANT OPTION、ALL PRIVILEGES ON *.*、REPLICATION SLAVE,立刻收缩 host 范围或回收权限 - 若输出为空或只有
USAGE,不能判定安全——必须立即跳去查mysql.role_edges和mysql.proxies_priv
最常被忽略的是:备份恢复、Docker 重部署、mysql_secure_installation 一路回车,都会让已删除的 ''@'localhost' 或 'root'@'%' 复活。巡检不能只跑一次,得写进 cron 定期触发。

















