HTTP逐跳请求头滥用

本节涵盖了通过滥用HTTP/1.1逐跳(hop-by-hop)头来以意外方式影响Web系统和应用程序的技术。受这些技术影响的系统可能在请求到达服务器应用程序之前有多个处理请求的缓存/代理。

逐跳请求头

规范 RFC 2612 定义了两种类别的HTTP头:

  • 端到端头(End-to-end headers):传输到请求或响应的最终接收者。响应中的端到端头必须作为缓存条目的一部分存储,并且必须在从缓存条目形成的任何响应中传输。

  • 逐跳头(Hop-by-hop headers):仅对单个传输级连接有意义,不被缓存存储或被代理转发。

换句话说,逐跳头设计为由当前处理请求的代理服务器处理和使用,与端到端头不同,端到头头设计为在请求中存在直到请求结束。

规范 RFC 2612 默认将以下头定义为逐跳头:

  • Keep-Alive

  • Transfer-Encoding

  • TE

  • Connection

  • Trailer

  • Upgrade

  • Proxy-Authorization

  • Proxy-Authenticate

HTTP/1.1定义的所有其他头都是端到端头。

如果在请求中找到逐跳头,兼容的代理服务器应该处理或执行操作,而不考虑这些头指示什么,并且不将它们转发到下一跳。

请求还可以通过将头添加到 Connection 头来定义自定义头集作为逐跳头,如下所示:

Connection: close, X-Foo, X-Bar

客户端要求代理服务器将 X-FooX-Bar 视为逐跳头,这意味着客户端希望代理在发送请求之前从请求中删除它们。

滥用HTTP逐跳请求头

Connection 头本身是默认的逐跳头。这意味着兼容的代理服务器在转发请求时不应该在其 Connection 头中将自定义逐跳头列表转发到链中的下一个服务器。然而,在实践中这并不总是发生,一些系统要么转发整个 Connection 头,要么复制逐跳列表并将其添加到他们自己的 Connection 头中。例如,HAProxy很可能原样传递 Connection 头,Nginx在反向代理模式下也有相同的行为。

下图显示了如果后端期望 X-Important-Header 并在逻辑决策中考虑其存在时,滥用逐跳头如何可能导致问题。

验证系统是否容易受到某种滥用逐跳请求头影响的快速简便方法是使用需要身份验证的端点的 Cookie 头(假设目标系统使用Cookie身份验证)。例如,让我们假设 /api/users/profile 端点返回 200 OK 以及关于用户的信息。在这种情况下,如果系统易受攻击,以下请求可能返回与预期不同的响应:

GET /api/users/profile HTTP/1.1
Host: vulnerable-website.com
Cookie: sessionid=...
Connection: close, Cookie

要搜索更有趣的效果,您可以使用Burp Suite Intruder或带有已知头列表的自定义脚本,比如这个列表

绕过身份验证或访问控制决策

如果应用程序在进行身份验证/授权决策时依赖任何头的存在/不存在,滥用逐跳头可用于绕过此类实现。

缓存中毒DoS

这种情况下的影响与通常的Cache Poisoning DoS实现的效果非常相似。然而,在这种情况下,方法略有不同——不是直接使用或修改创建不需要的应用程序状态并毒化Web缓存的请求头,而是使用逐跳头来创建这种不需要的状态并删除应用程序正常功能所依赖的头。

要利用缓存中毒DoS,需要:

  1. 前端缓存转发自定义的逐跳头集,而不是处理它们。

  2. 链中的任何中间代理处理自定义集并删除头。

  3. 应用程序考虑这些头的存在,如果它们不存在,返回不需要的响应,例如 400 Bad Request501 Not Implemented

结果,应用程序之前的Web缓存将缓存此不需要的响应并返回给其他用户。

服务指纹识别

当寻找逐跳头时,寻找服务器发送响应中的差异。删除特定于技术或特定于堆栈的HTTP头可能导致各种副作用,允许收集有关应用程序的更多信息。头越具体,应用程序的指纹越准确。

掩盖源IP地址

当前端代理服务器接受用户请求时,它可以将用户的IP地址添加到 X-Forwarded-For 头,以便后端知道用户的IP地址。但是,如果您告诉代理 X-Forwarded-For 头是逐跳头,它将从请求中删除该头。因此后端要么永远不会收到用户的IP地址,要么收到链中其他元素的IP地址。

请记住,X-Forwarded-For 头不是传输用户IP地址的唯一头。ForwardedX-Real-IP 等也可以使用。

参考资料

最后更新于