预处理阶段无法绕过,因其是mysql执行流程中不可跳过的语义检查环节,发生在语法解析之后、优化器之前,负责表/列存在性检查、权限校验、视图展开、参数绑定验证等,任一失败即在prepare阶段报错终止,不会进入后续执行。

预处理阶段的语法校验无法绕过——它不是过滤层,而是MySQL执行流程中不可跳过的语义检查环节。试图“绕过”只会导致语句在PREPARE阶段直接失败,根本不会进入后续执行。
为什么不能绕过预处理阶段的校验?
预处理(Preprocessor)发生在词法/语法解析之后、优化器之前,职责包括:表/列存在性检查、权限校验、视图展开、参数绑定验证等。这些不是可配置的“防护墙”,而是SQL执行引擎的必经步骤。
- 比如
SELECT * FROM nonexist_table,会在预处理阶段报错Unknown table 'nonexist_table',连EXPLAIN都进不去 -
SELECT phone FROM users若当前用户无phone列的SELECT权限,立刻返回ERROR 1142,不生成执行计划 - 占位符个数与
EXECUTE ... USING提供的参数不匹配,PREPARE成功但EXECUTE会报Incorrect number of arguments
哪些“绕过”其实是误解?
常被误认为“绕过预处理”的操作,实际是避开应用层逻辑或WAF规则,而非跳过MySQL自身的预处理流程:
- 用
/**/、%0a替换空格,只是让SQL字符串能被MySQL词法分析器接受,不影响预处理阶段对对象存在性和权限的检查 - 双写
UNIunionON或编码%75%6e%69%6f%6e,只在到达MySQL前对抗WAF;一旦解码成合法SQL,仍要走完整预处理 - 用
JOIN替代逗号、greatest()替代=,解决的是注入时关键词被过滤的问题,不改变预处理对函数是否存在、参数类型是否合法的判断
真正可控的调整点只有sql_mode和系统变量
预处理阶段的行为受sql_mode和部分系统变量影响,但这是配置级变更,不是运行时“绕过”:
- 关闭
STRICT_TRANS_TABLES可让某些隐式类型转换不报错(如INSERT INTO t(id) VALUES('abc')转成0),但表结构校验、权限检查照常 -
sql_mode=IGNORE_SPACE允许函数名后加空格(SUBSTR (str,1,1)),但SUBSTRX()依然报FUNCTION does not exist - 修改
max_allowed_packet或wait_timeout影响连接层,和预处理语义检查无关
预处理阶段没有“绕过”一说——它像编译器的语法+语义检查,错就是错,不存在打补丁式 bypass。所有看似成功的“绕过”,本质都是让输入最终变成MySQL认可的合法语句,而不是跳过校验本身。











