普通用户无法直接修改DEFINER,所谓“修改”实为利用GRANT OPTION+CREATE ROUTINE权限创建新过程并指定高权限DEFINER,从而越权执行;根本风险在于权限失控而非语法漏洞。

普通用户无法直接修改 DEFINER,但若被授予 GRANT OPTION 或高危权限,就可能绕过限制创建恶意 DEFINER 过程/视图,从而越权执行操作——这才是真实风险点。
为什么普通用户能“修改”DEFINER其实是权限失控的信号
MySQL 不允许用 ALTER PROCEDURE 或 ALTER VIEW 修改 DEFINER(会报 ERROR 1064),所以所谓“修改”,本质是用户自己 CREATE 了一个新过程/视图,并指定 DEFINER='root'@'%' 或其他高权限账户。这只有在用户拥有 GRANT OPTION、CREATE ROUTINE 且目标 DEFINER 账户存在并具备对应权限时才可能成功。
- 常见错误现象:
CREATE DEFINER='root'@'%' PROCEDURE p_hack() ...执行成功,后续调用就能以root身份删库 - 根本原因不是语法漏洞,而是
GRANT OPTION+CREATE ROUTINE+ 宽泛Host的组合失控 - MySQL 8.0 会校验
DEFINER用户是否存在且有权限,但不会校验“你有没有资格指定他”——这个判断全靠你授不授权
禁止普通用户创建高权限 DEFINER 对象的关键配置
核心思路:不让普通用户拥有构造越权入口的能力,而不是事后去“拦截修改”。
- 绝对禁用
GRANT OPTION:对所有非 DBA 账号执行REVOKE GRANT OPTION ON *.* FROM 'app_user'@'%'; - 收回
CREATE ROUTINE和ALTER ROUTINE:除非业务明确需要自定义存储逻辑,否则一律不给app_user类账号 - 限定
DEFINER账户范围:只允许使用localhost或内网固定 IP 的专用账号(如'proc_runner'@'127.0.0.1'),避免'root'@'%'这类宽泛定义 - 启用
sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER',防止旧版兼容性绕过检查
如何快速发现已存在的危险 DEFINER 对象
别等出事再查。定期运行以下语句定位风险源:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
SELECT ROUTINE_NAME, ROUTINE_TYPE, DEFINER, SECURITY_TYPE
FROM information_schema.ROUTINES
WHERE DEFINER LIKE '%@\'%\'%'
OR DEFINER LIKE '%@\'%%\'%'
OR DEFINER NOT IN (SELECT CONCAT('''', User, '''@''', Host, '''') FROM mysql.user);
- 第一行匹配
'user'@'%'这种通配 Host,极易被滥用 - 第二行匹配含转义字符的异常格式(某些 ORM 导出时生成)
- 第三行检查
DEFINER是否指向一个根本不存在的账号——这类对象调用时会直接报ERROR 1449,但可能已被用于测试或留后门 - 同理检查视图:
SELECT TABLE_NAME, DEFINER, SECURITY_TYPE FROM information_schema.VIEWS WHERE ...
修复已有高危 DEFINER 的安全方式
不要直接 UPDATE mysql.proc 或 mysql.views —— MySQL 8.0+ 系统表受严格保护,且硬改容易导致元数据不一致或权限缓存失效。
- 首选方案:用
mysqldump --routines --no-create-info --no-data导出,手动替换DEFINER字段,加DROP PROCEDURE IF EXISTS后重载 - 临时应急:对已存在的危险过程,先
REVOKE EXECUTE ON PROCEDURE db.p_hack FROM 'attacker'@'%';切断调用链 - 彻底清理:确认无业务依赖后,
DROP PROCEDURE db.p_hack;,再从权限层面封死创建路径
真正难防的不是技术手段,而是开发人员顺手给应用账号加了 GRANT OPTION 却没意识到后果。每次授予权限时,都该问一句:这个权限是否能让用户“代表别人做事”?如果是,就必须配套审计和回收机制。










