最直接合规检查第一步是直查 mysql.user 表,重点识别 host='%' 且具备 super_priv、grant_priv 或 file_priv 的高危账号,三条核心查询返回空结果才标志真正合规。

查 mysql.user 表识别高危账号最直接
合规检查第一步不是看日志,而是直查 mysql.user 表——它暴露了所有账号的全局权限基线。重点不是“有没有权限”,而是“谁在不该有权限的地方有权限”。
-
SELECT User, Host, Super_priv, Grant_priv, File_priv FROM mysql.user WHERE Super_priv = 'Y' OR Grant_priv = 'Y' OR File_priv = 'Y';必须跑,这三个权限等于给账号开了后门 - 特别注意
Host = '%'的结果:远程可连 + 高权限 = 最高风险组合,优先处理 CHAR_LENGTH(authentication_string) 比 <code>authentication_string = ''更可靠,能捕获 MySQL 5.7 哈希截断导致的弱密码- 别漏掉
User = 'root' AND Host != 'localhost',这是等保明确要求禁止的配置
SHOW GRANTS 不足以覆盖真实权限
SHOW GRANTS FOR 'u'@'h' 看起来权威,但它只展示显式授予的语句,会漏掉三类关键风险:
- 角色(Role)继承的权限:用户被赋予角色 R,R 有
DROP权限,但SHOW GRANTS只显示GRANT ROLE R,不展开 R 的实际内容 - 库/表级细粒度授权:
mysql.db或mysql.tables_priv里存在Insert_priv = 'Y',但不会出现在SHOW GRANTS输出中 - 动态权限(MySQL 8.0+):如
BACKUP_ADMIN、CLONE_ADMIN,它们不存于mysql.user,得查performance_schema.role_edges或information_schema.role_table_grants
用 bash 脚本自动化扫描要避开字段错位和注入
纯 mysql 命令就能完成轻量巡检,但脚本写错一行,结果就全偏。
- 必须用
mysql -N -s -e "SQL":-N去列头,-s关闭表格对齐,输出才是制表符分隔的干净数据 - 读取时设
IFS=$'\t',否则用户名含空格会导致User和Host字段错位 - 所有过滤条件硬编码进 SQL,比如
WHERE Host != 'localhost' AND Super_priv = 'Y'—— 绝不拼接变量,防 shell 注入 - 检测到高危组合立刻
echo "ALERT: remote super user found"并exit 1,方便 CI/CD 中断流程
定期执行不能只靠 cron,得验证结果有效性
定时任务跑成功 ≠ 检查到位。常见失效点藏在权限、编码、连接方式里。
- 脚本用的 MySQL 账号必须有
SELECT ON mysql.*,否则Access denied for SELECT on mysql.user静默失败 - 输出文件若用
> output.log重定向,终端默认编码是 latin1,中文用户名或注释会乱码,建议加export LANG=C.UTF-8 - 云 RDS 或 MySQL 8.0+ 环境下,
plugin = 'caching_sha2_password'用户即使authentication_string非空,也可能因未启用require_secure_transport而允许非加密连接 - 真正合规的标志不是“没报错”,而是三条核心检查返回空结果:
SELECT User, Host FROM mysql.user WHERE Host != 'localhost' AND (Super_priv = 'Y' OR Grant_priv = 'Y');SELECT User, Host FROM mysql.user WHERE CHAR_LENGTH(authentication_string) <br><code>SELECT User, Host FROM mysql.user WHERE User = 'root' AND Host != 'localhost';











