我正在开发一个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 ... |
+---------------------------------------------------------------+
答案 0 :(得分:53)
Websockets在RFC6455中定义,在Section 5.3中声明:
屏蔽键的不可预测性是 防止恶意应用程序的作者选择的必要条件 线上出现的字节。
在blog entry about Websockets中,我找到了以下解释:
masking-key(32位):如果设置了掩码位(并且相信我,如果你为服务器端写的话),你可以在这里读取无符号字节,这些字节用于与有效负载进行xor。 它用于确保来自客户端的攻击者不会滥用糟糕的代理。
但是我在mailing list archive找到的答案最明确。约翰坦普林说:
基本上,WebSockets的独特之处在于您需要保护网络 基础设施,即使你在客户端运行恶意代码,也是完整的 对服务器的恶意控制,唯一值得信赖的是 客户浏览器。 让浏览器为每个浏览器生成一个随机掩码 框架,恶意客户端代码无法选择出现的字节模式 在线上并使用它来攻击易受攻击的网络基础设施。
正如kmkaplan所述,攻击向量在RFC的Section 10.3中描述 这是一种防止代理缓存中毒攻击的措施(请参阅Paper about the attack)。 它的作用是创造一些随机性。您必须使用随机屏蔽密钥对有效负载进行异或。
顺便说一下:不仅仅是推荐。这是强制性。
答案 1 :(得分:12)
来自this article:
需要屏蔽从客户端到服务器的WebSocket流量,因为恶意代码不太可能导致某些损坏的代理执行错误操作并将其用作某种攻击。没有人证明这可能实际发生,但由于它可能发生的事实足以让浏览器供应商变得抽搐,因此增加了屏蔽以消除它被用作攻击的可能性。
因此,假设攻击者能够同时破坏在浏览器和后端服务器中执行的JavaScript代码,屏蔽旨在防止在这两个端点之间发送的字节序列以特殊方式制作,可能会中断这两个端点之间的任何破坏的代理(通过破坏,这意味着可能尝试将websocket流解释为HTTP的代理,实际上它们不应该)。
浏览器(而不是浏览器中的JavaScript代码)对用于发送消息的随机生成的掩码有最终决定权,这就是为什么攻击者无法知道最终的字节流是什么的代理可能会看到。
请注意,如果您的WebSocket流已加密(应该是),则掩码是多余的。来自Python's Flask的作者的Article:
为什么要屏蔽?因为显然有足够的基础架构可以让升级标头通过,然后将剩余的连接作为第二个HTTP请求处理,然后将其填入缓存。我对此没有任何言论。在任何情况下,对此的防御基本上是一个强大的32位随机数作为掩蔽密钥。或者你知道......使用TLS并且不要使用糟糕的代理。
答案 2 :(得分:2)
我一直难以理解WebSocket掩码的用途,直到遇到以下两个清楚地概述了它的资源。
摘自《高性能浏览器网络》一书:
使用帧头中指定的值屏蔽所有客户端启动的帧的有效负载:这可以防止在客户端执行的恶意脚本对可能不了解WebSocket协议的中介执行缓存中毒攻击。
由于WebSocket协议并不总是被中介程序(例如透明代理)所理解,因此恶意脚本可以利用它,并在这些中介程序中创建导致缓存中毒的流量。
但是如何?
文章自言自语以获取乐趣和收益(http://www.adambarth.com/papers/2011/huang-chen-barth-rescorla-jackson.pdf)进一步说明了缓存中毒攻击的工作原理:
- 攻击者的Java小程序打开了一个指向Attacker.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,代理将 提供恶意脚本的缓存副本。
本文还进一步说明了WebSocket如何在缓存中毒攻击中出现:
考虑由中介机构检查浏览器与攻击者服务器之间交换的数据包。如上所述,客户要求 WebSockets和服务器同意。此时,客户端可以发送 频道上想要的任何流量。不幸的是,中介 不知道WebSockets,所以最初的WebSockets握手 看起来像是标准的HTTP请求/响应对, 与往常一样,请求由空行终止。因此,客户 程序可以注入看起来像HTTP请求的新数据,并且 代理可以这样对待。因此,例如,他可能会注入 以下字节序列:
GET /sensitive-document HTTP/1.1
Host: target.com
当中介检查这些字节时,可能会得出以下结论: 这些字节表示同一套接字上的第二个HTTP请求。如果 中介是透明代理,中介可能会路由 请求或根据伪造的Host标头缓存响应。
在上面的示例中,恶意脚本利用了中介无法理解的WebSocket的优势,并“毒化”了其缓存。下次有人从sensitive-document
请求target.com
时,他们将收到攻击者的版本。想象一下,如果该文档适用于google-analytics,那么攻击的规模。
总而言之,通过在有效负载上加一个掩码,这种中毒是不可能的。中介的缓存条目每次都会不同。