WebSocket 驱动的网络应用程序(例如“彗星”应用程序)是否必须担心 CSRF?

信息安全 csrf 网络套接字
2021-08-30 03:57:42

对于希望防止跨站点请求伪造的 HTTP 应用程序的标准建议是在每个状态更改请求(通常是 POST)中包含一个随机令牌,该令牌在允许状态更改之前由服务器验证。

相同的注意事项是否适用于 WebSocket 连接?使用 WebSockets(或 Socket.IO 或 SockJS 使用的 JSON 轮询等后备传输)的 Web 应用程序是否应该在每次传输时包含由服务器验证的 nonce 以防止 CSRF?

或者是否有针对 WebSockets 的首选缓解策略?

2个回答

使用 websockets (...) 的 web 应用程序是否应该在每次传输时包含由服务器验证的 nonce 以防止 CSRF?

TL;DR:这是可取的,尽管不一定在每次传输(每个连接一次就足够了)并且不是为了防止 CSRF,而是为了防止 XSS。不过,这更像是一种保障,而不是一种严格的必要性。详情如下。


要回答 WebSockets 是否易受 CSRF 攻击,我们必须首先了解允许此类攻击发生的条件:

  1. 用户通过域的身份验证,通常通过会话 cookie;
  2. 存在一种或多种类型的 HTTP 请求,当由经过身份验证的用户执行时,会产生某种副作用;
  3. 由于同源策略的例外情况一个通常不应被允许发出给定请求的站点能够这样做,并且用户代理在该请求中包含身份验证/授权 cookie 。

例如,当站点 A 包含一个指向域 B 的img标记时src,用户代理会接受请求,并传递为域 B 设置的任何 cookie。使用秘密 CSRF 令牌完成的是,部分身份验证数据是包含在 URL 本身中,因此不知道令牌的攻击者无法伪造将被服务器接受的 URL(因为这部分身份验证将失败)。

AFAIK WebSockets 可以打开与任何服务器和端口的连接(免责声明:链接帖子中使用的参考可能已过时)。他们可以拥有自己的 cookie(尽管与 HTTP 页面使用的 cookie 不同 - 因为方案不同)并且 - 如果我对RFC6455的解释是正确的 - 这些 cookie与连接请求一起发送,无论哪个站点发起请求(尽管服务器可以拒绝来自不同来源的请求)。如果这些 cookie 提供了接受请求所需的所有身份验证,则服务器将接受请求。

因此,要确定是否可以进行基于 WebSocket 的 CSRF 攻击,必须考虑以下问题(尽管我恐怕无法提供明确的答案):

  • 您的服务器是否正确配置为仅接受来自受信任来源的请求?可以欺骗来源(在这种情况下)吗?
  • WebSocket 连接是否可以在 JavaScript 调用的上下文之外发生,例如使用wswss作为方案创建 URL 并将其用作标记元素的src或?href那会不会有任何不良的副作用?我知道这很愚蠢,但由于我对这个问题没有答案,我仍然必须提出这种可能性......
  • 您的身份验证和授权是如何完成的?根据这篇文章(也强调了其他潜在问题,与 CSRF 没有直接关系)没有内置任何东西,所以你必须自己实现它。根据您的操作方式以及您对用户代理行为的假设,这可能会为您打开 XSS 攻击(虽然严格来说与 CSRF 不同,但在某种意义上是相关的,即浏览器会滥用其权限来设置与您预期不同的上下文中的身份验证 cookie - 正确或错误)。

相同的考虑是否适用于 websocket 连接?

不,websockets 本身没有 cookie,它们只有通过 websocket 连接显式发送的数据。

使用 websockets(或 Socket.IO 或 SockJS 使用的 JSON 轮询等后备传输)的 Web 应用程序是否应该在每次传输时包含由服务器验证的 nonce 以防止 CSRF?

是的,这是特定于实现的。例如,关于授权的 Socket.IO 文档指出:

当服务器接收到连接时,它将开始从请求中收集以后可能需要的数据。这样做有两个原因:

  1. 用户可能希望根据标头或 IP 地址中的信息授权客户端。
  2. 并非所有传输在尝试与服务器建立实时连接时都会发送标头,因此我们在内部存储握手数据,因此我们确保用户可以在客户端连接时再次重用此数据。例如,您可能希望从 cookie 标头中读取会话 ID,并为连接的套接字初始化 Express 会话。

因此,除非您对每个用户会话使用 nonce,否则如果您在回退机制的服务器端自动接受 cookie 值,则回退传输可能容易受到 CSRF 的攻击。

或者是否有针对 websockets 的首选缓解策略?

Origin如果在初始 HTTP 握手期间验证了标头,则Websocket 不会受到 CSRF的攻击。因此缓解策略是验证Origin客户端发送的标头。