最直接方法是查询mysql.user表中super_priv='y'的账号,但mysql 8.0+需结合role_edges表补查角色继承链,且show grants不显示super权限,验证须实际执行kill或set global操作。

查 mysql.user 表里 Super_priv = 'Y' 的账号最直接
MySQL 5.7 及更早版本中,Super_priv 字段为 'Y' 就代表该账号能执行 KILL、SET GLOBAL、绕过 SQL mode 等高危操作。这是最快的一线筛查方式,但必须注意:Super_priv 必须严格大写 S 和 P;查询需用有 SELECT ON mysql.* 权限的账号(如 root);刚执行 GRANT SUPER 但没 FLUSH PRIVILEGES 时,表里可能仍是 'N',而权限已实际生效。
MySQL 8.0+ 必须连查 role_edges 补角色继承链
只查 mysql.user 会漏掉通过角色获得 SUPER 的账号——它们在表里显示 Super_priv = 'N',却真实可用。分两步走:
先查谁绑定了角色:SELECT FROM_USER, FROM_HOST, TO_ROLE FROM mysql.role_edges;
再对每个 TO_ROLE 执行 SHOW GRANTS FOR 'role_name'@'%',若输出含 GRANT SUPER ON *.* TO,就说明该角色链提供 SUPER;最后反查哪些用户被授了这个角色:SELECT User, Host FROM mysql.user u JOIN mysql.role_edges r ON u.User = r.FROM_USER AND u.Host = r.FROM_HOST WHERE r.TO_ROLE = 'xxx';
别信 SHOW GRANTS,它永远不显示 SUPER
SHOW GRANTS FOR 'u'@'h' 输出里永远不会出现 GRANT SUPER ON *.* TO,哪怕用户真有该权限。这是 MySQL 内部设计限制,不是你查错了。它只展示显式 GRANT 语句,不解析角色继承、不读取 mysql.user 字段快照。验证是否真能用,最可靠的方式是登录该账号后执行 KILL QUERY 1 或 SET GLOBAL max_connections = 1000 —— 成功了,就是真有权限。
Host = '%' 的账号要立刻标记为最高风险
允许从任意 IP 连接的账号(Host = '%')配上 Super_priv = 'Y' 或 Grant_priv = 'Y',等于把数据库 root 密码贴在公网门口。巡检脚本中一旦检测到 Super_priv = 'Y' 且 Host = '%',应立即 echo "ALERT: wildcard root found" 并 exit 1,方便 CI/CD 流程中断。这类账号不能只改密码,必须收缩 Host 范围或降权——哪怕只改成 '192.168.%',攻击面也大幅收窄。











