WAF(Web Application Firewall)是渗透测试的第一道坎。扫之前先搞清楚对面是什么 WAF——Cloudflare?阿里云 WAF?安全狗?不同 WAF 的绕过策略天差地别。这篇从 sqlmap 的 WAF 检测模块拆解指纹识别的底层原理。
WAF 指纹识别的两种思路
- 主动探测:发送特定 Payload,根据响应特征判断。sqlmap 用的就是这招。
- 被动识别:看响应头里的
Server、X-Powered-By,或者 Cookie 里 WAF 注入的标记。
vibeWaf 结合了两种思路——先被动扫一眼,不命中再主动发 Payload。
被动识别:响应头里的证据
很多 WAF 会在响应中留下痕迹:
1 | PASSIVE_FINGERPRINTS = { |
1 | def passive_detect(target_url, session): |
主动探测:从 sqlmap 学攻击性检测
sqlmap 的 WAF 检测逻辑在 lib/request/connect.py 中。核心思路很简单:
发送一个显然恶意的 Payload → 看响应是否被拦截 → 根据拦截页面的特征判断 WAF 类型
1 | import hashlib |
WAF 指纹规则库
这是 vibeWaf 的核心——一个包含 60+ 条 WAF 指纹规则的 JSON 数据库:
1 | { |
每条规则包含多个检测维度(status + header + body),全部命中才判定为该 WAF,降低误报。
检测引擎实现
1 | import json |
绕过策略速查表
识别了 WAF 类型,绕过策略就有方向了:
| WAF | 弱项 | 绕过 Payload 示例 |
|---|---|---|
| Cloudflare | 分块传输编码 | Transfer-Encoding: chunked |
| ModSecurity | 参数污染 | ?id=1&id=1' OR '1'='1 |
| 阿里云 WAF | 大小写混写 | SeLeCt * FrOm users |
| 安全狗 | 内联注释 | /*!50000UNION*/ SELECT |
| 360 主机卫士 | HTTP/0.9 | 使用 HTTP/0.9 协议 |
| D盾 | 特殊字符编码 | %2527 (双重 URL 编码) |
实现中的细节
1. sqlmap 的 Payload 为什么用 MD5
1 | payload = f"%d' AND %d=%d UNION ALL SELECT NULL... -- {md5('waf_test')}" |
md5 字符串有两个作用:
- 唯一标识:如果响应中出现这个 md5,说明 Payload 未被执行(被 WAF 拦截了),但如果 WAF 拦截后返回了原始请求内容,这个 md5 也会出现。通过对比正常请求和恶意请求的响应差异来判断。
- 避免缓存:每次测试生成新的 Payload,绕过 CDN 缓存。
2. 多 Payload 确认
不要用一个 Payload 就下结论。至少发 2-3 个不同类型的恶意请求交叉验证:
1 | PAYLOADS = [ |
总结
WAF 指纹识别本质上是一个模式匹配问题。被动识别看响应头和 Cookie,主动探测发送恶意 Payload 看反应。sqlmap 的思路很经典——用一个明显恶意的请求试探,根据 WAF 的拦截页面特征反推类型。
知道对面是什么 WAF,后面的绕过才有方向。