mysql权限越权本质是授权粒度粗,非自身漏洞;关键在最小权限原则、限定库表、禁用all privileges与通配符,并结合mysql.db表、连接参数及中间件路由实现双重控制。

MySQL 权限越权的本质是授权粒度太粗
越权不是 MySQL 本身有漏洞,而是 GRANT 时用了 ALL PRIVILEGES、* 或给错数据库/表名。比如对 test.* 授权却让应用连的是 production 库——只要连接用户没被限制库名,它照样能切过去执行 USE production,再操作数据。
关键判断点:权限是否绑定到具体对象(库、表、列),是否限制了可访问的数据库范围(通过 mysql.user 的 db 字段或代理层路由)。
用最小权限原则配置用户,别碰 ALL PRIVILEGES
生产环境用户应只拥有其业务逻辑真正需要的权限,且限定在明确的库和表上。
-
GRANT SELECT, INSERT ON myapp.users TO 'app_user'@'10.20.30.%';—— 比GRANT ALL ON myapp.*安全得多 - 避免通配符滥用:
GRANT SELECT ON `order_%`.*看似方便,但一旦新建order_backup_2024库就自动获得权限,容易失控 - 敏感操作(如
DROP、ALTER、FILE、SUPER)必须单独审批,不随业务账号下发 - 应用账号禁用
USAGE以外的全局权限(即不要给ON *.*的任何权限)
限制用户可访问的数据库,靠 db 表 + 连接参数双重控制
仅靠 GRANT 不够,MySQL 允许用户连接后用 USE 切库。要真正隔离,得配合 mysql.db 表和客户端连接参数:
- 插入记录到
mysql.db表:INSERT INTO mysql.db (Host, Db, User, Select_priv, Insert_priv) VALUES ('10.20.30.%', 'myapp', 'app_user', 'Y', 'Y');,再FLUSH PRIVILEGES; - 应用连接字符串中显式指定
database=myapp,避免连接后自由切换 - 若用中间件(如 ProxySQL、MaxScale),在路由规则里硬性绑定用户 → 库映射,比单纯依赖 MySQL 权限更可靠
- 注意:
mysql.db表不支持通配符库名,Db字段必须是字面量(如myapp_v2),不能写myapp_%
定期审计权限,重点查 SELECT 和 EXECUTE 越界风险
SELECT 权限最容易被忽视——它不改数据,但能拖走全部用户手机号、身份证;EXECUTE 若开放给存储过程,也可能间接调用高权限逻辑。
- 查越界读权限:
SELECT host, user, db FROM mysql.db WHERE db NOT IN ('myapp', 'information_schema') AND user = 'app_user'; - 查全局权限残留:
SELECT user, host, Super_priv, File_priv FROM mysql.user WHERE user = 'app_user';,确认为N - 用
SHOW GRANTS FOR 'app_user'@'10.20.30.%';输出结果,人工核对是否含未声明的库或WITH GRANT OPTION - 权限变更必须走版本化 SQL 脚本,禁止直接在生产库
GRANT,否则无法追溯
最常被忽略的一点:MySQL 权限检查是“叠加生效”的,mysql.db 表权限 + mysql.tables_priv 表权限 + mysql.columns_priv 列权限会合并判断。哪怕某张表只开了 SELECT,但如果 mysql.db 里对应库的 Select_priv 是 Y,那这张表就自动继承——这种隐式继承极易漏审。










