最准起点是查 mysql.user 和 information_schema.role_table_grants;需重点核查 grant option、super_priv、root 的 host 值、敏感字段权限、密码策略、连接来源限制及权限变更可追溯性。

怎么快速发现谁有超纲权限
直接查 mysql.user 和 information_schema.role_table_grants 是最准的起点。很多团队只看账号是否“能连上”,却漏掉 GRANT OPTION、ALTER ROUTINE 或跨库 DROP 这类高危权限——它们不常被用,但一旦被滥用,就能绕过应用层控制。
- 运行
SELECT user,host,Select_priv,Insert_priv,Update_priv,Delete_priv,Grant_priv,Super_priv FROM mysql.user WHERE Grant_priv='Y' OR Super_priv='Y';,把结果里非DBA角色全标红 - 查具体用户权限时别只信
SHOW GRANTS FOR 'dev'@'%';,它不显示继承自角色的权限;得补一句SELECT * FROM information_schema.role_table_grants WHERE grantee="'dev'@'%'; - 重点盯
root账号的host值:如果还是'%',说明远程任意IP都能爆破;等保2.0明确要求限制为内网段(如'192.168.10.%')
敏感表/字段有没有被“裸奔”暴露
最小权限不是只看账号级别,而是落到具体表、甚至字段。比如一个报表账号,理论上只需要 SELECT 三个统计字段,但如果给的是 SELECT ON finance_db.transactions.*,那身份证、银行卡号、交易明细全在它视野里。
- 用
SELECT table_schema,table_name,column_name FROM information_schema.columns WHERE column_name REGEXP 'idcard|phone|bank|pwd|token' AND table_schema NOT IN ('mysql','performance_schema','information_schema');快速捞出敏感字段位置 - 再对每个敏感字段反查权限:
SELECT grantee,privilege_type,grantable FROM role_column_grants WHERE table_schema='user_db' AND table_name='users' AND column_name='id_card';(MySQL 8.0+ 支持列级权限) - 常见坑:开发习惯性用
GRANT SELECT ON user_db.* TO 'app'@'%';,以为只是读数据,却忘了user_db里混着一张config_secret表——权限颗粒度没跟上业务拆分节奏
密码策略和连接来源有没有形同虚设
等保要求密码必须满足长度、复杂度、定期更换三要素,但 MySQL 默认全关。更隐蔽的问题是:很多团队开了 validate_password 插件,却没改默认策略等级,导致 12345678 这种密码依然能通过校验。
- 检查当前策略:
SELECT @@validate_password_policy, @@validate_password_length, @@validate_password_mixed_case_count;;MEDIUM策略下,validate_password_length至少要设为10,且必须含大小写字母+数字+特殊字符 - 确认 root 是否禁用远程登录:
SELECT user,host FROM mysql.user WHERE user='root' AND host!='localhost';—— 如果有结果,立刻DROP USER 'root'@'x.x.x.x'; - 防火墙和数据库层双重限制:仅允许应用服务器 IP 连接
3306端口,同时数据库创建用户时强制指定 host,例如CREATE USER 'app_rw'@'10.20.30.40' IDENTIFIED BY '...';,而不是'%'
权限变更有没有留下可追溯痕迹
等保审计项里,“权限变更记录留存不少于180天”是硬指标。但 MySQL 默认不记谁什么时候改了谁的权限——general_log 太重,audit_log 插件又得额外装。最容易落地的方式,是靠触发器 + 自建日志表捕获关键操作。
- 开启
binlog并确保格式为ROW(binlog_format=ROW),虽然不能直接读语义,但配合mysqlbinlog工具可还原GRANT/REVOKE/DROP USER操作时间与执行者 - 手动补一层防护:建表
db_audit_log (id BIGINT AUTO_INCREMENT, op_time DATETIME, op_user VARCHAR(50), op_sql TEXT, client_ip VARCHAR(20)),再用代理层或中间件(如 ProxySQL)拦截并写入;比依赖 MySQL 原生审计插件更可控 - 最容易被忽略的一点:DBA 自己用脚本批量授权时,往往用同一个运维账号执行,日志里只显示“admin”操作,无法定位到具体责任人——必须要求所有自动化脚本带
--defaults-extra-file指定个人凭据文件
权限安全不是设完就完的事,真正难的是持续对齐业务变化:新上线的微服务要不要加字段读取?外包人员离职后权限是否秒删?这些动作一旦滞后,最小权限就变成纸面原则。等保检查时,他们不看你文档写得多漂亮,只翻最近三个月的权限变更记录和敏感字段访问日志。










