HTTP/1.1必须消亡:反同步攻击的终局

本文深入分析了HTTP/1.1协议的根本性安全缺陷,揭示了新型HTTP反同步攻击技术如何危及数百万网站安全,包括针对Akamai、Cloudflare和Netlify等核心基础设施的关键漏洞。

HTTP/1.1必须消亡:反同步攻击的终局

摘要

上游HTTP/1.1本质上不安全,定期使数百万网站面临恶意接管风险。六年的缓解尝试掩盖了问题,但未能修复它。

本文介绍了几类新型HTTP反同步攻击,能够大规模泄露用户凭证。这些技术通过详细案例研究进行演示,包括通过颠覆Akamai、Cloudflare和Netlify内部核心基础设施而暴露数千万网站的关键漏洞。

我还介绍了一个开源工具包,能够系统检测解析器差异和特定目标的弱点。该工具包与这些技术结合,在两周内产生了超过20万美元的漏洞赏金。

最终,我认为HTTP请求走私必须被认定为基本协议缺陷。过去六年证明,解决个别实现问题永远不会消除这种威胁。尽管我的发现已被报告和修补,但网站仍然默默易受未来变种攻击。这些都源于HTTP/1.1的致命缺陷,意味着微小的实现错误经常触发严重安全后果。HTTP/2+解决了这种威胁。如果我们想要安全的网络,HTTP/1.1必须消亡。

目录

  • 反同步终局
  • HTTP/1.1的致命缺陷
  • 隐藏但不修复的缓解措施
  • 意外入侵2000万个网站
  • “HTTP/1简单"及其他谎言
  • 赢得反同步终局的策略
  • 检测解析器差异
  • 理解V-H和H-V差异
  • 将V-H差异转化为CL.0反同步
  • 在ALB后利用IIS的H-V差异
  • 无Transfer-Encoding情况下利用H-V差异
  • 0.CL反同步攻击
  • 0.CL死锁
  • 超越400错误请求
  • 通过双反同步将0.CL转换为CL.0
  • 更多反同步攻击即将到来
  • 基于Expect的反同步攻击
  • 绕过响应头移除
  • 通过标准Expect的0.CL反同步 - T-Mobile
  • 通过混淆Expect的0.CL反同步 - Gitlab
  • 通过标准Expect的CL.0反同步 - Netlify CDN
  • 通过混淆Expect的CL.0反同步 - Akamai CDN
  • 防御HTTP反同步攻击
  • 为什么修补HTTP/1.1不够
  • HTTP/2相比HTTP/1有多安全
  • 如何在使用HTTP/1.1时生存
  • 如何帮助消灭HTTP/1.1
  • 结论

反同步终局

HTTP/1.1的致命缺陷

HTTP/1.1有一个致命、高度可利用的缺陷 - 单个HTTP请求之间的边界非常弱。请求只是在底层TCP/TLS套接字上简单连接,没有分隔符,并且有多种指定长度的方法。这意味着攻击者可以创建一个请求结束和下一个请求开始的极端歧义。

主要网站通常使用反向代理,将不同用户的请求通过共享连接池汇集到后端服务器。这意味着攻击者如果在服务器链中找到最微小的解析器差异,就可以导致反同步,将恶意前缀应用到其他用户的请求,通常实现完全站点接管。

由于HTTP/1.1是一个古老、宽松、基于文本的协议,有数千种实现,找到解析器差异并不难。当我在2019年首次发现这种威胁时,感觉你可以入侵任何东西。例如,我展示了它可以被利用来两次入侵PayPal的登录页面。从那时起,我们还发布了关于请求走私的免费在线课程和多个进一步的研究论文。

六年后,很容易认为我们已经通过解析器收紧和HTTP/2的组合解决了问题 - HTTP/2是一个二进制协议,如果用于从前端开始的上游连接,几乎消除了整个攻击类别。不幸的是,结果发现我们只是成功地使问题看起来已解决。

隐藏但不修复的缓解措施

在2025年,HTTP/1.1无处不在 - 但不一定在明处。服务器和CDN通常声称支持HTTP/2,但实际上将传入的HTTP/2请求降级为HTTP/1.1以传输到后端系统,从而失去了大部分安全好处。降级传入的HTTP/2消息比端到端使用HTTP/1.1更危险,因为它引入了第四种指定消息长度的方法。

HTTP/1.1乍看起来安全,因为如果你应用原始的请求走私方法和工具包,很难引起反同步。但这是为什么?让我们看看使用轻度混淆Transfer-Encoding头的经典CL.TE攻击。

如今,探测可能会失败,即使你的目标实际上易受攻击,原因有三:

  1. WAF现在使用正则表达式检测和阻止具有混淆Transfer-Encoding头的请求,或主体中的潜在HTTP请求。
  2. /robots.txt检测小工具在特定目标上不起作用。
  3. 服务器端竞争条件使这种技术在某些目标上高度不可靠。

这创造了反同步终局 - 由于玩具缓解措施和选择性硬化,你有安全的错觉,这只破坏了既定的检测方法。一切看起来安全,直到你做出最微小的改变。

事实上,HTTP/1.1实现如此密集地充满关键漏洞,你实际上可以意外找到它们。

意外入侵2000万个网站

HTTP/1.1根本不适合我们通过添加另一层来解决每个问题的世界。以下案例研究精美地说明了这一点。

Wannes Verwimp请我就他发现的影响在Heroku上托管、在Cloudflare后面的站点的问题发表意见。他发现了H2.0反同步,并能够利用它将访问者重定向到他自己的网站。

这个重定向被保存在Cloudflare的缓存中,因此通过毒化JavaScript文件的缓存条目,他能够持久控制整个网站。这一切都不足为奇,除了一件事 - 被劫持的用户并没有尝试访问目标网站。攻击实际上危害了随机的第三方站点,包括某些银行!

我同意调查并注意到其他奇怪的事情 - 攻击被Cloudflare的前端缓存阻止,意味着请求永远不会到达后端服务器。我推断这种攻击不可能工作,Wannes一定犯了错误,所以我添加了缓存破坏器…攻击失败了。当我移除缓存破坏器时,它开始工作。

通过忽略他的攻击被缓存阻止的事实,Wannes发现了Cloudflare基础设施内部的HTTP/1.1反同步。

这一发现暴露了超过24,000,000个网站完全站点接管风险!它体现了反同步终局 - 经典方法不起作用,但建立在HTTP/1上的系统如此复杂和关键,以至于你犯一个错误,最终控制2400万个网站。

我们报告了这个问题,Cloudflare在几小时内修补了它,发布了事后分析,并授予了7,000美元赏金。

“HTTP/1简单"及其他谎言

这样的错误是怎么发生的?部分原因是所涉及系统的纯粹复杂性。例如,我们可以推断,通过HTTP/2发送到Cloudflare的请求有时被重写为HTTP/1.1供内部使用,然后再次重写为HTTP/2用于上游连接!然而,根本问题是基础。

有一个广泛、危险的误解,认为HTTP/1.1是适合你可能构建的任何系统的稳健基础。特别是,没有实现反向代理的人经常认为HTTP/1.1简单,因此安全。当你尝试代理HTTP/1.1时,它变得不那么简单。为了说明这一点,这里有五个我个人曾经相信的谎言 - 每个都将对本文后面讨论的真实世界利用至关重要:

  1. HTTP/1.1请求不能直接针对中介
  2. HTTP/1.1反同步只能由解析器差异引起
  3. HTTP/1.1响应包含代理解析它所需的一切
  4. HTTP/1.1响应只能包含一个头块
  5. 完整的HTTP/1.1响应需要完整的请求

你相信哪些?你能将每个陈述映射到破坏它的特性吗?

综合起来,最后三个谎言背后的现实是,你的代理需要引用请求对象只是为了从后端TCP套接字读取正确数量的响应字节,你需要控制流分支来处理多个头块,甚至在你到达响应主体之前,整个响应可能在客户端甚至完成发送请求之前到达。

这就是HTTP/1.1 - 它是网络的基础,充满复杂性和陷阱,定期暴露数百万网站,我们花了六年时间未能修补实现来补偿它。它需要消亡。为了实现这一点,我们需要集体向世界展示HTTP/1.1不安全 - 特别是,更多反同步攻击总是即将到来。

在本文的其余部分,我希望向你展示如何做到这一点。

赢得反同步终局的策略

检测解析器差异

在反同步终局中,由于缓解措施、复杂性和怪癖,检测漏洞很困难。为了在这种环境中蓬勃发展,我们需要一种检测策略,可靠地识别使反同步攻击成为可能的根本缺陷,而不是尝试具有许多移动部件的脆弱攻击。这将使我们能够识别和克服利用挑战。

早在2021年,Daniel Thacher在黑帽欧洲会议上提出了"实用HTTP头走私”,并描述了一种使用Content-Length头检测解析器差异的方法。我非常喜欢这个概念,在我尝试了他的工具后,我决定尝试从头构建自己的实现,做略有不同的事情,看看会发生什么。

这个工具被证明非常有效,我很高兴在开源Burp Suite扩展HTTP Request Smuggler v3.0中发布它。

理解V-H和H-V差异

让我们看看真实检测,以及如何解释它。

这里,HTTP Request Smuggler检测到发送具有部分隐藏Host头的请求会导致独特响应,无法通过发送正常Host头,或完全省略头,或发送任意掩码头来触发。这是目标使用的服务器链中存在解析器差异的有力证据。

如果我们假设有前端和后端,有两个关键可能性:

可见-隐藏(V-H):掩码Host头对前端可见,但对后端隐藏 隐藏-可见(H-V):掩码Host头对前端隐藏,但对后端可见

你通常可以通过密切关注响应来区分V-H和H-V差异,并猜测它们是否源自前端或后端。注意,特定状态码不相关,有时可能令人困惑。重要的是它们是不同的。

将V-H差异转化为CL.0反同步

给定V-H差异,你可以尝试通过向后端隐藏Transfer-Encoding头来尝试TE.CL利用,或通过隐藏Content-Length头来尝试CL.0利用。我强烈建议尽可能使用CL.0,因为它被WAF阻止的可能性小得多。

利用H-V差异无Transfer-Encoding

这项研究的下一个重大突破是当我在某个网站上发现H-V差异时,该网站阻止所有包含Transfer-Encoding的请求,使CL.TE攻击不可能。这只有一个前进方向:0.CL反同步攻击。

0.CL反同步攻击

0.CL死锁

0.CL反同步攻击被广泛认为不可利用。要理解原因,考虑当你将以下攻击发送到具有H-V解析器差异的目标时会发生什么。

前端看不到Content-Length头,因此它将橙色负载视为第二个请求的开始。这意味着它缓冲橙色负载,只将头块转发到后端。

后端确实看到Content-Length头,因此它将等待主体到达。同时,前端将等待后端回复。最终,其中一个服务器将超时并重置连接,破坏攻击。本质上,0.CL反同步攻击通常导致上游连接死锁。

打破0.CL死锁

在这项研究之前,我花了两年时间探索竞争条件和定时攻击。在这个过程中,我偶然发现了0.CL死锁的解决方案。

每当我在运行nginx的目标上尝试对静态文件使用单包攻击时,nginx会在请求完成之前响应请求,从而破坏我的定时测量。当时这需要一个复杂的解决方法,但暗示了使0.CL可被利用的方法。

逃脱0.CL死锁的关键是找到早期响应小工具:一种使后端服务器响应请求而不等待主体到达的方法。这在nginx上很简单,但我的目标运行IIS,静态文件技巧在那里不起作用。那么,我们如何说服IIS响应请求而不等待主体到达?让我们看看我最喜欢的Windows文档片段:

如果你尝试使用保留名称访问文件或文件夹,操作系统将因有趣的遗留原因抛出异常。我们可以通过请求映射到文件系统的任何文件夹内的’con’来使服务器遇到这个怪癖。

我发现如果我击中目标网站上的/con,IIS会响应而不等待主体到达,并有助于保持连接打开。当与CL.0反同步结合时,这将导致它将第二个请求的开始解释为第一个请求的主体,触发400错误请求响应。

超越400错误请求

为了证明你找到了0.CL反同步,下一步是触发可控响应。在攻击请求之后,发送包含嵌套在头块内的第二个路径的"受害者"请求。

如果你正确设置第一个请求的Content-Length,它将从受害者请求中切出初始字节,你将看到指示隐藏请求行被处理的响应。

这足以证明存在0.CL反同步,但显然不是现实攻击 - 我们不能假设我们的受害者会在自己的请求中包含负载!我们需要一种将我们的负载添加到受害者请求的方法。我们需要将我们的0.CL转换为CL.0。

通过双反同步将0.CL转换为CL.0

要将0.CL转换为CL.0,我们需要双反同步!这是一个多阶段攻击,攻击者使用两个请求序列为受害者设置陷阱。

实现这一点的最干净方法是让0.CL从第一个请求切出整个头块。

不幸的是,这不像看起来那么容易。你需要知道第二个请求头块的确切大小,几乎所有前端服务器都会附加额外的头。在后端,上面的请求序列最终看起来像。

你可以使用Turbo Intruder的新0cl-find-offset脚本发现注入头的长度,但这些通常包含像客户端IP这样的东西,这意味着攻击对你有效,但当其他人尝试复制时会中断。这使得漏洞赏金分类痛苦。

经过大量痛苦,我发现了更好的方法。大多数服务器在头块末尾插入头,而不是开头。所以,如果我们的走私请求在那之前开始,攻击将可靠工作!

从这一点,我们可以使用传统的CL.0利用技术。

更多反同步攻击即将到来

在这一点上,我认为反同步威胁终于完全映射,未来问题将是利基的、一次性的实现缺陷。这是我每年犯的错误。以下是请求走私重大进展的部分历史:

  • 2004: HTTP请求走私 - (大部分被遗忘)
  • 2016: 在HTTP中隐藏伍基 (当时大部分被忽略)
  • 2019: 利用头解析器差异 (CL.TE, TE.CL)
  • 2021: 利用HTTP/2降级 (H2.CL, H2.TE)
  • 2022: 利用忽略CL的端点 (CL.0, H2.0, CSD)
  • 2024: 利用去分块 (TE.0)
  • 2025: 利用块扩展 (TE.TE)
  • 刚刚: 0.CL反同步攻击

直到下一个发现,我才最终意识到真相 - 更多反同步攻击总是即将到来。

基于Expect的反同步攻击

Expect复杂性炸弹

早在2022年,我尝试使用Expect头进行反同步攻击,但没有找到任何东西。事实证明,我没有足够努力。

这次,我首先开始使用Expect头,同时寻找一种在没有早期响应小工具的情况下检测0.CL反同步漏洞的方法。

Expect头是一种古老的优化,将发送单个HTTP请求拆分为两部分过程。客户端发送包含Expect: 100-continue的头块,服务器评估请求是否会被接受。如果服务器响应HTTP/1.1 100 Continue,客户端被允许发送请求主体。

这对客户端和服务器都很复杂,对反向代理更糟。考虑如果前端不支持Expect,或看不到头,或将值解析为100-continue会发生什么。后端呢?如果后端提前响应,或客户端不等待100-continue怎么办?

Expect头是特殊的东西的第一个明确线索是它破坏了我的Turbo Intruder工具中的HTTP客户端,在关键点,任何错误都可能导致反同步。修复客户端大大增加了代码复杂性。

Expect也破坏服务器。在一个站点上,Expect使服务器忘记HEAD响应没有主体,并尝试从后端套接字读取太多数据,导致上游死锁。

这很有趣但相对无害 - 它只构成DoS风险。其他不当行为不那么无害,例如多个服务器通过响应Expect泄露内存。

绕过响应头移除

所有HTTP/1.1响应都有一个头块 - 除非你发送Expect。因此,第二个头块经常使解析器惊讶,并破坏前端服务器移除敏感响应头的尝试。

这种技术还揭示了数百个人们试图掩码以减轻针对性利用的服务器/版本横幅。幸运的是,暴露的服务器横幅对合规性比任何关键事物更具威胁。

计划外合作

大约在这个时候,我收到了一个全职赏金猎人小队的消息 - Paolo ‘sw33tLie’ Arnolfo, Guillermo ‘bsysop’ Gregorio, 和 Mariani ‘Medusa’ Francesco。他们也注意到Expect头使有趣的事情发生。他们有扎实的研究资历 - 他们对TE.0请求走私的探索在2024年十大网络黑客技术中排名第三。因此,我们决定组队。

我们最终利用了许多许多目标。我们的发现分为四大类:

0.CL反同步通过标准Expect - T-Mobile

简单地发送有效的Expect头导致许多不同服务器上的0.CL反同步。我相信这是由前端服务器中损坏的Expect实现引起的,这使它正确转发头,但被后端的非100回复混淆,并忘记它仍然需要从客户端接收主体。

T-Mobile授予我们12,000美元用于此发现 - 对非生产域具有高度竞争力的支出。

0.CL反同步通过混淆Expect - Gitlab

发送轻度混淆的Expect头暴露大量新目标。例如,“Expect: y 100-continue"导致h1.sec.gitlab.net上的0.CL反同步。这是一个有趣的目标,因为它保存发送到Gitlab漏洞赏金程序的报告的附件 - 潜在的关键零日。

该站点攻击面很小,因此我们无法找到经典的重定向或XSS反同步小工具进行利用。相反,我们选择响应队列毒化(RQP) - 一种高影响攻击,导致服务器向每个人发送针对其他用户的随机响应。由于固有的竞争条件,RQP在低流量目标上很棘手,但我们坚持了,27,000个请求后,我们获得了其他人漏洞报告视频的访问权和7,000美元赏金。

此后,一些高端支出使我们从0.CL基于Expect的反同步攻击中赚取约95,000美元。

CL.0反同步通过标准Expect - Netlify CDN

证明它可以以各种可能的方式破坏服务器,Expect也可以导致CL.0反同步漏洞。

例如,我们在Netlify中发现了CL.0 RQP漏洞,当触发时,向我们发送来自Netlify CDN上每个网站的连续响应流。

我们在测试特定Netlify托管网站时发现了这一点,但向他们报告没有意义,因为我们劫持的响应都来自第三方网站。

攻击在我们发现后不久停止工作,但我们还是向Netlify报告了它,并收到回复"使用Netlify的网站超出范围”,没有赏金。

CL.0反同步通过混淆Expect - Akamai CDN

毫不奇怪,混淆Expect头揭示了更多CL.0反同步漏洞。

我们很快意识到这影响了使用Akamai CDN的大量目标。事实上,我相信我们可以用它来控制可能是互联网上最负盛名的域 - example.com!不幸的是,example.com没有VDP,因此验证这将是非法的。除非Akamai通知我们,我们可能永远不确定。

尽管如此,这提出了一个问题。我们应该直接向受影响公司报告问题,还是向Akamai报告?作为研究人员,与CDN及其客户保持良好关系非常重要,我赚取的任何赏金都捐给慈善机构,所以我没有个人利益。然而,我可以看到赏金猎人没有我的帮助会独立发现这个问题,并且不想破坏他们的收入。最终,我决定退出 - 我没有参与探索或报告问题,也没有分得赏金。我有点后悔,因为它最终产生了74个单独的赏金,总计221,000美元。

报告受到良好接收,但事情并非完全顺利。事实证明,漏洞实际上完全在Akamai的基础设施内部,因此Akamai被客户的支持票淹没。我担心技术在Akamai仍然易受攻击时可能泄露,并联系Akamai帮助他们更快修复。问题被分配CVE-2025-32094,我被授予9,000美元赏金。他们能够快速为一些客户发布热修复,但从那时起完全解决漏洞仍然花了65天。

总的来说,压力很大,但至少我得到了一些有美元支持的证据,证明HTTP/1.1构成的危险。从这项研究中赚取的总赏金目前略超过350,000美元。

防御HTTP反同步攻击

为什么修补HTTP/1.1不够

本文中的所有攻击都在利用实现缺陷,因此结论是放弃整个协议可能看起来奇怪。然而,所有这些攻击都有相同的根本原因。HTTP/1.1的致命缺陷 - 弱请求分离 - 意味着微小错误经常具有关键影响。这由两个关键因素复合。

首先,HTTP/1.1只有在你没有代理时才简单。RFC包含许多地雷,如指定消息长度的三种不同方式,复杂性炸弹如Expect和Connection,以及特殊情况如HEAD。这些都相互交互,以及解析器差异,创造无数关键漏洞。

其次,过去六年证明我们难以应用真正解决威胁的修补和硬化类型。在前端服务器上应用稳健验证或规范化会有帮助,但我们太害怕破坏与遗留客户端的兼容性而不敢这样做。相反,我们诉诸基于正则表达式的防御,攻击者可以轻松绕过。

所有这些因素结合意味着一件事 - 更多反同步攻击即将到来。

HTTP/2相比HTTP/1有多安全

HTTP/2不完美 - 它比HTTP/1复杂得多,并且可能难以实现。然而,上游HTTP/2+使反同步漏洞可能性大大降低。这是因为HTTP/2是二进制协议,很像TCP和TLS,对每条消息的长度零歧义。你可以预期实现错误,但给定错误实际可被利用的概率显著更低。

迄今为止在HTTP/2实现中发现的大多数漏洞是DoS缺陷,如HTTP/2 Rapid Reset - HTTP/1也有其公平份额的攻击类别。对于更严重的漏洞,你通常需要内存安全问题或整数溢出作为根本原因。再次,这些问题也影响HTTP/1.1实现。当然,总有例外 - 如CVE-2023-32731和HTTP/3连接污染 - 我期待未来看到更多针对这些的研究。

注意HTTP/2降级,前端服务器与客户端说HTTP/2但将其重写为HTTP/1.1用于上游通信,提供最小的安全好处,实际上使网站更多暴露于反同步攻击。

如何在使用HTTP/1.1时生存

如果你目前被困在上游HTTP/1.1,有一些策略你可以使用,以帮助你的网站在你能够开始使用HTTP/2之前生存不可避免的未来几轮反同步攻击。

  • 在前端服务器上启用所有可用的规范化和验证选项
  • 在后端服务器上启用验证选项
  • 避免利基Web服务器 - Apache和nginx是较低风险
  • 使用HTTP Request Smuggler执行定期扫描
  • 禁用上游连接重用 (可能影响性能)
  • 如果方法不需要主体存在,拒绝具有主体的请求 (GET/HEAD/OPTIONS)

最后,请警惕供应商声称WAF可以像上游HTTP/2一样有效阻止反同步攻击。

如何帮助消灭HTTP/1.1

现在,消灭上游HTTP/1的最大障碍是对它有多危险的认识差。希望这项研究将有所帮助,但为了产生持久差异并确保我们在六年内不在完全相同的位置,我需要你的帮助。

我们需要集体向世界展示HTTP/1.1有多破碎。尝试HTTP Request Smuggler 3.0,入侵系统并使用HTTP/2修补它们。只要可能,发布你的发现,以便我们其他人可以从中学习。不要让目标仅通过修补方法论逃脱你 - 适应和定制技术和工具,永远不满足于最新技术。它不像你想象的那么难,你绝对不需要多年的研究经验。例如,在总结这项研究时,我意识到去年发布的文章实际上描述了基于Expect的0.CL反同步,所以你可以通过阅读和应用那个来击败我这些发现!

最后,分享信息 - 更多反同步攻击总是即将到来。

结论

过去六年,我们看到HTTP/1.1中的设计缺陷定期暴露网站于关键攻击。尝试热修复个别实现未能跟上威胁步伐,唯一可行的长期解决方案是上游HTTP/2。这不是快速修复,但通过传播上游HTTP/1.1真正有多危险的意识,我们可以帮助消灭HTTP/1.1。

祝你好运!

James Kettle

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计