Should web applications using websockets (...) include nonces verified by the server on each transmission to prevent CSRF?
TL;DR: This is desirable, though not necessarily on each trasnmission (once per connection should suffice) and not to prevent CSRF, but XSS. This is more a safeguard than a strict necessity though. Details below.
To answer whether or not WebSockets are vulnerable to CSRF we must first understand the conditions that allow such attacks to take place:
- The user is authenticated to a domain, usually by means of a session cookie;
- There exists one or more types of HTTP request that, when performed by an autheticated user, will have some sort of side-effect;
- Because of exceptions to the same origin policy, one site that should generally not be allowed to make a given request is able to do so, and the user agent includes authentication/authoriation cookies in that request.
For instance, when site A includes a img
tag with src
pointing to domain B, the user agent honors the request, passing along any cookie that is set for domain B. What the use of a secret CSRF token accomplishes is that part of the authentication data is included in the URL itself, so an attacker that does not know the token can not forge a URL that will be accepted by the server (since this part of the authentication will fail).
AFAIK WebSockets can open connections to any server and port (disclaimer: the reference used in the linked post might be outdated). They can have their own cookies (although not the same ones used by the HTTP pages - since the scheme is different) and - if my interpretation of RFC6455 is correct - these cookies will be sent alongside the connection request regardless of which site initiated the request (though the server can reject requests coming from a different origin). If these cookies provide all the authentication required to honor the request, then the server will honor the request.
So, to determine whether or not a WebSocket-based CSRF attack can be made, these questions must be considered (though I'm afraid I can't provide a definite answer on them):
- Is your server properly configured to only accept request from trusted origins? Can the origin be spoofed (in this context)?
- Can a WebSocket connection happen outside the context of a JavaScript call, for instance creating a URL with
ws
or wss
as scheme and using it as a src
or href
of a markup element? Would that have any undesirable side-effect? I know it's silly, but since I don't have an answer to this question I must raise the possibility nonetheless...
- How is your authentication and authorization done? According to this post (which also highlight other potential issues, not directly related to CSRF) there is nothing built-in, so you have to implement it yourself. Depending on how you do it, and what assumptions you make about the user agent behavior, this may open you up for XSS attacks (which, while different from CSRF strictly speaking, is related in the sense that the browser would misuse its authority to set authentication cookies in contexts that are different from what you expected - righly or wrongly).