75

我正在研究 websocket 实现,但不知道框架中的掩码是什么意思。

有人可以解释一下它的作用以及为什么推荐它吗?

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-------+-+-------------+-------------------------------+
 |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
 |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
 |N|V|V|V|       |S|             |   (if payload len==126/127)   |
 | |1|2|3|       |K|             |                               |
 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
 |     Extended payload length continued, if payload len == 127  |
 + - - - - - - - - - - - - - - - +-------------------------------+
 |                               |Masking-key, if MASK set to 1  |
 +-------------------------------+-------------------------------+
 | Masking-key (continued)       |          Payload Data         |
 +-------------------------------- - - - - - - - - - - - - - - - +
 :                     Payload Data continued ...                :
 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
 |                     Payload Data continued ...                |
 +---------------------------------------------------------------+
4

3 回答 3

77

Websockets 在 RFC6455 中定义,在第 5.3 节中声明:

屏蔽密钥的不可预测性对于防止恶意应用程序的作者选择出现在线路上的字节至关重要。

一篇关于 Websockets 的博客文章中,我找到了以下解释:

掩码密钥(32 位):如果设置了掩码位(相信我,如果您为服务器端编写代码),您可以在此处读取用于对有效负载进行异或运算的无符号字节。它用于确保来自客户端的攻击者不会滥用糟糕的代理

但我在邮件列表存档中找到的最清楚的答案。约翰·坦普林在那儿说:

基本上,WebSockets 的独特之处在于您需要保护网络基础设施,即使您在客户端运行恶意代码、对服务器的完全恶意控制,并且您可以信任的唯一部分是客户端浏览器。 通过让浏览器为每一帧生成一个随机掩码,恶意客户端代码无法选择出现在网络上的字节模式并使用它来攻击易受攻击的网络基础设施

正如 kmkaplan 所述,攻击向量在 RFC的第 10.3 节中进行了描述。
这是防止代理缓存中毒攻击的一种措施1。它的作用是创造一些随机性。您必须使用随机掩码密钥对有效负载进行异或。

顺便说一句:不只是推荐。这是强制性的。

1:见Huang、Lin-Shung 等人。“为了乐趣和利益而自言自语。” W2SP 论文集 (2011)

于 2013-01-05T17:30:29.037 回答
18

这篇文章

需要屏蔽从客户端到服务器的 WebSocket 流量,因为恶意代码不太可能导致一些损坏的代理做错事并将其用作某种攻击。没有人证明这实际上会发生,但由于它可能发生的事实足以让浏览器供应商感到紧张,因此添加了屏蔽以消除它被用作攻击的可能性。

因此,假设攻击者能够破坏在浏览器和后端服务器中执行的 JavaScript 代码,屏蔽旨在防止这两个端点之间发送的字节序列以可能破坏任何损坏代理的特殊方式制作在这两个端点之间(通过破坏,这意味着代理可能会尝试将 websocket 流解释为 HTTP,而实际上它们不应该)。

浏览器(而不是浏览器中的 JavaScript 代码)对用于发送消息的随机生成的掩码拥有最终决定权,这就是为什么攻击者不可能知道代理可能会看到的最终字节流的原因。

请注意,如果您的 WebSocket 流已加密(应该如此),则掩码是多余的。Python的Flask作者的文章:

为什么会有遮罩?因为显然那里有足够多的损坏的基础设施,可以让升级标头通过,然后将其余连接作为第二个 HTTP 请求处理,然后将其填充到缓存中。我对此无话可说。无论如何,对此的防御基本上是一个强大的 32 位随机数作为掩码密钥。或者你知道……使用 TLS 而不要使用糟糕的代理。

于 2015-08-29T20:22:49.347 回答
8

我一直在努力理解 WebSocket 掩码的用途,直到我遇到以下两个可以清楚地总结它的资源。

摘自《高性能浏览器网络》一书:

所有客户端发起的帧的有效负载都使用帧头中指定的值进行屏蔽:这可以防止在客户端上执行的恶意脚本对可能不理解 WebSocket 协议的中介执行缓存中毒攻击。

由于中介(例如透明代理)并不总是理解 WebSocket 协议,因此恶意脚本可以利用它并创建导致这些中介中的缓存中毒的流量。

但是怎么做?

文章为乐趣和利润自言自语 ( http://www.adambarth.com/papers/2011/huang-chen-barth-rescorla-jackson.pdf ) 进一步解释了缓存中毒攻击的工作原理:

  1. 攻击者的 Java 小程序打开一个到攻击者.com:80 的原始套接字连接(和以前一样,攻击者还可以通过托管适当的策略文件来授权此请求的 SWF 来发起类似的攻击)。
  2. 攻击者的 Java 小程序通过伪造的 Host 标头通过套接字发送字节序列,如下所示: GET /script.js HTTP/1.1 主机:target.com
  3. 透明代理将字节序列视为 HTTP 请求,并根据原始目标 IP 将请求路由到攻击者的服务器。
  4. 攻击者的服务器在很远的将来使用带有 HTTP Expires 标头的恶意脚本文件进行回复(以指示代理尽可能长时间地缓存响应)。
  5. 由于代理基于 Host 标头进行缓存,因此代理将恶意脚本文件存储在其缓存中为http://target.com/script.js,而不是 http://attacker.com/script.js
  6. 将来,每当任何客户端通过代理请求http://target.com/script.js时,代理都会提供恶意脚本的缓存副本。

在此处输入图像描述

这篇文章还进一步解释了 WebSockets 如何在缓存中毒攻击中发挥作用:

考虑一个中介检查浏览器和攻击者服务器之间交换的数据包。如上所述,客户端请求 WebSockets 并且服务器同意。此时,客户端可以在通道上发送它想要的任何流量。不幸的是,中介不知道 WebSockets,所以最初的 WebSockets 握手看起来就像一个标准的 HTTP 请求/响应对,请求像往常一样被一个空行终止。因此,客户端程序可以注入看起来像 HTTP 请求的新数据,并且代理可以这样对待它。因此,例如,他可能会注入以下字节序列:GET /sensitive-document HTTP/1.1 Host: target.com

当中介检查这些字节时,它可能会得出结论,这些字节表示同一套接字上的第二个 HTTP 请求。如果中介是透明代理,中介可能会根据伪造的 Host 头路由请求或缓存响应。

在上面的示例中,恶意脚本利用了中间人不理解的 WebSocket 并“毒化”了它的缓存。下次有人要求时sensitive-documenttarget.com他们将收到攻击者的版本。如果该文档用于谷歌分析,想象一下攻击的规模。

总而言之,通过在有效载荷上强制使用掩码,这种中毒是不可能的。中介的缓存条目每次都会不同。

于 2020-11-12T17:36:30.733 回答