针对 QUIC协议的客户端请求伪造攻击
2023-5-11 19:6:11 Author: FreeBuf(查看原文) 阅读量:18 收藏

QUIC(Quick UDP Internet Connection)是谷歌制定的一种基于UDP的低时延的互联网传输层协议。随着最近的标准化和各大型科技公司的兴趣日益浓厚,QUIC 协议获得越来越多的关注。本研究对从QUIC设计中产生的客户端请求伪造攻击进行了初步分析。目前相关脚本已开源:https://github.com/yurigbur/QUICforge

本研究分析了三种请求伪造攻击模式,并了解它们如何用于协议假冒攻击和流量放大攻击。然后,探索了各个协议消息的可控攻击空间,并证明其中一种攻击模式可以用来假冒其它基于 UDP 的协议,例如 DNS 请求。尽管 QUIC 协议规范规定了反放大的限制,但对 13 个 QUIC 开源实现的评估表明,某些情况下这些缓解措施缺失或实施不充分。最后,本研究提出了缓解协议假冒的方法并讨论了 QUIC 规范中的问题。

0x01 简介

QUIC协议是传输层流抽象的创新发展。它结合了 TCP 和 TLS 1.3 的功能,以减少连接设置期间所需的往返时间 (RTT)。 它可以为已知端点实现真正的 0-RTT 连接设置,从而提高高延迟网络的性能。 在苹果、Cloudflare、Facebook、谷歌和 Mozilla 等许多知名公司的支持下,QUIC 获得了更多的关注。 如今 QUIC 非常重要,因为它被选择作为新 HTTP/3 标准的核心协议。QUIC 的广泛采用导致了 Web 协议栈变化,并催生了各种新开源实现的开发。

为了实现与互联网协议栈的兼容,QUIC 建立在 UDP 之上。在提供传输层功能的同时,QUIC 在技术上是一种应用层协议,具有自己的寻址方案。QUIC 的寻址允许底层 UDP 端口和 IP 地址发生变化,同时保持连接。QUIC 协议处理端点的迁移。为此,服务器必须将 UDP 数据报发送到未知端点。握手也是如此,其中第一条消息始终指向未验证的端点。

综上所述,QUIC 似乎特别容易受到地址欺骗和请求伪造的攻击。QUIC 规范承认漏洞并提供首要安全考虑。虽然其重要性是不可否认的,但对 QUIC 中的攻击研究仍处于起步阶段。特别是多种新实现以及新协议设计需要更深入的安全分析。

本文详细研究了 QUIC 中的客户端请求伪造,并提供了首个可行性分析。在由 QUIC 客户端(攻击者)发起请求伪造攻击时,请求伪造会导致 QUIC 服务器(受害者)发送攻击者控制的数据包。攻击者可以利用服务器在网络中的位置来获得更高的权限(例如环境权限)和访问更多的资源(例如带宽)。具体来说,本文评估了QUIC 规范中引入的两种请求伪造攻击模式,它们基于 QUIC 中的连接迁移(CMRF)和版本协商机制(VNRF)。此外,本研究还介绍了第三种请求伪造攻击方式,即利用标准握手 (SIRF) 中的服务器初始消息。它们都会导致 QUIC 服务器向目标主机发出“意外”请求。

本研究分析了 QUIC 中客户端请求伪造的可行性,主要有两个漏洞:首先是协议假冒攻击,由于请求伪造发生在传输层,它使攻击者能够伪造其他应用层协议的协议消息,类似于跨协议请求伪造。其次是流量放大攻击,攻击者可以利用伪造消息与在放大拒绝服务 (DoS) 场景中触发请求伪造所需的消息之间的大小不平衡,具体工作如下图所示。

此外,本研究还提供了可控攻击空间的分析。特别是基于版本协商的请求伪造容易受到协议假冒的影响。研究者为此提供了攻击向量的概念证明,它可以诱导受害者发送有效的 DNS 请求。本研究进一步评估了 13 个 QUIC 的开源实现,并表明它们通常容易受到至少一种请求伪造攻击模式的攻击。除了一般漏洞外,本研究还确定了规范中的缺陷,这表现为在 13 个开源实现中有 9 个不符合反放大限制。最后,讨论了如何减轻请求伪造攻击影响。

0x02 QUIC请求伪造

A. QUIC 基础知识

QUIC 的广泛采用导致了 Web 协议栈变化,如下图所示。QUIC 是一种面向连接的协议,即客户端和服务器具有一个共享状态,用于可靠地向应用程序提供数据。为了识别连接,QUIC 引入了连接 ID (CID) 作为端点标识符,以允许 UDP 端口和 IP 地址的网络路径更改。在当前版本中,CID 的长度是可变的,但不超过 20 个字节,并且不得包含任何可用于关联 CID 的信息。因此,一个连接的所有 CID 都必须随机独立生成。CID 的长度在握手中或在连接期间通过NEW_CONNECTION_ID 帧进行通信。常规数据包具有仅包含目标 CID (DCID) 的短标头格式。因此,端点需要记住相应的长度。对等点可以存储多个 CID 以供将来用于连接。

QUIC 握手(下图)结合了传输层握手和 TLS 加密握手。初始数据包类似于 TCP 的 3 次握手,而 TLS 参数在 CRYPTO 帧中“piggybacked”。握手中的所有数据包都使用长报头格式,并包含源 CID (SCID) 以及具有相应长度的 DCID。作为服务器初始数据包的替代方案,服务器可以发送包含令牌的重试数据包。此令牌必须在来自客户端的第二个初始数据包中进行镜像以验证路径。没有重试的正常握手也会隐式执行路径验证。但是通过使用重试数据包,服务器可以避免将明显更大的加密信息发送到未经验证的端点。如果服务器收到未知版本,它会用版本协商(Version Negotiation)数据包进行应答,提供支持的版本列表。版本协商数据包必须始终具有版本标识符 0x00000000 。

QUIC 的一个相当独特的功能是连接迁移(Connection Migration)。CID 的使用允许连接在连接建立后在端点地址更改后继续存在。如果服务器检测到迁移的端点,则它必须对新主机执行路径验证。为了验证路径,服务器发送一个 PATH_CHALLENGE 帧,其中包含一个必须由客户端在 PATH_RESPONSE 帧 中镜像的令牌。

B. 系统和威胁模型

当攻击者能够触发主机(受害者)向另一台主机(目标)发送一个或多个“意外”网络请求时,就会发生请求伪造攻击,这是通过滥用协议功能或滥用应用程序逻辑缺陷来实现的。本文中探讨了由客户端发起的请求伪造攻击,即客户端请求伪造。因此,客户端 - 攻击者以及服务器 - 受害者这两个词是同义词。攻击者可以利用请求伪造来实现两个目标,如下图所示。首先,利用受害者的更高权限,即内部/受限网络访问或更高权限。其次,利用从服务器到目标的更高可用带宽。

对于本研究所提出的攻击,假设攻击者能够完全控制发送给受害者的数据包的内容,包括 IP 地址和端口欺骗。虽然假设受害服务器会理解 QUIC ,但承认在各个服务器实现中可能会出现错误和故障。目标不需要能够使用 QUIC,但至少有一个 UDP 端口需要传入的数据报。虽然攻击者可能无法直接到达目标,但受害者必须能够到达它。

C. 请求伪造攻击方式

下面分别介绍三种客户端请求伪造技术,即服务器初始请求伪造(Server Initial Request Forgery,SIRF)、版本协商请求伪造(Version Negotiation Request Forgery,VNRF)和连接迁移请求伪造(Connection Migration Request Forgery,CMRF)。如无特别说明,假定上述模型成立。

1)服务器初始请求伪造(SIRF):SIRF 可能是 QUIC 中客户端最基本的请求伪造技术,然而QUIC 规范中目前并未提及所描述的技术。SIRF 攻击概念遵循下图a中描述的步骤,攻击客户端根据协议定义,使用服务器支持的版本发起与受害服务器的 QUIC 握手。但是,第一个数据包的源IP和端口是直接伪造的。因此,受害者假设新的连接尝试来自目标主机,并通过发送服务器初始数据包或重试数据包来继续握手。

2) 版本协商请求伪造(VNRF):VNRF 类似于 SIRF,但滥用了 QUIC 握手的另一种变体:如果客户端的初始数据包中包含未知版本,则 QUIC 服务器以版本协商数据包进行响应。恶意客户端可以发送一个不存在的版本标识符来可靠地触发版本协商功能。如果客户端进一步欺骗数据报的源,则版本协商被发送到目标,类似于 SIRF。整个消息流如上图b所示。

3)连接迁移请求伪造(CMRF):最后一种请求伪造技术利用了 QUIC 的连接迁移功能。服务器无法检测迁移地址是否来自客户端的真实迁移,或者源地址是否被欺骗。在这两种情况下,都会发送 PATH_CHALLENGE。这允许攻击者启动 UDP 数据报的发送,其中带有至少一个 PATH_CHALLENGE 帧的 QUIC 数据包到任意 IP 地址和端口,如上图c 所示。要执行 CMRF,攻击者需要启动新连接并按预期完成握手。服务器必须从客户端 CID 池中为新路径使用New CID。因此原始连接需要停留在初始端点上,直到服务器从客户端接收到至少一个 NEW_CONNECTION_ID 帧。当满足这些先决条件时,攻击者就会欺骗任意数据包的源地址。检测到新地址的服务器启动路径验证,从而向该地址发送 UDP 数据包。

0x03 协议假冒攻击

由于 QUIC 在技术上是一种应用层协议,因此攻击者可以通过请求伪造来攻击其他基于 UDP 的协议。如果攻击者能够控制伪造的 QUIC 数据包中足够多的数据,他可能能够模仿其他协议的数据包。虽然在文献中攻击本身也称为跨协议请求伪造 (Cross-protocol Request Forgery,CPRF) ,但在此使用术语“协议假冒”(Protocol Impersonation)来区分攻击模式(SIRF、VNRF 和 CMRF)以及可以利用的攻击向量。

数据包的未加密部分是协议假冒的主要攻击面。攻击者也可能修改加密部分的密文,但这些加密攻击将超出本文的范围。数据包的某些部分也可能会根据客户端-服务器组合、使用的版本和网络条件等因素发生变化。但是,重点在于可以在大多数环境中可靠地操作的数据。

下文分析了可控攻击空间,即与攻击方式SIRF、VNRF 和 CMRF 相关的短标头和长标头的可控位。结果表明SIRF和CMRF的可控攻击空间明显有限。然而,VNRF 的可控攻击空间足以执行协议假冒。通过协议假冒的概念证明(Proof of Concept,PoC)来演示此攻击向量,该协议假冒使用 VNRF 伪造有效的 DNS 查询。

A. 短标头中的可控位 (CMRF)

在 CMRF 攻击期间,路径挑战和可能的填充在带有短标头的数据包中传输。因此未加密和可控的数据量非常有限。下图列出了短报头数据包的详细结构。第一位表示短头格式并且是固定的。对于与定义的其他传输层协议的互操作性所需的第二位也是如此。自旋位(spin)用于被动延迟监控并施加不可预测的行为。它可以完全关闭,也可以随机关闭,以确保在网络上经常观察到禁用旋转位的连接,它不能可靠地控制。

位4和5是两个保留位,必须为零,第六位是用于识别数据包保护密钥的密钥相位。所有三个位均由服务器直接设置,不受攻击者控制。第一个字节的最后两位被解释为无符号整数,并指示 DCID 之后的数据包编号的可变长度。包含的值比数据包编号字段 的实际字节长度小1。假设只要攻击者愿意,连接就可以保持打开状态,那么在开始迁移之前,只需等待数据包数量达到某个特定值,就可以影响 CMRF 的数据包数量。数据包编号长度位直接取决于数据包编号,但只要一个值可以编码为相同数量的字节,它们就会保持不变。这些头字段的强互连和依赖性明显降低了有效的可控性。

最后一个剩余值是 DCID,它具有 0 到 20 字节之间的可变长度整数。DCID 的内容完全由客户端控制。攻击者可能会选择 20 字节的长度来最大化可控空间。作为附加限制,需要考虑发送到服务器的多个 CID 不能包含相同的值。

B. 长标头中的可控位(SIRF 和 VNRF)

SIRF 和 VNRF 使用作为 QUIC 握手一部分的消息流。因此,随着更多未加密数据的传输,这两种攻击技术都能够控制比 CMRF 可能控制的更多数据。为此,QUIC 使用长标头。虽然初始和版本协商数据包的长标头有相似之处,但也存在明显差异,将在下文中分别进行剖析。

1) 初始数据包:上图显示了初始数据包的长报头。第一位设置为 1,表示长报头格式。第二个固定位必须是 1,以允许 QUIC 与类似于短标头的其他协议共存。接下来的两位用于指示不同类型的长报头数据包。对于初始数据包,两者都设置为零,保留位也是如此。再一次,包号长度对应于包后面跟随的包号可变长度整数。它们在 SIRF 用例中不会受到影响,因为连接设置的第一条消息将包含一个新初始化的计数器。因此,攻击者无法控制标头末尾的第一个字节和两到四个字节。

数据包号长度之后的字段以四个字节对版本标识符进行编码。尽管此值是动态的并且可以由攻击者设置,但它必须是服务器理解的预定义版本以避免触发版本协商。除了极少数情况,假冒协议可以在有效负载的这个位置包含完全相同的四个字节,这些字节将不可用于假冒攻击。版本后跟源和目标的 CID。每个都将在相应的长度标识符之前。在 QUIC 握手期间,服务器将始终发送客户端选择的 DCID。如果攻击者想要最大化控制的数据量,他很可能会使用 20 字节,从而为 DCID 长度字节提供静态值 20 (0x14)。

服务器发送的SCID存在两种情况。服务器要么选择客户端在第一个初始数据包中建议的 CID,要么设置自己的 CID。第一种情况称为 SIRF+,导致 SCID 的可控字节数与 DCID 的可控字节数相同。在第二种情况下,攻击者无法控制所选的 SCID 字节和长度,从而降低了攻击的通用性。由于许多经过测试的实现为 SCID 选择静态长度,因此周围字节的位置至少保持可预测。

服务器初始数据包必须始终包含长度为零的令牌,因为令牌仅供客户端使用(例如,在接收重试数据包之后)。所以,令牌字段不存在,导致两个字段都减少为一个无法控制的零字节。最后,长度参数对剩余的数据包有效载荷长度进行编码,包括数据包编号。它的长度可能会有所不同,具体取决于有效负载内容(例如,选择的 TLS 参数)以及包含的填充。尽管如此,它也不受客户控制。

2) 版本协商包:版本协商包的结构比初始包更简单,如上图所示。和前面一样,第一位表示长报头格式。接下来的七位未在版本协商数据包中使用,并且可以由服务器设置为任意值。为了遵守 RFC 7983,未使用位的最高有效位 (MSB) 应设置为 1,尽管它是理论上唯一可以为零的 QUIC 数据包。然而,从攻击者的角度来看,整个七位对于使用 VNRF 进行协议假冒是不可控的。版本协商数据包 (0x00000000) 中的四个版本字节都设置为零。除了 CID 之外,唯一剩下的部分是一个包含受支持版本标识符的四字节值数组,攻击者无法影响它。

同样,唯一剩下的部分是 CID。虽然 20 字节的可控量对于 CMRF 和 SIRF 来说非常有限,但 CID 是专门用于版本协商的。为了允许在未来 QUIC 版本的定义中进行调整,CID 长度不限于 20 个字节。未来的 QUIC 版本可以使用八位长度标识符中可编码的全部长度,从而导致每个 CID 的最大长度为 255 字节。通过使用整个长度范围的可能性,可以完全控制 CID 长度字节。攻击者需要权衡完全控制这些字节与控制更多字节的优势。

版本协商数据包的另一个独特要求是服务器必须镜像客户端发送的 DCID 和 SCID(为了它们的目的而切换)。因此,攻击者有能力始终利用两个 CID 进行协议假冒。考虑到扩展长度字节,这导致最多 512 个可控字节,前面有 5 个字节,后面至少有 4 个不可控字节。

C. 可控攻击空间对比

分析表明,VNRF 是发起假冒攻击的最通用的方式。下图显示了所有攻击模式的完整比较。SIRF、SIRF+ 和 CMRF在制作有效载荷时有两个主要障碍。首先,20 字节的总长度(或在极少数情况下为 40 字节)不足以模仿大多数协议消息。其次,非常有限的字节范围和对数据包长度和 CID 长度的控制不足以在假冒上下文中操作有意义的字节。因此得出结论,SIRF、SIRF+ 和 CMRF 的功能明显受限于协议假冒攻击。在包括 VNRF 在内的所有情况下,攻击者都必须绕过前几个标头字节。然而,仅此还不足以防止使用 VNRF 进行假冒。

D. 基于VNRF的协议假冒攻击

作为PoC,本节的目标是制作一个数据报,该数据报可以通过 VNRF 发送到 DNS 服务器,并触发对域名 tu-berlin.de 的受害者的有效 DNS 响应。选择假冒 DNS 协议,因为它是最著名的基于 UDP 的协议之一,在大多数网络中得到广泛使用和允许,它也可以用于版本协商数据包静态部分的限制。

下图显示了带有 QUIC 解释(上)和 DNS 解释(下)的手工制作的数据包字节的开始。QUIC 数据包的第一个字节将以 1 开头,表示长标头,后跟七位随机值。该字节加上版本标识符的第一个零字节将被解释为查询 ID。版本号的下两个零字节被解释为 RFC 1035中定义的 DNS 标志。两个零字节的 DNS 标志表示标准查询没有被截断,不需要递归,这是 DNS 查询的有效标志设置。最后一个版本字节是 DNS 查询中包含的主机查询数量的第一个字节。这个静态零字节限制了查询的最大数量,但在大多数情况下,剩余的第二个字节将绰绰有余。

查询数量的第二个字节由QUIC版本协商包的DCID长度决定。对于有效负载,选择了 7 的值,以将查询中所需主机名的数量保持在最低限度,同时仍然能够跳过答案编号 (Ans)、授权记录数 (Auth) 的剩余字节和附加记录号 (Add)。对于正常查询,Ans 和 Auth 字节应该为零,并且不可用于扩展有效负载。对于标准 DNS 查询,附加记录的数量通常为零。然而,将两个 Add 字节设置为 0x0001,以处理 CID 、之后的版本协商数据包的剩余版本号标识符。

选择 DCID 长度为 7 时,SCID 长度是主机名 tuberlin.de 的第一个字节。前面的字节 0x09 标记了以下域级别的字节数。每个域级别由一个长度八位字节表示,顶级域由一个零字节终止。将 SCID 长度设置为 t (0x74) 后,还有 116 个剩余的 SCID 字节可用于剩余的有效载荷。此大小足以包含对 tuberlin.de 的整个查询。

向根域添加了六个进一步的查询,总共需要七个查询。填充的主机名可以是任意的,只需要遵守 DNS 规范。根域最适合本文需求,因为它占用的负载空间尽可能少。添加部分查询条目设置为域根 (0x00),类型和类设置为零。Add表项的长度设置为剩余SCID载荷的长度加上版本协商包中版本标识数组的长度。服务器通告的版本标识符的数量是静态的,可以通过在没有欺骗地址的情况下触发版本协商来确定。数组的长度乘以四,因为版本标识符始终是 4 字节值并且添加条目长度以字节为单位给出。Add 条目开头和版本标识符之间的剩余有效负载空间由随机字节填充。通过以描述的方式对剩余的 QUIC 有效负载进行编码,附加记录对 DNS 服务器将没有意义。然而,整个数据包字节都被覆盖了,伪造的请求是一个有效的 DNS 请求 。

上图显示了基于 VNRF 的协议假冒与上述有效载荷的数据包捕获。为了证明伪造数据包的有效性,整个 QUIC 流量(左)在 Wireshark 中解码为 DNS(右)。为了执行真正的 DNS 查询,欺骗地址被设置为 Google DNS 服务器 8.8.8.8:53。因此上图a显示了数据包类型,上图b显示了第一个报头字节和版本,上图c显示了有效载荷中的 CID。虽然初始数据包是格式错误的 DNS 数据包,但右侧窗格显示版本协商数据包确实被解释为对 tu-berlin.de 的有效 DNS 请求(上图d),并导致包含 IP 地址的有效 DNS 响应(上图e)。

这种方法可以推广到大多数域名。唯一改变的是主要查询的域名,它会影响剩余负载的长度。如果域以转换为更小字节(例如 0=0x30)的字符或数字(ASCII 格式)开头,则长度会受到限制。也就是说,如果总长度超过这个值,漏洞利用将不起作用。然而,可以假设满足这些特殊条件的域名是相当罕见的。

在攻击脚本中包含了通用的PoC,即伪造对任意域名的 DNS 请求,该脚本可以在本研究存储库(https://github.com/yurigbur/QUICforge) 中找到。唯一必须手动设置的参数是被攻击的 QUIC 服务器支持的版本数。对于 DNS 请求的协议假冒以返回域的 IP 地址,DNS 服务器必须是递归解析器或必须具有相应的缓存域条目。

上面的PoC表明,使用 VNRF 的协议假冒可以与现实世界的协议一起使用。例如,此类 DNS 查询可能被用于减少 DNS 缓存中毒攻击时间的不确定性。由于未发现的限制,为 DNS 以外的其他协议创建有效负载可能需要大量调试和手动调整才能找到有效的字节组合。如上所述,将有一些无法在现有边界内实现的有效载荷。尽管如此,通过多次迭代和创造性地利用目标协议的规范,可以制作出许多正确的数据报。但是,CMRF 和 SIRF 的额外限制使它们在协议假冒的上下文中不可行。

E. 缓解:降低可控性

由于执行请求伪造的能力源于协议设计,因此没有内在机制可以完全避免它。本研究提出以下协议更改,以降低 CMRF、SIRF 和 VNRF 有效载荷的可控性。

1) CID Reflection:服务器应该总是在握手中选择一个新的CID作为自己的DCID,这不需要改变规范。除了部署New CID 之外,服务器还应随机选择长度参数以降低有效负载放置的可预测性。长度必须保持在指定的限制内,并且必须足够大以确保 CID 有足够的熵。

当前状态下的版本协商机制对协议假冒构成了最大的威胁。虽然为未来版本的变化提供空间是可观的,即版本协商数据包中的可变 CID 长度,但该机制需要一些修改。可以依靠删除客户端提供的 DCID 的镜像。虽然这将可控字节数减半,但并不能完全缓解可控字节的问题。因此,除了不对客户端提出的DCID进行镜像之外,还进一步提出了以下的方案。

2) 基于哈希的 CID 生成:对于剩余的客户端控制的 CID,本文提出了一种机制,使服务器能够控制 DCID 的客户端控制字节。服务器可以始终(或至少对于未验证的路径)反映新提议的 CID 的单向(散列)函数的返回值。因此,客户端仍然可以影响 CID 的“随机性”,但无法再控制内容。为了利用这种安全值进行协议假冒,需要攻击者计算有效负载的逆,这对于单向函数来说是不可行的。

然而,该机制可能与基于 CID 的路由和负载平衡以及客户端控制它们的能力相冲突。部署可能需要长度一致或 CID 的某些部分将数据包路由到正确的端点。应该避免依赖静态长度或部分 CID 的机制,因为它们更容易关联连接。对于散列 CID,客户端还可以预先计算值并将其用于某些路由策略。

3) 屏蔽:另一种将控制权交给客户端的方法是屏蔽机制。Websockets中的客户端到服务器屏蔽使用了类似的方法。QUIC 标头需要通过包含屏蔽值(例如 32 位)的字段进行扩展。此掩码值由服务器随机生成,整个剩余标头与从该值生成的掩码进行异或运算。使用这种屏蔽策略,客户端仍然可以选择服务器反映的 DCID,并且如果需要,它可以根据该值进行路由和负载平衡。然而由于服务器选择了屏蔽,因此请求伪造攻击的有效负载不再由攻击者控制。目标接收到的数据将随机出现。

0x04 流量放大攻击

请求伪造攻击的另一个影响是流量放大,如果伪造的数据包大于攻击者发送的数据包,就会出现实施流量放大攻击的条件。这种放大攻击是通过带宽放大因子( Bandwidth Amplification Factor,BAF)来衡量的,通常计算如下:

QUIC 协议指定了一个反放大的限制,要求在任何未经验证的路径上发送的数据量不得超过接收数据量的三倍。为了能够直接比较通过请求伪造的放大与 QUIC 中的此限制,定义并使用路径放大因子 (Path Amplification Factor,PAF) 进行测量:

对于 SIRF,PAF 值类似于经典的 BAF 定义。对于CMRF,攻击者在握手过程中发送的数据包不在PAF中计算。要获得相应的 BAF,必须将这些字节添加到除数。

A. 扩增向量

1) 最小路径要求:QUIC规范中要求如果网络路径不能支持至少 1200 字节的最大数据报大小,则不得使用 QUIC。因此,初始数据包和包含 PATH_CHALLENGES 的数据包应填充到 1200 字节以执行路径最大传输单元发现 (PMTUD),确保路径支持足够大以支持 QUIC 的数据报。尽管要求能够传输 1200 字节的数据报,但在连接期间某些数据包实际上可能非常小。可以观察到,仅包含一个 QUIC 数据包和一个 ACK 帧的数据报小至 73 字节。如果服务器在新路径上为此类数据报发送 1200 字节的填充路径质询,则 BAF 将为 1200/73 ≈ 16.44,这违反了反放大规则。

如果在 PMTUD 要求下无法满足抗放大限制,QUIC 规范允许在没有或更少填充的情况下进行首次初始路径验证。在这种情况下,在终端是合法迁移客户端时,一旦成功验证了路径就必须执行额外的路径验证。第二个填充验证确保 PMTUD 要求也得到满足。除了填充要求外,还允许服务器在验证地址之前就已经开始向新端点发送数据。如果检查不正确,发送的数据也可能违反反放大限制。

2) 不平衡的握手大小:对于 SIRF 和 VNRF,握手机制可能被滥用。服务器必须在收到连接尝试后至少发送一个客户端初始数据包(或重试)。服务器所需的 TLS 参数(例如证书)通常大于客户端的参数。如果生成的数据报大于 3600 字节,则即使将客户端初始数据包填充到 1200 字节的大小,也无法遵守反放大限制。规范并没有明确提到一般应该如何解决这种情况。它只说明在握手期间,必须遵守反放大限制。考虑到这个问题的客户端实现可以在初始数据包中包含补充填充,以增加允许服务器发送的数据量。由于内容有限,重试和版本协商数据包总是小于客户端初始数据包,不能用于放大。

3)可靠性:通过QUIC的可靠性机制,所引入的冲突的影响会被恶化。为确保路径挑战成功,服务器可能会突然发送多个 PATH_CHALLENGE 帧。如果没有收到路径响应,服务器可能会重新发送路径挑战。如果所有这些数据包都被填充,放大问题就会增加。

对于连接的正常未确认 QUIC 数据包,有超时和重试机制(不要与 QUIC 的标记化重试混淆)。必须为服务器初始数据包禁用此机制,因为它们几乎总是与反放大限制冲突。为了避免在这种情况下出现死锁,客户端必须实施探测超时 (PTO),之后它必须发送另一条初始消息。然而如果服务器执行重试,攻击者可以放大不平衡握手大小的问题。

B. 反放大机制

原则上QUIC 规范包含所有必要的细节,以防止如上所述的流量放大攻击。然而,PMTUD 和反放大限制之间的冲突可能会成为一个问题。建议官方按如下方式重新组织和调整 QUIC规范:

1)减少路径验证和握手期间所需决策的数量:例如,路径验证总是可以分两步执行。第一个数据包将在没有填充的情况下验证路径,而第二个数据包将仅通过包含一个 PADDING 帧来确保 PMTUD 限制。

2)鼓励客户端实现将填充包含到初始数据包中:如果服务器无法在放大限制内响应客户端初始数据包,则它应该有义务发送重试以首先验证路径。

关于握手中未验证的路径,如 SIRF 中所利用的那样,规范提到重试机制是一种有效的保护措施,可防止在服务器上不必要地计算(昂贵的)密钥交换信息。虽然评估支持这一说法,并且建议使用如上所述的重试,但这种机制在大多数情况下都不是更可取的,因为它为握手引入了另一个 RTT。

0x05 评估

在本节中评估了一系列开源 QUIC 实现,特别是评估了它们对概述的攻击向量的脆弱性,从而评估它们是否充分遵守规范。首先介绍攻击设置(下图)并针对每种攻击技术评估每个服务器开源实现的漏洞。对于有放大问题的服务器,对其 PAF 值进行了详细分析。

A. 服务器选择

本研究仅使用开源软件,因为理解应用程序逻辑的能力对于检测漏洞和了解现有安全功能至关重要。这些开源实现都列在 QUIC 工作组的 GitHub(https://github.com/quicwg/base-drafts/wiki/Implementations)中。在评估中考虑了所有列出的支持 QUIC 版本 1 的开源实现。不幸的是,由于互操作性问题和实现中的错误,不得不排除一些。其余 13 个被集成到攻击设置中,如下所述。一些开源实现是实验性的或由一个小团队维护,这与其他一些由拥有大型团队的大公司开发和支持的项目形成鲜明对比。此外,有些开源实现并不是为了在生产中部署而开发的。尽管如此,确实包括了所有类别的软件,因为它们都遵守规范很重要。用于每个服务器的版本/提交在各自的 docker 容器中可用。

B. 设置和攻击实施

在客户端虚拟机 (VM) 上使用自定义 Python 攻击脚本,该脚本利用带有 NetfilterQueue 和 scapy 库的 netfilter 队列来拦截和欺骗数据包。这种方法允许在不改变源代码的情况下为任意 QUIC 客户端欺骗数据包。为了通过 QUIC 进行通信,攻击脚本主要使用版本 3.0.4 中的 lsquic HTTP 客户端。因为它为不同的设置提供了各种命令行选项。

尽管 VNRF 需要较少的互操作性设置,但需要对客户端实现进行一些额外的调整。除了集成一个不存在的版本(在例子中为 0x13371337)之外,还必须实现 CID 的扩展,最大长度为 255 字节。上述调整已经实施到 aioquic 中,因为 Python 本地处理缓冲区长度,这与基于 C 的 lsquic 实施相比最大限度地减少了编程工作。请参阅本研究GitHub 存储库以获取有关攻击设置和实施的更多信息。

在服务器 VM 上,选择在容器化 Docker 设置中运行 QUIC 服务器二进制文件,以避免包冲突并创建更灵活的设置。chromium 在容器中有一个特殊的设置,它以代理模式启动并将请求转发到一个简单的 python 后端服务器。研究者被迫偏离其他设置,因为 Chromium 测试服务器仅支持代理或缓存模式,而缓存模式在要求的参数范围内不起作用。所有服务器都以默认配置部署。Dockerfiles可以在GitHub 存储库中找到。此外还在 DockerHub(https://hub.docker.com/u/yukonsec)中提供了使用过的容器,以提供一种简单的方法来重现实验。由于大多数 QUIC 开源实现只提供 HTTP 服务器作为测试二进制文件,因此为每个服务器创建了大文件(≈700MB)。如果需要,可以请求这些文件以保持 QUIC 连接打开。客户端和服务器的限制和能力符合威胁模型。

为了更深入地了解通信,使用了Wireshark 的开发版本 (v3.7.0) 来监控服务器上的网络流量,该服务器具有与规范开发同步的最新 QUIC 数据包分析功能。如果需要,TLS 加密密钥从 lsquic 客户端导出并加载到 Wireshark 中。

C. 漏洞分析

下表显示了每种开源实现的请求伪造攻击的相关因素:每种攻击技术(Vuln)的第一列表示该开源实现是否普遍易受攻击。协议假冒和流量放大的不同影响列在三种攻击技术的其余列中。总之观察到 13 个开源实现中有 9 个容易受到 CMRF 的攻击,所有 13 个开源实现都容易受到 SIRF 和 VNRF 的攻击。

填充列 (Pad) 列出了服务器是否根据 PMTUD 的要求将包含 PATH_CHALLENGE 的第一个数据包扩大到 1200 字节。观察到执行填充到这个大小的三个开源实现。

除了填充和放大,上表列出了New CID,Ref. CID,以及 CID > 20。New CID 列指示服务器是否为新路径使用New CID。为了使用 CMRF 执行协议假冒,攻击者必须事先知道使用哪个 CID 才能将有效负载注入正确的 CID。由于 QUIC 要求没有 CID 被重复用于一个连接,因此不可能在握手和 NEW_CONNECTION_ID 帧中传输相同的有效负载。只有五个支持连接迁移的开源实现根据需要使用New CID。这本身就违反了 QUIC 规范。

如果客户端提议的 DCID 被服务器镜像,SIRF 可以控制两倍的字节。此行为的评估结果由 Ref. CID列表示。所有经过测试的开源实现都使用New CID,从而限制了可控的攻击空间。最后一列CID > 20表示服务器是否响应版本标识符未知且CID大于20的客户端初始数据包。如果服务器不接受更长的CID值,VNRF的协议假冒攻击影响会显着降低,但这样做违反了 QUIC 规范。在 13 个开源实现中,有九个响应了未知版本 0x13371337,CID 长度最多为 255 字节。

D. 流量放大分析

在本节中评估欺骗路径上发生的放大,下图中描绘了各个放大因子。对 CMRF 使用了两个 PAF 测量值。第一个值描述了仅包含单个 ACK 帧的欺骗数据包的放大。对于第二次测量,来自客户端的所有未决帧也与欺骗地址一起传输。发送将继续最多三分钟,或者直到连接被其中一个端点终止,例如,由于缺少 PATH_RESPONSE。SIRF有一个 PAF测量,因为客户端总是只发送一个初始数据包。如果其中一个 PAF 测量值超过三个反放大限制,则该开源实现在前表中被标记为易受放大影响。由于版本协商包总是小于来自客户端的初始包,因此没有对 VNRF 进行放大方面的评估。下图进一步列出了 CMRF 的实际 BAF 值,如果它们超过它们也超过了反放大限制以表明现实世界的 DoS 生存能力。

chromium、lsquic、mvfst、neqo 和 picoquic 不遵守 QUIC 对 CMRF 的抗放大限制。他们不会将响应限制为单个欺骗数据包未验证路径上数据量的三倍,从而启动连接迁移。特别是chromium、lsquic 和 mvfst 显示出高达 374.44 的显着 PAF 值。虽然 lsquic 为冗余发起多路径挑战并在初始路径挑战中执行 1200 字节填充,但 mvfst 在验证路径之前已经传输了太多的流数据。neqo 是最接近遵守规范的,首先发起一个没有填充的路径挑战,然后是一个填充的路径挑战。但是,填充的挑战会在没有等待第一个响应的情况下过早发送。因此,第二条路径挑战违反了反放大限制。

chromium 在连接迁移期间会引发非常意外的行为。它根本不发送路径挑战,而是直接开始发送流数据。这会导致两种情况下的显着放大,因为与未决确认相比,STREAM 帧很大。由于某些客户端实现的兼容性问题,路径验证默认关闭,并使用旧的 gQUIC 机制。路径验证和严格遵守放大限制都可以通过设置相应的编译标志来打开。但是这不会影响测量的放大系数,因为比较的默认配置仍然容易受到攻击。

对于同样过早发送流数据的 mvfst,观察到它也超过了反放大限制。但是,对于 chromium 和 mvfst,随着更多数据通过未决 ACK 发送,PAF 较低。当未决数据包也被发送时,其余开源实现不会发生放大,因为服务器不会为每个接收到的数据包发送额外的路径挑战。

下图比较了超过 CMRF 反放大限制的开源实现随时间发送的字节数。它表明大部分数据是在一次大爆发中启动连接迁移后直接发送的。lsquic 还传输了初始路径挑战的重试,并随着时间的推移产生小块额外数据。对于在DDoS场景中利用放大的攻击者来说,这种行为可能不太有趣。由于并非所有放大都在连接迁移启动后立即执行。

总放大的字节率绘制在上图c 中。它表明也有大量数据突发发送到目标,但随着时间的推移发送的数据并不多。即使同时发送了欺骗数据包,铬的放大也会发生延迟,它可能是代理设置的产物。延迟使得 chromium 不太适合攻击,因为与受害者的连接可能必须保持打开更长时间。

对于 SIRF,大多数开源实现都遵循反放大限制。aioquic、msquic 和 quicly 遇到了前文描述的问题,即由于 TLS 参数太大,服务器初始数据包略微超过了允许的反放大限制。mvfst 和 neqo 在 QUIC 中施加了有关可靠性的错误行为。在这些开源实现中,握手消息也存在用于正在进行的连接的标准重试机制。服务器初始数据包被多次发送,导致这三种开源实现的 PAF (BAF) 值较高。

quic-go 和 quiche 也是 SIRF 评测的特色。这两种服务器开源实现都发送重试数据包而不是服务器初始数据包,以在计算服务器初始数据包之前为新的连接尝试验证路径。重试数据包总是小于客户端初始数据包,并且不会导致放大条件。

总的来说,所有 13 种开源实现都受到至少一种请求伪造技术的影响,但各不相同。九个服务器开源实现可以通过VNRF实施协议假冒攻击。所有 13 种开源实现都容易受到这种攻击向量的影响,如果它们符合规范的话。VNRF 的强项在于它完全基于 QUIC 协议的定义。为此,本研究结果驳斥了QUIC 工作组的早期看法(https://github.com/quicwg/base-drafts/issues/3995),即请求伪造并不那么严重。QUIC 中的请求伪造会产生重大影响,接下来,本研究展示了五个开源实现中违反放大限制的情况。测得的 PAF 值高达 374.44,大大超过了抗放大极限。经测量,可用于流量放大攻击的实际 BAF 值中,chromium (CMRF) 最高为 18.28,mvfst (SIRF) 最高为 22.1。即使实际 BAF 值被其他一些协议(例如 NTP 或某些情况下的 DNS )超越,它们可能仍然非常相关。作为核心网络协议,QUIC 将随时可用并被防火墙广泛接受。这些因素使得它比其他协议更适合流量放大。

E. 基于哈希的 CID 生成

作为PoC,本工作为 aioquic 服务器实现了基于哈希的 CID 生成,用于版本协商。由于版本协商与其他消息流是分开的,因此可以在不影响其余协议的情况下更改 CID 处理。作为单向哈希函数,使用 SHAKE 海绵函数(sponge function)。由于海绵函数旨在支持可变长度,因此非常适合 QUIC CID 场景。可以生成 20 个字节的值,同时保留将来使用更长 CID 的可能性。在测试中使用了 SHAKE256,因为它是当前 SHA3 标准的基础算法之一,并且有许多库支持它。

在实验性能测试中,比较了aioquic基于os.urandom()的CID生成和hashlib.shake_256()的哈希性能。为此生成了 10,000 个 CID,将长度增加到 255 字节,并测量了计算时间。所有值的平均差异仅为 859 ns 左右。根据研究员在 aioquic 实现方面的经验,开源实现所描述机制的努力是合理的。当使用 SHA3 时,所有常见的编程语言都有支持 SHAKE256 的库。在代码库的大部分地方,当前的 CID 变量可以用散列值替换。主要区别在于原始值必须传递给初始数据包的生成和 NEW_CONNECTION_ID 帧。

F. 掩蔽

由于屏蔽需要对标头结构进行更多更改,因此不容易集成到当前的开源实现中。从开发的角度来看,这使得基于哈希的缓解方法成为有利的方法,因为它只需要对代码库进行微小的更改。然而,基于哈希的 CID 生成对 CID 的当前功能的影响比屏蔽更大。使用 CID 的某些路由和负载平衡策略变得不可能。从性能的角度来看,得出的结论是基于哈希的 CID 生成也是有利的。为此执行了基本的性能分析,使用 numpy.bitwise_xor() 函数屏蔽了一个普通大小的初始标头(50 字节)。10,000 次重复导致平均掩蔽时间为 702 ns。虽然 XOR-ing 显然比散列运算快,但它必须对每个数据包执行,而不仅仅是对少数生成的 CID。

不幸的是,这两种缓解策略都破坏了当前和新 QUIC 版本的直接互操作性。为了保持向后兼容性,服务器实现仍需要了解原始 CID 的用法,作为与旧版本协商的一部分。如果需要版本协商以对旧 QUIC 版本使用可控 CID 设计,则如上所述的 VNRF 仍然存在。放弃当前的 QUIC 版本以使协议能够抵抗请求伪造对集成和开发具有巨大的影响。

0x06 探讨

A. 网络控制

上述缓解方法专注于协议内解决方案。虽然它们可以大大减少请求伪造的影响,但它们并不能完全防止伪造的 UDP 数据报可以传输到任意主机,即使它仅包含无法控制的数据。为了通过 QUIC 完全避免基于 UDP 的请求伪造,网络运营商的唯一选择是利用强大的网络控制。一种方法是为未验证路径上的数据包部署速率限制,以减少放大向量的影响。

作为第二个措施,建议限制允许服务器访问的内部 IP 地址范围。除了限制 IP 地址外,服务器还可以维护标准化 UDP 端口的拒绝列表,以避免对基于通用 UDP 的协议的请求伪造。一般来说,应该可以阻止端口 0-1023,因为这些系统端口永远不应该用作客户端源端口。然而,网络运营商应该意识到,QUIC 中常见的有状态传输层网络控制不如基于 TCP 的协议有效。此外,许多可用的深度数据包检测工具在 QUIC 分析方面缺乏成熟度,而负载平衡工具对数据包的洞察力有限。未来关于在 QUIC 存在的情况下保护网络的研究将是广泛采用的关键。

B. 服务器端攻击

本研究的重点在于客户端攻击。作为服务器的攻击者无法利用 CMRF、SIRF 和 VNRF。连接始终由客户端发起,从而防止 SIRF 和 VNRF。CMRF 是不可能的,因为目前只允许客户端进行连接迁移。QUIC规范提到了一种同样直接源于协议设计的服务器端攻击。该技术滥用握手中的 preferred_address 参数,指定客户端在握手后迁移到的地址。对于这种方法,只有 DCID 对于协议假冒是完全可控的,类似于 CMRF 攻击技术。前文中介绍的基于哈希的 CID 生成和反放大限制也将减轻此服务器端攻击的协议假冒攻击和 DoS 攻击场景。

C. 受害者检测

正如在评估中所讨论的那样,这 13 种开源实现需要不同的客户端设置,并且影响会因目标服务器软件而异。因此,相信在未来的研究中研究服务器/受害者检测机制将是有益的。通过使用触发版本协商的客户端初始数据包扫描 IP 地址,可以有效地执行 QUIC 使用的一般识别。旨在区分各种开源实现的现有指纹识别方法主要包含来自握手的微指标,例如数据包长度、CID 长度和 CID 更改。一些评估结果可以直接集成到指纹识别机制中以提高准确性。不同的互操作性设置和对攻击场景的响应为 13 个开源实现中的每一个创建了一组分离的标识符。特别是连接迁移行为可能是对现有方法的有价值的补充。此外,握手的 TLS 参数可能是一个有效的扩展,只要它们对于开源实现来说是静态的并且管理员不可配置。随着在相同 QUIC 库上创建更多单独的 HTTP/3 服务器,QUIC 和 HTTP/3 之间的混合方法可能会得到最准确的结果。

除了对主机的 QUIC 开源实现进行一般检测外,攻击者还需要验证所识别的服务器是否处于易受攻击的环境中。研究者始终具有优势,可以全面了解攻击者、受害者和目标站点上发生的一切。在现实场景中,攻击者可能无法观察到受害者和目标。此外,评估的请求伪造攻击总是盲目的,即假冒协议的答案不会转发给客户端。

确定服务器是否易受请求伪造攻击的一种可能性是将攻击者拥有的机器作为目标。通过观察这台机器上的传入数据包,可以看到成功的攻击。然而,这样的评估并不能使攻击者评估是否存在阻止寻址其他目标 IP(例如内部 IP)的机制。但是,识别在野普遍易受攻击的服务器可能是一种有效的策略。

0x07 总结

本文分析了 QUIC 中客户端请求伪造攻击的可行性,此类请求伪造攻击策略会对网络安全产生重大影响。被分析的攻击方法包括基于握手的服务器初始请求伪造(SIRF)、版本协商请求伪造(VNRF)以及基于连接迁移机制的连接迁移请求伪造(CMRF)。此外,本研究构建了一个自定义测试环境,评估了13 种不同的 QUIC 服务开源实现的攻击向量。结果表明,所有服务器都受到至少一种请求伪造技术的影响。

QUIC 是改进 Web 网络堆栈的更有前途的方法之一。然而,该协议的某些功能是全新的概念,尚未经过充分审查以确保它们符合有关其安全属性的声明。因此,在建议广泛采用之前,有必要对 QUIC 进行进一步的安全研究。

参考资料:

https://www.ndss-symposium.org/ndss-paper/quicforge-client-side-request-forgery-in-quic/
精彩推荐


文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NjA0NjgyMA==&mid=2651224297&idx=3&sn=7f4e460174d48ac7c6012e8efa0515ac&chksm=bd1dea628a6a637453c12521fcb90ed6d43087a1cd47331fe9d964971ea31c8882de0bd1fc3e#rd
如有侵权请联系:admin#unsafe.sh