WebSocket 框架中的掩码是啥?
Posted
技术标签:
【中文标题】WebSocket 框架中的掩码是啥?【英文标题】:What is the mask in a WebSocket frame?WebSocket 框架中的掩码是什么? 【发布时间】:2012-12-19 21:32:26 【问题描述】:我正在研究 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 ... |
+---------------------------------------------------------------+
【问题讨论】:
【参考方案1】:Websockets 在 RFC6455 中定义,在 Section 5.3 中声明:
掩码键的不可预测性是 防止恶意应用程序的作者选择 出现在线路上的字节。
在blog entry about Websockets我找到了以下解释:
masking-key(32 位):如果设置了掩码位(相信我,这是为服务器端编写的),您可以在此处读取用于对有效负载进行异或运算的无符号字节。 用于确保客户端的攻击者不会滥用糟糕的代理。
但我在mailing list archive 中找到了最清楚的答案。 John Tamplin 说:
基本上,WebSockets 的独特之处在于您需要保护网络 基础设施,即使你有恶意代码在客户端运行,完整的 对服务器的恶意控制,你唯一可以信任的就是 客户端浏览器。 通过让浏览器为每个 帧,恶意客户端代码无法选择出现的字节模式 在线上并使用它来攻击易受攻击的网络基础设施。
正如 kmkaplan 所述,攻击向量在 RFC 的 Section 10.3 中进行了描述。 这是一种防止代理缓存中毒攻击的措施1。 它的作用是创造一些随机性。您必须使用随机掩码密钥对有效负载进行异或。
顺便说一句:不只是推荐。这是强制性。
1:见Huang, Lin-Shung, et al. "Talking to yourself for fun and profit." Proceedings of W2SP (2011)
【讨论】:
感谢您的出色回答。但是被滥用的代理不能仍然取消屏蔽框架吗? 解释本身是在 RFC 6455 第 10.3 节。对基础设施的攻击(屏蔽) 我仍然完全不知道这种掩蔽技术试图阻止什么。如果我知道代理容易受到某个字节序列的攻击,我可以实现我自己的 TCP 服务器和客户端来利用它。 @pwuertz:但你不能通过在页面中包含恶意 javascript 来导致这种情况发生在倒霉用户的机器上,对吗? 这有点荒谬——任何“真正的”黑客都不会通过编写在浏览器中运行的 Javascript 代码来尝试执行缓存中毒攻击。采用非浏览器 WebSocket 库并将其修改为使用固定的掩码键是非常简单的,从而使您的代码能够通过网络发送您想要的任何字节(只需使用掩码键对字节进行预异或,然后libary 会将其异或返回到您想要在线上的任何内容)。尽管任何“真正的”代理都应该意识到连接使用 WebSocket 帧,并且不应该尝试将数据解析为其他任何东西。【参考方案2】:来自this article:
需要屏蔽从客户端到服务器的 WebSocket 流量,因为恶意代码不太可能导致一些损坏的代理做错事并将其用作某种攻击。没有人证明这真的会发生,但由于它可能发生的事实足以让浏览器供应商感到紧张,因此添加了屏蔽以消除它被用作攻击的可能性。
因此,假设攻击者能够破坏在浏览器和后端服务器中执行的 JavaScript 代码,掩码旨在防止以可能破坏的特殊方式在这两个端点之间发送的字节序列这两个端点之间的任何损坏的代理(损坏的意思是代理可能会尝试将 websocket 流解释为 HTTP,而实际上它们不应该)。
浏览器(而不是浏览器中的 JavaScript 代码)对用于发送消息的随机生成的掩码拥有最终决定权,这就是为什么攻击者无法知道代理可能会看到的最终字节流的原因是。
请注意,如果您的 WebSocket 流已加密(应该如此),则掩码是多余的。 Article来自Python的Flask作者:
为什么会有遮罩?因为显然那里有足够多的损坏的基础设施,可以让升级标头通过,然后将其余连接作为第二个 HTTP 请求处理,然后将其填充到缓存中。我对此无话可说。无论如何,对此的防御基本上是一个强大的 32 位随机数作为掩码密钥。或者你知道……使用 TLS 而不要使用糟糕的代理。
【讨论】:
【参考方案3】:我一直在努力理解 WebSocket 掩码的用途,直到我遇到以下两个资源来清楚地总结它。
摘自《高性能浏览器网络》一书:
使用帧头中指定的值屏蔽所有客户端发起的帧的负载:这可以防止在客户端上执行的恶意脚本对可能不理解 WebSocket 协议的中介执行缓存中毒攻击。
由于中介(例如透明代理)并不总是理解 WebSocket 协议,因此恶意脚本可以利用它并在这些中介中创建导致缓存中毒的流量。
但是怎么做呢?
为乐趣和利润自言自语 (http://www.adambarth.com/papers/2011/huang-chen-barth-rescorla-jackson.pdf) 文章进一步解释了缓存中毒攻击的工作原理:
攻击者的 Java 小程序打开一个到攻击者.com:80 的原始套接字连接(和以前一样,攻击者也可以通过 SWF 挂载一个 通过托管适当的策略文件来授权类似的攻击 请求)。 攻击者的 Java 小程序通过使用伪造的 Host 标头制作的套接字发送字节序列,如下所示:GET /script.js HTTP/1.1 主机:target.com 透明代理将字节序列视为HTTP请求,并根据原始目标IP路由请求, 那是攻击者的服务器。 攻击者的服务器回复带有 HTTP Expires 标头的恶意脚本文件在很远的将来(指示代理缓存 尽可能长时间的响应)。 由于代理缓存基于Host头,代理存储恶意 缓存中的脚本文件为http://target.com/script.js,而不是 http://attacker.com/script.js. 将来,只要有任何客户端 通过代理请求http://target.com/script.js,代理将 提供恶意脚本的缓存副本。
本文还进一步解释了 WebSockets 如何在缓存中毒攻击中发挥作用:
考虑一个中间人检查浏览器和攻击者服务器之间交换的数据包。如上,客户端请求 WebSockets 和服务器同意。此时,客户端可以发送 它想要在频道上的任何流量。可惜中介 不知道 WebSockets,所以最初的 WebSockets 握手 看起来就像一个标准的 HTTP 请求/响应对,带有 像往常一样,请求被空行终止。因此,客户端 程序可以注入看起来像 HTTP 请求的新数据,并且 代理可能会这样对待它。因此,例如,他可能会注入 以下字节序列:
GET /sensitive-document HTTP/1.1
Host: target.com
当中介检查这些字节时,它可能会得出结论: 这些字节表示同一套接字上的第二个 HTTP 请求。如果 中介是透明代理,中介可能会路由 根据伪造的Host头请求或缓存响应。
在上面的例子中,恶意脚本利用了中间人不理解的 WebSocket 并“毒化”了它的缓存。下次有人向target.com
请求sensitive-document
时,他们将收到攻击者的版本。如果该文档用于 google-analytics,请想象一下攻击的规模。
总而言之,通过在有效负载上强制使用掩码,这种中毒是不可能的。中介的缓存条目每次都会不同。
【讨论】:
以上是关于WebSocket 框架中的掩码是啥?的主要内容,如果未能解决你的问题,请参考以下文章