防止针对 WebSocket 通信的 CSRF 攻击

信息安全 Web应用程序 csrf html-5 网络套接字
2021-08-31 17:47:28

我已经阅读了关于 websockets 中的 CSRF 攻击的主题(Do WebSocket-powered web apps (eg "comet" apps) have to care about CSRF?)以及一些关于 websocket 安全性的更多材料,但它们似乎都没有解决以下问题-

攻击者是否有可能导致(通过引诱受害者点击链接)合法用户向合法服务打开 WebSocket 和/或导致受害者在受害者现有的 WebSocket 中发送攻击者制作的消息?(类似于 HTTP 上下文中的标准 CSRF 攻击)。

如果可能,可以做些什么来预防它?在 WebSocket 打开期间在 WebSocket URL 中发送令牌是否足够,或者是否需要在 WebSocket 内发送的每个请求中发送令牌?

我们打算使用 WebSockets 在我们网站的未经身份验证的区域中实现聊天,并且我们希望确保我们正在尽一切可能防止恶意用户执行类似于上述攻击的攻击。关于最安全的实施方式有什么特别的建议吗?

2个回答

如果您依赖身份验证 cookie,则可能会对 WebSocket 进行 CSRF 攻击。来自 RFC 6455 §1.3:

|产地| 标头字段 [RFC6454] 用于防止在 Web 浏览器中使用 WebSocket API脚本对 WebSocket 服务器进行未经授权的跨域使用服务器被告知生成 WebSocket 连接请求的脚本来源。如果服务器不希望接受来自该源的连接,它可以选择通过发送适当的 HTTP 错误代码来拒绝连接。该头域由浏览器客户端发送;对于非浏览器客户端,如果在这些客户端的上下文中有意义,则可以发送标头字段

我强调了几个部分。第一个魔法词是can,第二个是may。WebSocket 服务器可以检查来源,但这是可选的。非浏览器客户端可以发送源头,但这不是强制性的。

恶意行为者可以使用 CSRF 攻击打开与 WebSocket 服务器的 WebSocket 连接,并且浏览器会将 cookie 附加到请求中。如果服务器不检查来源,或者检查了来源但来源是伪造的,则攻击获取到具有受害者权限的 WebSocket 服务器的读写隧道。

检查来源可能涵盖了大多数攻击,因为人类传统上使用发送正确来源标头的主要浏览器。然而,面对非浏览器客户端,它们可以“发送虚假的 |Origin| 标头字段,误导服务器”[RFC 6455 §10.1],应该应用其他机制。这篇博文建议检查来源并使用会话个体随机令牌作为对策。我想人们也可以在 WebSocket 连接建立之后执行某种身份验证,尽管这会损害可用性。

请注意,我在下面的回答假设正确检查了 Origin 标头并专门回答了您的问题。

如果在打开新的 websocket 时没有在您自己的代码中进行源检查或其他有效的身份验证检查,则可能发生套接字劫持。

原始答案如下...

攻击者是否有可能导致(通过引诱受害者点击链接)合法用户打开一个指向合法服务的 websocket 和/或导致受害者在受害者现有的 websocket 中发送攻击者制作的消息?(类似于 HTTP 上下文中的标准 CSRF 攻击)。

不,攻击者无法通过打开新的 websocket 或重用受害者现有的 websocket 来使用 websocket 执行 CSRF。

通过打开一个新的 websocket:攻击者可以做到这一点,但没有向套接字侦听器提供身份验证凭据的机制。在初始握手 HTTP 请求期间,Origin可以在服务器端使用标头来验证这是否来自有效来源。对于套接字本身,与正常的 HTTP 请求不同,默认情况下浏览器不会发送任何标头来识别或验证用户。

重用受害者现有的 websocket:假设 websocket 在主页上是这样声明的www.example.com

var exampleSocket = new WebSocket("ws://www.example.com/socketserver", "protocolOne");

exampleSocket由于对 DOM 的访问www.example.com受到同源策略的保护,攻击者将无法获得引用