直接用'%'授权等于向任意ip开放账户权限,是越权访问最常见成因;应精确限定到ip段或域名,如'app_user'@'192.168.10.42',禁用'%'配合all privileges,并通过角色集中管理权限。

MySQL中GRANT语句使用'%'通配符的危险行为
直接用'%'作为主机名授权,等于向任意IP开放账户权限,是越权访问最常见、最直接的成因。比如执行GRANT ALL ON *.* TO 'admin'@'%',只要知道账号密码,攻击者从公网任意机器都能连上并执行高危操作。
这类授权在开发环境常被误用,但生产库一旦暴露在公网或内网边界,就相当于把数据库大门钥匙挂在门把手上。
-
'%'不等于“本机”或“可信网络”,它明确表示“所有主机”,包括外网扫描器 - MySQL 5.7+ 默认禁用
root@'%',但用户自建账号不受此限,需人工拦截 - 即使启用了防火墙,若DB服务监听
0.0.0.0:3306且未绑定skip-networking,通配符授权仍可被利用
如何安全地替换'%'为最小必要范围
核心原则:主机名必须精确到IP段或域名,拒绝模糊匹配。不是“能连上就行”,而是“只允许该业务节点连”。
- Web应用服务器固定IP?用
'app_user'@'192.168.10.42',而不是'app_user'@'%' - 容器化部署?优先用宿主机内网IP或Docker网络子网,如
'api_user'@'172.18.0.%'(注意:仅当该子网无其他非信任容器时才可用) - 云环境有安全组?仍需限制MySQL层主机名——安全组可能配置错误,而MySQL授权是最后一道过滤
- 绝对不要用
'%'配合ALL PRIVILEGES;即使是SELECT权限,对敏感表也应单独授权,例如GRANT SELECT ON app_db.users TO 'reporter'@'10.20.30.0/255.255.255.0'
检查与清理现有通配符授权的实操步骤
先确认哪些账号正在滥用'%',再逐个收敛。别跳过这步——很多线上库至今还留着'dev'@'%'这种账号。
- 查所有含
'%'的授权:SELECT User, Host FROM mysql.user WHERE Host = '%'; - 查具体权限:
SHOW GRANTS FOR 'username'@'%';,重点看是否包含GRANT OPTION或跨库权限 - 删除高危账号:
DROP USER 'old_user'@'%';(MySQL 5.7+ 支持直接DROP,无需先REVOKE) - 重授最小权限:
CREATE USER 'new_user'@'192.168.5.100' IDENTIFIED BY 'strong_pwd'; GRANT SELECT, INSERT ON app.orders TO 'new_user'@'192.168.5.100'; FLUSH PRIVILEGES;
MySQL 8.0+ 的角色机制如何降低通配符依赖
角色(Role)本身不解决'%'问题,但它让“按需授权”变得可持续。你不再需要给每个IP重复写一堆GRANT,而是集中管理权限集合。
- 创建角色:
CREATE ROLE 'app_reader'; GRANT SELECT ON sales.* TO 'app_reader'; - 将角色分配给具体主机账号:
CREATE USER 'web_app'@'10.1.2.3'; GRANT 'app_reader' TO 'web_app'@'10.1.2.3'; - 后续新增节点时,只需
CREATE USER+GRANT role_name TO user@host,避免遗漏或过度授权 - 注意:
SET DEFAULT ROLE必须显式执行,否则新用户登录后不会自动激活角色权限
真正难的不是技术操作,而是推动团队建立“每次加账号必填IP白名单”的流程习惯——通配符授权漏洞,90%源于开发提需求时一句“先开个通配的我调通再说”。











