with grant option 允许用户直接转授当前持有的任意权限,mysql 不校验其本应拥有权限,仅检查当前持有状态;它不记录下游授权、回收后历史授权仍有效、usage+with grant option 会泄露库名,且无法限制转授范围。

WITH GRANT OPTION 会绕过权限校验直接转授
MySQL 不会在执行 GRANT 时检查用户是否“本应拥有”被授予的权限,只看该用户当前是否持有。比如你只给了 SELECT ON app_db.*,但用户加了 WITH GRANT OPTION,他就能执行 GRANT SELECT ON *.* TO 'attacker'@'%',把整个实例的读权限送出去。
常见错误现象:
- 安全审计时发现一堆非 DBA 创建的账号,且权限远超预期
-
SHOW GRANTS FOR 'u'@'h'看不到下游账号,因为 MySQL 不记录转授权行为 - 回收
GRANT OPTION后,已转授的权限依然有效(MySQL 8.0.16+ 才支持REVOKE GRANT OPTION,但仍不回滚历史授权)
USAGE + WITH GRANT OPTION 会导致库名泄露
当用户对某个库只有 USAGE 权限却带 WITH GRANT OPTION,比如 GRANT USAGE ON `file`.* TO 'ttt'@'%' WITH GRANT OPTION,MySQL 会让他在 SHOW DATABASES 中看到 file 这个库名——即使他完全不能查任何表。
这违反最小可见性原则,可能暴露敏感库命名逻辑或内部结构。实际场景中,攻击者可据此枚举出备份库、配置库、日志库等非业务库名,为后续提权铺路。
使用场景注意:
- 监控账号、健康检查账号通常只需
USAGE,绝不能配WITH GRANT OPTION - 测试环境临时账号若需代理授权,应限定到具体库+明确权限组合,避免用
USAGE搭配WITH GRANT OPTION
它和角色级的 WITH ADMIN OPTION 完全不是一回事
WITH GRANT OPTION 是账户级委托,绑定在 'user'@'host' 上;WITH ADMIN OPTION 是角色级委托,必须配合 CREATE ROLE 使用,且只能转授指定角色。
关键差异:
-
WITH GRANT OPTION无法限制转授范围:用户拿到后可授任意权限、任意对象、任意账号 -
WITH ADMIN OPTION只能再授同一个角色,比如GRANT 'backup_admin' TO 'ops_lead'@'10.0.1.%' WITH ADMIN OPTION,ops_lead不能授SELECT或其他角色 - 角色必须显式激活(
SET DEFAULT ROLE),否则权限不生效;而WITH GRANT OPTION一旦授予,登录即生效
root 报 “GRANT OPTION denied” 往往是认错了用户
你连的是 'root'@'192.168.1.100',但 mysql.user 表里只有 'root'@'localhost' 的 Grant_priv='Y',那远程连接就真的没授权能力。
排查步骤:
- 执行
SELECT USER(), CURRENT_USER();确认实际认证账户 - 查对应
host行的Grant_priv字段是否为Y - 必要时用
UPDATE mysql.user SET Grant_priv='Y' WHERE user='root' AND host='192.168.1.100';修正 - 改完必须
FLUSH PRIVILEGES;,且要重新登录才生效
最容易被忽略的是:权限匹配严格依赖 user 和 host 的完整字符串,'root'@'127.0.0.1' 和 'root'@'localhost' 互不兼容,也不能用通配符自动覆盖。











