6

The standard advice for HTTP applications wanting to prevent Cross Site Request Forgery is to include a random token on each state-changing request (usually POST) which is verified by the server before allowing the state change.

Do the same considerations apply for WebSocket connections? Should web applications using WebSockets (or fall-back transports like JSON polling, as employed by Socket.IO or SockJS) include nonces verified by the server on each transmission to prevent CSRF?

Or is there a preferred mitigation strategy for WebSockets?

SilverlightFox
  • 33,408
  • 6
  • 67
  • 178
user85461
  • 301
  • 1
  • 7

2 Answers2

3

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:

  1. The user is authenticated to a domain, usually by means of a session cookie;
  2. There exists one or more types of HTTP request that, when performed by an autheticated user, will have some sort of side-effect;
  3. 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).
mgibsonbr
  • 2,905
  • 2
  • 20
  • 35
  • 1
    -1 This answer is completely misleading and uninformed, and the parts that tries to be helpful are mere speculations. WebSockets **do** follow the RFC6454 (The Web Origin Concept). The RFC6455 explains how cookies should be used and how the user agent should transport these cookies. Finally, the whole answer has nothing to do with CSRF. – Adi May 18 '13 at 16:12
  • @Adnan ok, thanks for the info, I'll read more about the RFC6454. But in face of this, I guess this answer is unsalvageable, so I'm deleting it... – mgibsonbr May 18 '13 at 16:36
  • @Adnan new attempt... you're right that the previous answer was uninformed, and I really appreciate the feedback, but I disagree it had nothing to do with CSRF: I was simply breaking down the elements that allow such attacks to take place (something I made more explicit after this edit) and commenting on how much each of them applied to WebSockets. And the "speculations" were simply more questions that - while I didn't/don't have a definite answer to them - I judged important in evaluating whether or not the assumptions we make about the browser behavior are correct. – mgibsonbr May 18 '13 at 19:25
  • @Adi: "WebSockets do follow the RFC6454 (The Web Origin Concept)." --- Not all clients have to add the origin header: "The request MUST include a header field with the name |Origin| [RFC6454] **if** the request is coming from a browser client." – Daniel Feb 01 '17 at 14:47
1

Do the same considerations apply for websocket connections?

No, websockets do not have cookies as such, they only have the data that is explicitly sent through the websocket connection.

Should web applications using websockets (or fallback transports like JSON polling, as employed by Socket.IO or SockJS) include nonces verified by the server on each transmission to prevent CSRF?

Yes, this is implementation specific. For example, the Socket.IO documentation on authorization states:

When the server receives a connection it will start gathering data from the request that might be needed later. This is done for two reasons:

  1. Users might want to authorize the clients based on information from the headers or IP address.
  2. Not all transports sends headers when they attempt to establish a real time connection with the server, so we store the handshake data internally so we are sure users can re-use this data again for when the client is connected. For example you might want to read out the session id from the cookie headers and initialize the Express session for the connected socket.

So it appears that unless you use a nonce per user session, it is possible that fallback transports would be vulnerable to CSRF if you are automatically accepting cookie values in the server side end of the fallback mechanism.

Or is there a preferred mitigation strategy for websockets?

Websockets are not vulnerable to CSRF, provided the Origin header is validated during the initial HTTP handshake. So the mitigation strategy is to validate the Origin header sent from the client.

SilverlightFox
  • 33,408
  • 6
  • 67
  • 178
  • Non-browser clients can "*send fake |Origin| header fields, misleading the server.*" [RFC 6455] So checking the origin is not sufficient to cover all attack possibilities. – Daniel Feb 01 '17 at 14:42
  • 1
    CSRF requires a browser, and the attacker isn't the one using this browser. It is a client-side attack and involves "tricking" the victim browser into making a request, which will pass the `Origin` from the victim browser of which the attacker has no control of. – SilverlightFox Feb 01 '17 at 14:45