本文为 WebSocket 协议的第九章,本文翻译的主要内容为 WebSocket 安全性相关内容。html
这一章描述了一些 WebSocket 协议的可用的安全性考虑。这一章的小节描述了这些特定的安全性考虑。算法
WebSocket 协议防止在受信任的应用例如 Web 浏览器中执行的恶意 JavaScript 代码,例如经过检查Origin
头字段(见下面)。见第 1.6 节去了解更多详情。这种假设在更有能力的客户端的状况下不成立。浏览器
这个协议能够被网页中的脚本使用,也能够经过宿主直接使用。这些宿主是表明本身的利益的,所以能够发送假的Origin
头字段来欺骗服务端。所以服务端对于他们正在和已知的源的脚本直接通讯的假设须要消息,而且必须认为他们可能经过没有预期的方式访问。特别地,服务端不该该相信任何输入都是有效的。缓存
示例:若是服务端使用输入的内容做为一部分的 SQL 查询语句,全部的输入文本都必须在传递给 SQL 服务器时进行编码,以避免服务端受到 SQL 注入攻击。安全
只处理特定站点,不打算处理任何 Web 页面的数据服务器应该验证Origin
字段是不是他们预期的。若是服务端收到的源字段是不接受的,那么他应该经过包含 HTTP 禁止状态码为 403 的请求响应做为 WebSocket 握手的响应。服务器
当不信任的一方是 JavaScript 应用做者并存在受信任的客户端中运行时,Origin
字段能够避免出现这种攻击的状况。客户端能够链接到服务端,经过协议中的Origin
字段,肯定是否开放链接的权限给 JavaScript 应用。这么作的目的不是组织非浏览器应用创建链接,而是保证在受信任的浏览器中可能运行的恶意 JavaScript 代码并不会构建一个假的 WebSocket 握手。网络
除了终端可能会成为经过 WebSocket 被攻击的目标以外,网络基础设施的另一部分,例如代理,也有多是攻击的对象。app
这个协议发展后,经过一个实验验证了部署在外部的缓存服务器因为一系列在代理上面的攻击致使投毒。通常形式的攻击就是在攻击者控制下创建一个与服务端的链接,实现一个与 WebSocket 协议创建链接类似的 HTTP UPGRADE 链接,而后经过升级之后的链接发送数据,看起来就像是针对已知的特定资源(在攻击中,这可能相似于普遍部署的脚本,用于跟踪广告服务网络上的点击或资源)进行 GET 请求。远端服务器可能会经过一些看上去像响应数据的来响应假的 GET 请求,而后这个响应就会按照非零百分比的已部署中介缓存,所以致使缓存投毒。这个攻击带来的影响就是,若是一个用户能够正常的访问一个攻击者控制的网网站,那么攻击者能够针对这个用户进行缓存投毒,在相同缓存的后面其余用户会运行其余源的恶意脚本,破坏 Web 安全模型。测试
为了不对中介服务的此类攻击,使用不符合 HTTP 的数据帧中为应用程序的数据添加前缀是不够的,咱们不可能详细的检查和测试每个不合标准的中介服务有没有跳过这种非 HTTP 帧,或者对帧载荷处理不正确的状况。所以,采用的防护措施是对客户端发送给服务端的全部数据添加掩码,这样的话远端的脚本(攻击者)就不可以控制发送的数据如何出如今线路上,所以就不可以构造一条被中介误解的 HTPT请求。网站
客户端必须为每一帧选择一个新的掩码值,使用一个不可以被应用预测到的算法来进行传递数据。例如,每个掩码值能够经过一个加密强随机数生成器来生成。若是相同的值已经被使用过或者已经存在一种方式可以判断出下一个值如何选择时,攻击这个能够发送一个添加了掩码的消息,来模拟一个 HTTP 请求(经过在线路上接收攻击者但愿看到的消息,使用下一个被使用的掩码值来对数据进行添加掩码,当客户端使用它时,这个掩码值能够有效地反掩码数据)。
当从客户端开始传递第一帧时,这个帧的有效载荷(应用程序提供的数据)就不可以被客户端应用程序修改,这个策略是很重要的。不然,攻击者能够发送一个都是已知值(例如所有为 0)的初始值的很长的帧,计算收到第一部分数据时使用过的掩码,而后修改帧中还没有发送的数据,以便在添加掩码时显示为 HTTP 请求。(这与咱们在以前的段落中描述的使用已知的值和可预测的值做为掩码值,其实是相同的问题。)若是另外的数据已经发送了,或者要发送的数据有所改变,那么新的数据或者修改的数据必须使用一个新的数据帧进行发送,所以也须要选择一个新的掩码值。简短来讲,一旦一个帧的传输开始后,内容不可以被远端的脚本(应用)修改。
受保护的威胁模型是客户端发送看似HTTP请求的数据的模型。所以,从客户端发送给服务端的频道数据须要添加掩码值。从服务端到客户端的数据看上去像是一个请求的响应,可是,为了完成一次请求,客户端也须要能够伪造请求。所以,咱们不认为须要在双向传输上添加掩码。(服务端发送给客户端的数据不须要添加掩码)
尽管经过添加掩码提供了保护,可是不兼容的 HTTP 代理仍然因为客户端和服务端之间不支持添加掩码而受到这种类型的攻击。
在从多个帧从新组装后,对于帧大小或总消息大小具备实现和必须避免本身超过相关的多平台特定限制带来的影响。(例如:一个恶意的终端可能会尝试耗尽对端的内存或者经过发送一个大的帧(例如:大小为 2 ** 60)或发送一个长的由许多分片帧构成的流来进行拒绝服务攻击)。这些实现应该对帧的大小和组装事后的包的总大小有必定的限制。
这个协议在 WebSocket 握手时,没有规定服务端可使用哪一种方式进行认证。WebSocket 服务器可使用任意 HTTP 服务器通用的认证机制,例如: Cookie、HTTP 认证或者 TLS 认证。
链接保密性是基于运行 TLS 的 WebSocket 协议(wss 的 URLs)。WebSocket 协议实现必须支持 TLS,而且应该在与对端进行数据传输时使用它。
若是在链接中使用 TLS,TLS带来的链接的收益很是依赖于 TLS 握手时的算法的强度。例如,一些 TLS 的加密算法不提供链接保密性。为了实现合理登记的保护措施,客户端应该只使用强 TLS 算法。“Web 安全:用户接口指南”(W3C.REC-wsc-ui-20100812)讨论了什么是强 TLS 算法。RFC5246 的附录 A.5和附录 D.3提供了另外的指导。
传入的数据必须通过客户端和服务端的认证。若是,在某个时候,一个终端面对它没法理解的数据或者违反了这个终端定义的输入安全规范和标准,或者这个终端在开始握手时没有收到对应的预期值时(在客户端请求中不正确的路径或者源),终端应该关闭 TCP 链接。若是在成功的握手后收到了无效的数据,终端应该在进入关闭 WebSocket
流程前,发送一个带有合适的状态码(第 7.4 节)的关闭帧。使用一个合适的状态码的关闭帧有助于诊断这个问题。若是这个无效的数据是在 WebSocket 握手时收到的,服务端应该响应一个合适的 HTTP 状态码(RFC2616)。
使用错误的编码来发送数据是一类通用的安全问题。这个协议指定文本类型数据(而不是二进制或者其余类型)的消息使用 UTF-8 编码。虽然仍然能够获得长度值,但实现此协议的应用程序应使用这个长度来肯定帧实际结束的位置,发送不合理的编码数据仍然会致使基于此协议构建的应用程序可能会致使从数据的错误解释到数据丢失或潜在的安全漏洞出现。
在这个文档中描述的 WebSocket 握手协议是不依赖任意 SHA-1 的安全属性,流入抗冲击性和对第二次前映像攻击的抵抗力(就像 RFC4270 描述的同样)。