Apache Tomcat HTTP请求走私(CVE-2021-33037)漏洞分析
字数 2142 2025-08-05 08:19:04

Apache Tomcat HTTP请求走私漏洞(CVE-2021-33037)深入分析与教学指南

漏洞概述

Apache Tomcat在处理HTTP/1.0请求时,对Transfer-Encoding头的解析存在缺陷,导致在与反向代理一起使用时可能出现HTTP请求走私漏洞。该漏洞影响以下版本:

  • Apache Tomcat 10.0.0-M1至10.0.6
  • Apache Tomcat 9.0.0.M1至9.0.46
  • Apache Tomcat 8.5.0至8.5.66

HTTP请求走私基础

HTTP请求走私(HTTP Request Smuggling)是指攻击者通过精心构造的HTTP请求,利用前端代理(如Nginx)和后端服务器(如Tomcat)对HTTP协议解析的差异,使得前端和后端对请求边界的理解不一致,从而导致恶意请求"走私"到后端服务器的处理流程中。

常见HTTP走私类型

  1. CL不为0的GET请求:GET请求带有非零的Content-Length
  2. CL-CL:请求包含两个Content-Length头
  3. CL-TE:请求同时包含Content-Length和Transfer-Encoding头
  4. TE-CL:请求同时包含Transfer-Encoding和Content-Length头
  5. TE-TE:请求包含两个Transfer-Encoding头

CVE-2021-33037漏洞特殊性

Tomcat的这个漏洞与上述常见类型都不同,是通过HTTP版本和Transfer-Encoding头的特殊组合造成的。

漏洞核心问题

当客户端声明只接受HTTP/1.0响应时,Tomcat会错误地忽略Transfer-Encoding头,同时:

  • Tomcat会尊重identity编码
  • 不能确保分块编码(如果存在)是最终编码

漏洞复现

测试环境

  • Tomcat版本:9.0.35
  • 后端代码示例:request.getParameter("a");

测试请求

HTTP/1.1请求

POST /test HTTP/1.1
Host: example.com
Transfer-Encoding: chunked
Content-Type: application/x-www-form-urlencoded

3
a=b
0

Tomcat会正常解析Transfer-Encoding: chunked,参数a的值为"b"。

HTTP/1.0请求

POST /test HTTP/1.0
Host: example.com
Transfer-Encoding: chunked
Content-Type: application/x-www-form-urlencoded
Content-Length: 6

3
a=b
0

Tomcat会忽略Transfer-Encoding头,按照Content-Length解析,导致参数a的值为"b\r\n0\r\n"。

漏洞代码分析

Tomcat的HTTP协议解析主要在org.apache.coyote.http11.Http11Processor类的prepareRequest方法中实现。

HTTP/1.1处理流程

  1. 处理Transfer-Encoding头
  2. 将TE取值作为encoding增加到inputFilter中
  3. 对于多个TE值,以chunked结束
  4. 如果TE为identity则跳过处理
  5. 如果TE为chunked则设置相应过滤器
  6. 其他有效TE值调用addActiveFilter函数
  7. 无效TE值返回501错误

HTTP/1.0处理流程

关键代码判断:

if (http11 || inputBuffer.isChunkingAllowed()) {
    // 处理Transfer-Encoding
} else {
    // 跳过Transfer-Encoding处理
}

在HTTP/1.0协议下,Tomcat会跳过Transfer-Encoding头的处理,直接进入Content-Length的解析,默认激活identity编码。

实际攻击场景分析

搭建环境:Ubuntu 16.04 + Nginx 1.14.0 + Tomcat 8.5.45

发现Nginx对HTTP/1.0请求中的Transfer-Encoding也会进行解析,而Tomcat不能正确解析HTTP/1.0中的chunked数据,这就形成了TE-CL类型的HTTP走私漏洞。

RFC规范分析

根据RFC 7230第3.3.1节:

  • Transfer-Encoding是在HTTP/1.1中添加的功能
  • HTTP/1.0实现应忽略Transfer-Encoding
  • 客户端不应发送包含Transfer-Encoding的请求,除非知道服务器可以处理HTTP/1.1或更高版本的请求

Tomcat开发者可能误解了规范,直接将HTTP/1.0协议设置为不支持Transfer-Encoding,即使它实现了HTTP/1.1的Transfer-Encoding功能。

漏洞修复建议

  1. 升级到不受影响的Tomcat版本:

    • Tomcat 10.0.7+
    • Tomcat 9.0.47+
    • Tomcat 8.5.67+
  2. 配置反向代理确保HTTP协议版本一致性

  3. 在无法升级的情况下,限制只接受HTTP/1.1请求

防御措施

  1. 前端代理配置

    • 强制所有后端连接使用HTTP/1.1
    • 规范化请求头,移除冗余的Transfer-Encoding或Content-Length
  2. 后端服务器配置

    • 拒绝包含Transfer-Encoding头的HTTP/1.0请求
    • 严格验证请求格式
  3. 应用层防御

    • 实现请求验证中间件
    • 监控异常请求模式

总结

CVE-2021-33037展示了协议实现不一致带来的安全隐患,即使在遵循RFC规范的情况下,不同组件对协议细节的实现差异也可能导致严重的安全问题。这提醒我们在构建多层Web架构时,必须确保各组件对协议的处理方式一致,并对边界条件进行充分测试。

Apache Tomcat HTTP请求走私漏洞(CVE-2021-33037)深入分析与教学指南 漏洞概述 Apache Tomcat在处理HTTP/1.0请求时,对 Transfer-Encoding 头的解析存在缺陷,导致在与反向代理一起使用时可能出现HTTP请求走私漏洞。该漏洞影响以下版本: Apache Tomcat 10.0.0-M1至10.0.6 Apache Tomcat 9.0.0.M1至9.0.46 Apache Tomcat 8.5.0至8.5.66 HTTP请求走私基础 HTTP请求走私(HTTP Request Smuggling)是指攻击者通过精心构造的HTTP请求,利用前端代理(如Nginx)和后端服务器(如Tomcat)对HTTP协议解析的差异,使得前端和后端对请求边界的理解不一致,从而导致恶意请求"走私"到后端服务器的处理流程中。 常见HTTP走私类型 CL不为0的GET请求 :GET请求带有非零的Content-Length CL-CL :请求包含两个Content-Length头 CL-TE :请求同时包含Content-Length和Transfer-Encoding头 TE-CL :请求同时包含Transfer-Encoding和Content-Length头 TE-TE :请求包含两个Transfer-Encoding头 CVE-2021-33037漏洞特殊性 Tomcat的这个漏洞与上述常见类型都不同,是通过HTTP版本和Transfer-Encoding头的特殊组合造成的。 漏洞核心问题 当客户端声明只接受HTTP/1.0响应时,Tomcat会错误地忽略Transfer-Encoding头,同时: Tomcat会尊重identity编码 不能确保分块编码(如果存在)是最终编码 漏洞复现 测试环境 Tomcat版本:9.0.35 后端代码示例: request.getParameter("a"); 测试请求 HTTP/1.1请求 : Tomcat会正常解析Transfer-Encoding: chunked,参数a的值为"b"。 HTTP/1.0请求 : Tomcat会忽略Transfer-Encoding头,按照Content-Length解析,导致参数a的值为"b\r\n0\r\n"。 漏洞代码分析 Tomcat的HTTP协议解析主要在 org.apache.coyote.http11.Http11Processor 类的 prepareRequest 方法中实现。 HTTP/1.1处理流程 处理Transfer-Encoding头 将TE取值作为encoding增加到inputFilter中 对于多个TE值,以chunked结束 如果TE为identity则跳过处理 如果TE为chunked则设置相应过滤器 其他有效TE值调用addActiveFilter函数 无效TE值返回501错误 HTTP/1.0处理流程 关键代码判断: 在HTTP/1.0协议下,Tomcat会跳过Transfer-Encoding头的处理,直接进入Content-Length的解析,默认激活identity编码。 实际攻击场景分析 搭建环境:Ubuntu 16.04 + Nginx 1.14.0 + Tomcat 8.5.45 发现Nginx对HTTP/1.0请求中的Transfer-Encoding也会进行解析,而Tomcat不能正确解析HTTP/1.0中的chunked数据,这就形成了TE-CL类型的HTTP走私漏洞。 RFC规范分析 根据RFC 7230第3.3.1节: Transfer-Encoding是在HTTP/1.1中添加的功能 HTTP/1.0实现应忽略Transfer-Encoding 客户端不应发送包含Transfer-Encoding的请求,除非知道服务器可以处理HTTP/1.1或更高版本的请求 Tomcat开发者可能误解了规范,直接将HTTP/1.0协议设置为不支持Transfer-Encoding,即使它实现了HTTP/1.1的Transfer-Encoding功能。 漏洞修复建议 升级到不受影响的Tomcat版本: Tomcat 10.0.7+ Tomcat 9.0.47+ Tomcat 8.5.67+ 配置反向代理确保HTTP协议版本一致性 在无法升级的情况下,限制只接受HTTP/1.1请求 防御措施 前端代理配置 : 强制所有后端连接使用HTTP/1.1 规范化请求头,移除冗余的Transfer-Encoding或Content-Length 后端服务器配置 : 拒绝包含Transfer-Encoding头的HTTP/1.0请求 严格验证请求格式 应用层防御 : 实现请求验证中间件 监控异常请求模式 总结 CVE-2021-33037展示了协议实现不一致带来的安全隐患,即使在遵循RFC规范的情况下,不同组件对协议细节的实现差异也可能导致严重的安全问题。这提醒我们在构建多层Web架构时,必须确保各组件对协议的处理方式一致,并对边界条件进行充分测试。