12

I have read the thread about CSRF attacks in websockets (Do WebSocket-powered web apps (e.g. "comet" apps) have to worry about CSRF?) and also some more material regarding websocket security, but none of them seem to address the following issue -

Is it possible for an attacker to cause (by luring the victim to press a link) a legitimate user to open a WebSocket towards the legitimate service and/or cause the victim to send messages crafted by an attacker within the victim's existing WebSocket? (similar to a standard CSRF attack in the context of HTTP).

If possible, what can be done to prevent it? Is sending a token in the WebSocket URL during the WebSocket opening enough, or does the token need to be sent within each and every one of the requests sent within the WebSocket?

We are intending to use WebSockets to implement a chat in the unauthenticated area of our site, and we want to make sure we are doing everything possible to prevent malicious users from executing attacks similar to the one described above. Any special recommendations regarding the most secure way to implement this?

user3074662
  • 541
  • 2
  • 6
  • 11

2 Answers2

5

A CSRF attack on WebSocket is possible, if you rely on authentication cookies. From RFC 6455 §1.3:

The |Origin| header field [RFC6454] is used to protect against unauthorized cross-origin use of a WebSocket server by scripts using the WebSocket API in a web browser. The server is informed of the script origin generating the WebSocket connection request. If the server does not wish to accept connections from this origin, it can choose to reject the connection by sending an appropriate HTTP error code. This header field is sent by browser clients; for non-browser clients, this header field may be sent if it makes sense in the context of those clients.

I've highlighted a few parts. The first magic word is can and the second is may. WebSocket servers can check the origin, but this is optional. Non-browser clients may send the origin header, but this is not mandatory.

A malicious actor could use a CSRF attack to open a WebSocket connection to a WebSocket server and the cookies would be appended by the browser to the request. If the server does not check the origin, or if does check the origin but the origin is forged, then the attack acquires a read-write tunnel to the WebSocket server with the permissions of the victim.

Checking the origin probably covers the majority of attacks since humans traditionally use major browsers that do send the correct origin header. However, in the face of non-browser clients, which can "send fake |Origin| header fields, misleading the server" [RFC 6455 §10.1], other mechanisms should be applied. This blog post suggests both checking the origin and using session-individual random tokens as countermeasures. I suppose one can also perform some kind of authentication over the WebSocket connection, after it is established, though this can harm usability.

Daniel
  • 627
  • 5
  • 16
3

Note, my answer below assumes that the Origin header is being correctly checked and answers your question specifically.

Socket hijacking is possible if there are no origin checks, or other valid authentication checks made in your own code when opening a new websocket.

Original answer follows...

Is it possible for an attacker to cause (by luring the victim to press a link) a legitimate user to open a websocket towards the legitimate service and/or cause the victim to send messages crafted by an attacker within the victim's existing websocket? (similar to a standard CSRF attack in the context of HTTP).

No, an attacker could not perform CSRF with websockets by opening a new websocket or by reusing the victim's existing websocket.

By opening a new websocket: An attacker could do this, but would have no mechanism for providing authentication credentials to the socket listener. During an initial handshake HTTP request, the Origin header can be used on the server-side to verify that this is from a valid origin. For the socket itself, unlike a normal HTTP request, there are no headers sent by the browser to identify or authenticate the user by default.

Reusing the victim's existing websocket: Say the websocket is declared like so on the homepage of www.example.com:

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

An attacker will not be able to get a reference to exampleSocket as access to www.example.com's DOM is protected by the Same Origin Policy.

SilverlightFox
  • 33,408
  • 6
  • 67
  • 178
  • According to this paper: http://www.christian-schneider.net/CrossSiteWebSocketHijacking.html , websockets are not protected by the same origin policy. Is this correct only for the websocket upgrade itself? An attacker cannot embed code in his site instructing the browser to send input into an existing web socket? @SilverlightFox – user3074662 Jan 04 '15 at 10:28
  • @user3074662: As the article states, to prevent this attack you must check the `Origin` header server-side: `Clearly the CORS stuff has nothing to do with the WebSockets stuff, but they both utilize the same request header (Origin) and the server-side code should check that header!`. – SilverlightFox Jan 04 '15 at 13:25
  • @user3074662: No, the connection needs to be first "upgraded" so the `Origin` can be checked at this point. – SilverlightFox Jan 04 '15 at 13:26