mysql如何定期检查权限风险_mysql安全巡检策略

2次阅读

应优先查询mysql.user表中grant_priv、super_priv、file_priv为’y’的账号,并特别标记host为’%’的高危账号;再结合performance_schema或系统日志识别长期未登录的闲置高权限账号予以回收。

mysql如何定期检查权限风险_mysql安全巡检策略

如何用SQL快速识别高危权限账号

MySQL里最危险的不是密码弱,而是账号被误授了GRANT OPTIONSUPERFILE或全库ALL PRIVILEGES。巡检第一件事就是查出这些账号:

  • select user, host, privilege_type FROM information_schema.role_table_grants WHERE privilege_type IN ('GRANT OPTION', 'SUPER', 'FILE')(适用于8.0+角色模型)
  • SELECT User, Host, Select_priv, Insert_priv, Update_priv, Delete_priv, Grant_priv, Super_priv, File_priv FROM mysql.user WHERE Grant_priv = 'Y' OR Super_priv = 'Y' OR File_priv = 'Y'(兼容5.7/8.0,直接查mysql.user
  • 特别注意Host'%'的账号——它允许从任意IP连接,比'localhost'风险高得多

哪些账号该被标记为“闲置”并回收

长期不用但拥有高权限的账号,是攻击者最爱的跳板。MySQL本身不记录登录时间,但可以通过以下方式交叉判断:

  • 检查performance_schema.events_statements_summary_by_account_by_event_name(需开启performance_schemaconsumers启用events_statements_summary_by_account_by_event_name
  • 结合系统日志:grep 'Connect' /var/log/mysqld.log | awk '{print $3}' | sort | uniq -c(前提是启用了general_loglog_error_verbosity=3
  • 更可靠的做法:在巡检脚本中加一步SELECT user, host FROM mysql.user WHERE account_locked = 'N' AND password_last_changed ,再人工确认是否真闲置

为什么SHOW GRANTS FOR 'user'@'host'不能代替权限表扫描

这个命令只显示当前生效的权限合并结果,会掩盖两个关键风险:

  • 角色(Role)叠加权限:用户A被赋予角色R,R有DROP权限,但SHOW GRANTS只显示ROLE R,不展开R的实际权限
  • 库/表级权限覆盖:用户在mysql库有SELECT,但在test.*ALLSHOW GRANTS会分两行显示,容易漏看第二行
  • 真正要巡检的是底层授权表:mysql.dbmysql.tables_privmysql.columns_priv——它们才是权限生效的唯一依据

自动化巡检脚本必须避开的三个坑

写定时任务跑SQL很容易,但实际部署时常见三类失效:

  • 权限不足:脚本用的账号没查mysql.user的权限,报错access denied for SELECT on mysql.user。解决方法:用root或显式授权SELECT ON mysql.*
  • 字符集混乱:脚本输出含中文注释或用户名,若终端或重定向文件编码是latin1,会导致???乱码,进而让grep漏匹配关键词。统一用SET NAMES utf8mb4开头
  • 未处理空值:比如max_connections字段为NULL时,WHERE max_connections > 100会跳过该行。巡检条件里所有数值比较都要加IS NOT NULL

复杂点不在SQL多难写,而在每次上线前得确认目标实例的版本、日志开关状态、字符集配置——漏一项,巡检报告就可能漏掉一个能删库的账号。

text=ZqhQzanResources