mysql 8.0+ 明确禁止角色间互相授予,即 grant role1 to role2 直接报错;权限扩散实际源于用户层滥用 grant option 或多角色叠加,需重点管控带 grant option 的用户及角色分配行为。

MySQL角色能否互相授予?8.0+明确禁止循环授权
MySQL 8.0+ 的 ROLE 机制从设计上就阻断了角色之间的直接授予权限——GRANT role1 TO role2 会直接报错 ERROR 3724 (HY000): Cannot grant roles to roles。这不是配置问题,而是内核级限制。角色只能被授予给用户(USER),不能作为权限容器再嵌套或转发。
为什么还会出现“权限扩散”?真正风险在用户层
所谓“循环授权”往往不是角色之间串连,而是用户被错误地同时持有多个高权限角色,或某个用户被额外授予了 GRANT OPTION,从而绕过角色隔离。常见诱因包括:
- 用
GRANT 'admin_role' TO 'dev_user'@'%' WITH GRANT OPTION—— 这条语句本身合法,但会让dev_user获得转授admin_role的能力 - 用户已拥有
GRANT OPTION ON *.*,再执行GRANT 'reader_role' TO 'attacker'@'%',就完成了一次隐性权限扩散 - 角色被设为默认角色后,用户登录即激活全部权限,若该角色包含
SELECT ON *.*或INSERT ON mysql.*,实际效果等同于全局权限
如何验证和堵住扩散路径
重点不是查角色之间有没有循环,而是查“谁能把角色给别人”:
- 查所有带
GRANT OPTION的用户:SELECT User, Host, Grant_priv FROM mysql.user WHERE Grant_priv = 'Y'; - 查哪些用户被显式授予了角色且带
WITH GRANT OPTION:SELECT * FROM mysql.role_edges WHERE USING_GRANT_OPTION = 1;(该字段 8.0.16+ 才有) - 回收高危授权:
REVOKE GRANT OPTION ON *.* FROM 'dev_user'@'%';,再确认SHOW GRANTS FOR 'dev_user'@'%';不含GRANT OPTION - 避免角色继承敏感权限:不要让
app_writer角色包含CREATE VIEW或EXECUTE,这类权限可能被用于提权
角色嵌套不可用,但间接扩散仍存在
虽然 GRANT role_a TO role_b 被禁止,但人可以绕过:用户 A 持有 role_a 和 role_b,再用 GRANT role_a TO user_c、GRANT role_b TO user_c,就等效实现了“组合授权”。所以关键控制点始终是人——不是角色本身,而是谁拥有 GRANT 权限、谁被允许分配角色。生产环境里,GRANT 操作必须限定在 DBA 账号下,且日志需留存完整上下文(谁、何时、对谁、授了哪个角色)。











