mysql权限最小化需先禁用默认授权,再据日志反推最小权限;禁用%通配符、root远程登录;用sql查高危账号;角色须按场景封装且禁用grant option;应用层须加where过滤与账号隔离。

MySQL 用户权限最小化原则怎么落地
直接给用户 GRANT ALL PRIVILEGES 是最常见也最危险的越权根源。真实业务中,90% 的越权问题不是因为漏洞,而是权限分配时没想清楚「这个账号到底要做什么」。
实操建议:
- 新建用户后,先不授任何权限,再根据应用日志或 SQL 审计(如
general_log或代理层记录)反推所需最小权限 - 对 Web 应用账号,通常只需
SELECT、INSERT、UPDATE(且限定在特定表),禁用DROP、ALTER、CREATE、FILE、PROCESS - 避免使用
ON *.*,始终指定数据库名甚至表名,例如:GRANT SELECT ON myapp.users TO 'webuser'@'10.20.30.%' - 生产环境禁用
root远程登录;管理账号应绑定固定 IP 段,例如'dba'@'192.168.10.0/24'
如何快速发现已存在的越权账号
别等出事才查。MySQL 权限是叠加生效的,mysql.user、mysql.db、mysql.tables_priv 多层授权容易漏看。
执行这条语句能揪出高危账号:
SELECT User, Host, Select_priv, Insert_priv, Update_priv, Delete_priv,
Drop_priv, Alter_priv, Create_priv, File_priv, Super_priv, Grant_priv
FROM mysql.user
WHERE Drop_priv = 'Y' OR Alter_priv = 'Y' OR File_priv = 'Y' OR Super_priv = 'Y';
重点关注返回结果里 Host 为 % 或宽泛网段(如 10.%)的账号 —— 这些是越权操作的温床。
补充动作:
- 用
SHOW GRANTS FOR 'username'@'host';查单个账号完整权限,注意检查是否继承了role(MySQL 8.0+) - 定期导出权限快照:
mysqldump -u root -p --no-data mysql user db tables_priv columns_priv,用于比对变更
MySQL 8.0+ 角色(ROLE)机制怎么用才不翻车
角色不是万能胶,用错反而让权限更难理清。核心误区是把角色当「权限组」乱赋,结果一个 SET DEFAULT ROLE all_rw TO 'appuser' 就绕过最小化原则。
安全用法:
- 角色只封装明确场景的权限组合,例如
role_report_readonly(仅SELECT几张报表表),role_order_write(仅INSERT/UPDATE订单相关表) -
禁止给角色授予
GRANT OPTION,否则角色持有者可自行扩散权限 - 应用连接后立即执行
SET ROLE role_name;,而非依赖DEFAULT ROLE—— 这样可审计每次会话实际启用的角色 - 删除角色前,务必先查
mysql.role_edges确认无用户引用,否则权限残留
连接层和应用层必须补的权限兜底措施
MySQL 自身权限控制再严,也防不住应用拼接 SQL 或暴露调试接口。越权常发生在「权限对了,但逻辑错了」的地方。
关键补丁点:
- 所有用户输入进 SQL 前,强制做
WHERE user_id = ?过滤(比如订单查询必须带当前登录用户的 ID),不能只靠权限拦 - 数据库账号按应用模块隔离:后台系统用
admin_*账号,API 服务用api_*,定时任务用job_*,物理隔离比权限隔离更可靠 - 开启
sql_mode = 'STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER',防止低权限用户通过语法歧义触发意外行为 - 敏感操作(如删用户、改余额)必须走独立高权限账号 + 二次确认日志,不能复用普通业务账号
权限策略真正难的不是配置命令,而是持续对抗「为了上线快而开大权限」的惯性。每次加权限前,多问一句:这个操作能不能用视图 + 更细粒度权限替代?










