Web安全之HTTP请求走私攻击(HTTP Request Smuggling)详解
字数 2733 2025-12-09 22:53:02

Web安全之HTTP请求走私攻击(HTTP Request Smuggling)详解

描述
HTTP请求走私是一种利用HTTP服务器对请求消息解析的差异,通过构造一个模糊的HTTP请求,来干扰请求的处理边界,从而让前端代理服务器与后端源站服务器对“请求的结束位置”和“下一个请求的开始位置”产生不同判断的攻击技术。成功利用可导致请求走私、缓存投毒、权限绕过、窃取用户请求等严重后果。


解题过程与原理详解

核心问题根源:HTTP/1.1允许在单个TCP连接上发送多个请求,协议依靠“Content-Length”和“Transfer-Encoding”等头部来判断每个请求的边界。当前端服务器(如反向代理、CDN、WAF)与后端服务器采用不同的方式解析请求边界时,就会产生解析歧义,攻击者可精心构造一个请求,使得前端和后端看到不同的“请求组合”。


第一步:理解两种确定请求体长度的标准方法

  1. Content-Length

    • Content-Length: 13 明确表示请求体长度为13字节。
    • 服务器读取完请求头后,会严格按照这个长度读取对应字节数的请求体,之后认为当前请求结束,后续数据属于下一个请求。
  2. Transfer-Encoding: chunked

    • 表示请求体是分块传输的。格式为:
      <块大小(十六进制)>\r\n
      <块数据>\r\n
      0\r\n
      \r\n
      
    • 服务器会一块一块地读取,直到遇到一个大小为0的块,标志请求体结束。

关键点:HTTP规范规定,如果请求中同时包含Content-LengthTransfer-EncodingTransfer-Encoding应被优先采用,Content-Length应被忽略。但并非所有服务器都严格遵守此规范,或处理顺序存在差异。


第二步:认识两种经典的走私攻击技术

假设网络拓扑为:客户端 -> 前端服务器 -> 后端服务器。攻击者通过一个TCP连接发送恶意请求。

  1. CL.TE走私(前端用Content-Length,后端用Transfer-Encoding

    • 构造请求
      POST /vulnerable-endpoint HTTP/1.1
      Host: target.com
      Content-Length: 6
      Transfer-Encoding: chunked
      
      0
      
      G
      
    • 前端视角:看到Content-Length: 6。它会读取6个字节的请求体(即0\r\n\r\nG),之后认为第一个请求结束,将剩余的字符G视为下一个请求的开始
    • 后端视角:看到Transfer-Encoding: chunked。它开始分块解析:第一块0\r\n表示0字节,接着\r\n,于是认为整个请求体已结束。后面的字符G被当作是下一个请求的第一个字符。
    • 结果:后端将G解析为下一个请求的起始(例如GET /admin HTTP/1.1...的一部分),实现了请求走私。如果这个“走私”的请求能影响其他用户的请求,就形成了攻击。
  2. TE.CL走私(前端用Transfer-Encoding,后端用Content-Length

    • 构造请求
      POST /vulnerable-endpoint HTTP/1.1
      Host: target.com
      Content-Length: 4
      Transfer-Encoding: chunked
      
      5c
      (这里是92字节的恶意数据,例如“GET /admin HTTP/1.1\r\nHost: target.com\r\n\r\n”)
      0
      
      
    • 前端视角:看到Transfer-Encoding: chunked。它解析第一块大小为5c(十六进制,即92字节),读取接下来的92字节,然后遇到0\r\n\r\n,认为第一个请求结束。
    • 后端视角:忽略了Transfer-Encoding,只认Content-Length: 4。它只读取请求头后的4个字节(即5c\r\n),就认为第一个请求结束了。后面那92字节的恶意数据,被它当作是下一个请求
    • 结果:走私成功。这个恶意请求(如访问/admin)会被后端处理,并可能影响到后续连接到此TCP连接的其他用户请求。

第三步:扩展与变种技术(TE.TE攻击)

  • 场景:当服务器链中,有一个服务器对Transfer-Encoding头部的处理存在缺陷时(例如,可以被混淆、重写),可以利用这种差异。
  • 构造方法:对Transfer-Encoding头部进行混淆,诱导前后端产生不同解析。
    • Transfer-Encoding: xchunked
    • Transfer-Encoding : chunked(头部名称后加空格)
    • Transfer-Encoding: chunked
      Transfer-Encoding: identity(重复头部)
    • Transfer-Encoding: x, chunked
  • 原理:前端服务器可能被某种混淆绕过,从而不采用chunked解析;而后端服务器则能正确识别chunked,反之亦然。这就在CL.TE和TE.CL之外,创造了新的解析差异点。

第四步:攻击利用场景与危害

  1. 绕过安全控制:前端WAF、防火墙可能只检查第一个“合法”请求,而将走私的恶意请求(如SQL注入、路径遍历)直接传递给后端应用。
  2. 劫持用户请求:攻击者先发送一个走私请求,然后让正常用户的请求“紧跟”其后。后端会将用户的请求行和头部,当作走私请求的“请求体”的一部分,导致用户请求被篡改或重定向,进而可能窃取用户Cookie、授权令牌。
  3. 缓存投毒:走私的请求可能是一个恶意构造的请求,其响应被前端缓存服务器缓存,污染了缓存键,导致其他用户访问时得到恶意内容(如XSS脚本)。
  4. 权限提升:走私一个访问高权限接口的请求,将其与另一个低权限用户的请求绑定,可能导致后端以高权限处理了该请求。

第五步:检测与防御策略

  1. 检测

    • 时间差法:发送一个模糊的走私请求,然后紧跟一个正常请求。如果第二个请求的响应延迟或异常,表明可能存在走私漏洞。
    • 干扰响应法:如果走私成功,第二个请求可能会得到第一个请求的响应内容。
  2. 防御(服务器端/开发运维)

    • 禁用连接重用:在后端服务器上,对来自前端的连接,处理完一个请求后立即关闭连接。但这会影响性能。
    • 使用HTTP/2:HTTP/2是二进制、分帧的协议,有明确的帧边界,天然能防御基于HTTP/1.1的请求走私。尽可能在前端与后端之间使用HTTP/2。
    • 规范化请求:前端代理应严格规范化并重新构建发往后端的请求,例如,当存在Transfer-Encoding: chunked时,强制删除Content-Length头部,并正确计算新的Content-Length
    • 使用同构服务器:确保前端和后端服务器使用同种技术栈和配置,减少解析差异。
    • 安全头部:某些WAF或服务器可以配置规则,检测和阻止畸形的Content-LengthTransfer-Encoding头部。
  3. 开发注意事项:应用层代码难以直接防御此类攻击,因为漏洞发生在网络基础设施层面。但保持应用框架、服务器、代理的最新版本,可以避免已知的解析器漏洞。

Web安全之HTTP请求走私攻击(HTTP Request Smuggling)详解 描述 HTTP请求走私是一种利用HTTP服务器对请求消息解析的差异,通过构造一个模糊的HTTP请求,来干扰请求的处理边界,从而让前端代理服务器与后端源站服务器对“请求的结束位置”和“下一个请求的开始位置”产生不同判断的攻击技术。成功利用可导致请求走私、缓存投毒、权限绕过、窃取用户请求等严重后果。 解题过程与原理详解 核心问题根源 :HTTP/1.1允许在单个TCP连接上发送多个请求,协议依靠“Content-Length”和“Transfer-Encoding”等头部来判断每个请求的边界。当前端服务器(如反向代理、CDN、WAF)与后端服务器采用不同的方式解析请求边界时,就会产生解析歧义,攻击者可精心构造一个请求,使得前端和后端看到不同的“请求组合”。 第一步:理解两种确定请求体长度的标准方法 Content-Length Content-Length: 13 明确表示请求体长度为13字节。 服务器读取完请求头后,会严格按照这个长度读取对应字节数的请求体,之后认为当前请求结束,后续数据属于下一个请求。 Transfer-Encoding: chunked 表示请求体是 分块传输 的。格式为: 服务器会一块一块地读取,直到遇到一个大小为 0 的块,标志请求体结束。 关键点 :HTTP规范规定,如果请求中同时包含 Content-Length 和 Transfer-Encoding , Transfer-Encoding 应被优先采用, Content-Length 应被 忽略 。但并非所有服务器都严格遵守此规范,或处理顺序存在差异。 第二步:认识两种经典的走私攻击技术 假设网络拓扑为: 客户端 -> 前端服务器 -> 后端服务器 。攻击者通过一个TCP连接发送恶意请求。 CL.TE走私 (前端用 Content-Length ,后端用 Transfer-Encoding ) 构造请求 : 前端视角 :看到 Content-Length: 6 。它会读取6个字节的请求体(即 0\r\n\r\nG ),之后认为 第一个请求结束 ,将剩余的字符 G 视为 下一个请求的开始 。 后端视角 :看到 Transfer-Encoding: chunked 。它开始分块解析:第一块 0\r\n 表示0字节,接着 \r\n ,于是认为 整个请求体已结束 。后面的字符 G 被当作是 下一个请求 的第一个字符。 结果 :后端将 G 解析为下一个请求的起始(例如 GET /admin HTTP/1.1 ...的一部分),实现了请求走私。如果这个“走私”的请求能影响其他用户的请求,就形成了攻击。 TE.CL走私 (前端用 Transfer-Encoding ,后端用 Content-Length ) 构造请求 : 前端视角 :看到 Transfer-Encoding: chunked 。它解析第一块大小为 5c (十六进制,即92字节),读取接下来的92字节,然后遇到 0\r\n\r\n ,认为第一个请求结束。 后端视角 :忽略了 Transfer-Encoding ,只认 Content-Length: 4 。它只读取请求头后的4个字节(即 5c\r\n ),就认为第一个请求结束了。后面那92字节的恶意数据,被它当作是 下一个请求 。 结果 :走私成功。这个恶意请求(如访问 /admin )会被后端处理,并可能影响到后续连接到此TCP连接的其他用户请求。 第三步:扩展与变种技术(TE.TE攻击) 场景 :当服务器链中,有一个服务器对 Transfer-Encoding 头部的处理存在缺陷时(例如,可以被混淆、重写),可以利用这种差异。 构造方法 :对 Transfer-Encoding 头部进行混淆,诱导前后端产生不同解析。 Transfer-Encoding: xchunked Transfer-Encoding : chunked (头部名称后加空格) Transfer-Encoding: chunked Transfer-Encoding: identity (重复头部) Transfer-Encoding: x, chunked 原理 :前端服务器可能被某种混淆绕过,从而不采用 chunked 解析;而后端服务器则能正确识别 chunked ,反之亦然。这就在CL.TE和TE.CL之外,创造了新的解析差异点。 第四步:攻击利用场景与危害 绕过安全控制 :前端WAF、防火墙可能只检查第一个“合法”请求,而将走私的恶意请求(如SQL注入、路径遍历)直接传递给后端应用。 劫持用户请求 :攻击者先发送一个走私请求,然后让正常用户的请求“紧跟”其后。后端会将用户的请求行和头部,当作走私请求的“请求体”的一部分,导致用户请求被篡改或重定向,进而可能窃取用户Cookie、授权令牌。 缓存投毒 :走私的请求可能是一个恶意构造的请求,其响应被前端缓存服务器缓存,污染了缓存键,导致其他用户访问时得到恶意内容(如XSS脚本)。 权限提升 :走私一个访问高权限接口的请求,将其与另一个低权限用户的请求绑定,可能导致后端以高权限处理了该请求。 第五步:检测与防御策略 检测 : 时间差法 :发送一个模糊的走私请求,然后紧跟一个正常请求。如果第二个请求的响应延迟或异常,表明可能存在走私漏洞。 干扰响应法 :如果走私成功,第二个请求可能会得到第一个请求的响应内容。 防御(服务器端/开发运维) : 禁用连接重用 :在后端服务器上,对来自前端的连接,处理完一个请求后立即关闭连接。但这会影响性能。 使用HTTP/2 :HTTP/2是二进制、分帧的协议,有明确的帧边界,天然能防御基于HTTP/1.1的请求走私。尽可能在前端与后端之间使用HTTP/2。 规范化请求 :前端代理应严格规范化并重新构建发往后端的请求,例如,当存在 Transfer-Encoding: chunked 时,强制删除 Content-Length 头部,并正确计算新的 Content-Length 。 使用同构服务器 :确保前端和后端服务器使用同种技术栈和配置,减少解析差异。 安全头部 :某些WAF或服务器可以配置规则,检测和阻止畸形的 Content-Length 或 Transfer-Encoding 头部。 开发注意事项 :应用层代码难以直接防御此类攻击,因为漏洞发生在网络基础设施层面。但保持应用框架、服务器、代理的最新版本,可以避免已知的解析器漏洞。