什么是 WebSocket?
WebSocket 变得越来越流行,因为它们极大地简化了客户端和服务器之间的通信。
WebSocket 协议使用 OSI 模型应用层(第 7 层)来允许客户端和服务器执行双向(全双工)通信。这使得创建动态、实时的 Web 应用程序(例如即时消息和照片共享应用程序)成为可能。
WebSockets 克服了浏览器和服务器之间通信的一些传统限制:
- 客户端请求/服务器响应——过去的服务器有永久的监听器。客户端(使用浏览器的客户端)没有用于长期连接的固定侦听器。这使得每次通信都以客户端要求和服务器响应为中心。
- 通信依赖于客户端——服务器只能在客户端请求时将资源推送给客户端。
- 持续检查——客户端不断被迫刷新服务器的结果。这就是为什么库专注于优化所有异步调用。他们还必须确定自己的反应。此问题最常见的解决方案是使用回调函数。
WebSocket 克服了从客户端到浏览器的单向通信所固有的延迟。在http[s]://协议中,客户端发起请求并等待响应。这称为交易。每个请求/响应都会启动一个不同的事务,并且每个事务都有开销。在 ws[s]:// 协议中,WebSockets 通过多个请求和响应启动长期事务。服务器还可以在没有事先请求的情况下发送数据,从而使通信更加高效。
在本文中:
最常见的 WebSocket 漏洞
让我们回顾一下最常见的 WebSocket 漏洞并了解它们是如何被利用的。
最常见的 WebSocket 漏洞包括
拒绝服务攻击
WebSockets 允许无限数量的连接到达服务器。这使得攻击者可以通过 DOS 攻击淹没服务器。这极大地增加了服务器的压力并耗尽了该服务器上的资源。然后网站速度大大减慢。
握手过程中不进行身份验证
这里的问题是 WebSocket 协议不允许服务器在握手过程中对客户端进行身份验证。仅 HTTP 连接的正常机制可用。其中包括 HTTP 和 TLS 身份验证以及 cookie。从HTTP到WebSocket,升级后的握手仍然发生。但是,HTTP 直接将身份验证信息发送到 WS。这可以被利用,我们将这种攻击称为跨站点 WebSocket 劫持。
未加密的 TCP 通道
WebSocket 的另一个问题是它们可以通过未加密的 TCP 通道使用。这会导致 OWASP 十大 A6 敏感数据泄露中列出的各种问题。
输入数据攻击的漏洞
当组件容易受到恶意输入数据攻击时会发生什么?像跨站点脚本这样的技术。这是一种常见但非常危险的攻击,可能会严重损害您的网站。
在我们关于 跨站点脚本的详细博客文章中了解更多信息。
数据脱敏
数据屏蔽本质上并不是坏事。WebSockets 协议使用它来阻止诸如代理缓存中毒之类的事情。然而,有一个问题。屏蔽可防止安全工具执行识别流量模式等操作。
像 DLP(数据丢失防护)这样的软件甚至不知道 WebSocket 的存在。这使得他们无法对 WebSocket 流量进行数据分析。这也阻止了这些软件程序识别恶意 JavaScript 和数据泄露等情况。
WhenSocket 授权/认证
WebSocket 协议的一个大缺陷是它们不处理授权/身份验证。任何应用程序级协议都需要单独处理这个问题。特别是在传输敏感数据的情况下。
隧道技术
WebSocket 允许任何人通过隧道传输任意 TCP 服务。一个示例是直接通过隧道建立数据库连接并到达浏览器。在跨站点脚本攻击的情况下,它会演变并最终成为彻底的安全漏洞。
嗅探攻击
通过 WebSocket 协议的数据传输以纯文本形式完成,类似于 HTTP。因此,这些数据很容易受到中间人攻击。为了防止信息泄露,请使用WebSocket Secure (wss://)协议。与 HTTPS 一样,wss 并不意味着您的 Web 应用程序是安全的,而是确保数据传输使用传输层安全性 (TLS) 进行加密。
如何提高 WebSocket 安全性
漏洞已被覆盖。我们现在提出一些预防指南来帮助保护您的 WebSocket。
WSS
您不应该使用 ws://,它不是安全传输。相反,使用 wss://,这是一个更安全的协议。WSS 是安全的,因此它可以防止中间人攻击之类的事情。安全的传输从一开始就可以防止许多攻击。
总之,WebSocket 不是标准套接字实现。WebSocket 用途广泛,已建立的连接始终打开,并且可以连续发送和接收消息。然而,DOS 攻击、无身份验证/授权、数据输入攻击漏洞都是可利用的漏洞。这就是为什么使用客户端输入和服务器数据验证、基于票证的身份验证和 WSS 很重要。
客户端输入验证
任意数据。可以在浏览器外部轻松建立 WebSocket 连接。无论如何,您都会处理任意数据。在处理这些数据以及来自客户端的任何其他数据之前,需要对其进行验证。为什么?因为诸如操作系统、SQL、盲 SQL 之类的注入攻击都可以通过 WebSocket 进行。
服务器数据验证
您不必只担心客户端数据验证。服务器返回的数据也可能带来问题。客户端收到的消息应始终作为数据进行处理。不建议将这些消息直接分配给 DOM 或作为代码进行计算。对于 JSON 响应,请结合使用 JSON.parse() 和异常处理(如果需要)结合使用自定义清理方法来安全地解析数据。
基于票证的身份验证
如前所述,WebSocket 协议不处理授权或身份验证。那么如何提高 WebSocket 的安全性呢?通过优化和保护您的连接。WebSocket 传递用于身份验证的所有标准 HTTP 标头。那么为什么我们不使用用于 WebSocket 连接的 Web 视图的身份验证机制呢?
我们无法从 JavaScript 自定义 WebSocket 标头。不幸的是,每个人都仅限于浏览器发送的“隐式”身份验证(cookie)。这还不是全部,因为处理 WebSocket 的服务器通常与处理标准 HTTP 请求的服务器是分开的。这极大地阻碍了共享授权标头。值得庆幸的是,有一种模式可以帮助解决 WebSocket 身份验证问题。基于票证的身份验证系统的工作原理如下:
- 在客户端代码尝试打开 WebSocket 的情况下,会联系 HTTP 服务器以允许客户端代码获取(授权)票证
- 现在票证已生成,其中包含用户/帐户 ID、请求票证的 IP、时间戳和其他内部记录保存
- 票证存储在服务器/数据库中并返回给客户端
- 客户端现在可以打开 WebSocket 连接并将此票证与初始握手一起发送
- 现在,服务器可以选择比较票证、评估源 IP、验证票证的安全性(如果重复使用)等。
- 当一切检查完毕后,WebSocket 连接就会得到验证
防止隧道传输
正如我们已经提到的,通过 WebSocket 建立任意 TCP 服务的隧道非常简单。这是需要防范的风险。避免这个问题的最好方法是什么?尽可能避免挖掘隧道。强烈建议在 WebSocket 之上使用其他安全且经过验证的协议。
速率限制
速率限制是防止滥用 Web 应用程序或 Web 服务的重要方法。它可以防止恶意机器人、抓取攻击和小规模拒绝服务 (DoS) 攻击。在某些情况下,客户端故障可能会导致意外的 DoS 攻击。
要实现速率限制,请为每个用户分配一个“桶”,并确定以下参数:
- 用户每秒发送多少 websocket 流量
- 服务器每秒可以安全处理多少流量
- 来自同一用户的超过服务器容量的流量应放入队列中
- 服务器应该允许一定的超时时间,以允许客户端的突发流量,然后是一个安静的时间段,在此期间服务器可以处理队列
- 超时后,队列中的消息应被丢弃
来源标头
WebSocket 标准允许您定义 Origin 标头字段。这类似于 AJAX X-Requested-With 标头。它确定 WebSocket 连接来自哪个主机。否则,客户端可以通过 WebSocket 协议与任何主机进行通信。
Origin 标头是建议性的,攻击者可以伪造。但是,这仍然需要攻击者更改客户端浏览器上的 Origin 标头,而现代浏览器在大多数情况下会阻止该标头。因此,虽然设置 Origin 字段是个好主意,但您不应该依赖它进行身份验证 - 始终将其与 cookie 或其他身份验证机制结合起来。