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',防止低权限用户通过语法歧义触发意外行为 敏感操作(如删用户、改余额)必须走独立高权限账号 + 二次确认日志,不能复用普通业务账号
权限策略真正难的不是配置命令,而是持续对抗「为了上线快而开大权限」的惯性。每次加权限前,多问一句:这个操作能不能用视图 + 更细粒度权限替代?
