Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there no same-origin policy for WebSockets? Why can I connect to ws://localhost?

I'd like to use WebSockets for inter-process communication for my application (Daemon<->WebGUI and Daemon<->FatClient, etc.). During testing, I tried connecting to my locally running web socket server (ws://localhost:1234) via the JavaScript WebSocket client on websocket.org (http://www.websocket.org/echo.html).

My question now is:
Why is this possible? Is there no cross-origin policy implemented in the browsers (here: FF29 on Linux)?

I am asking because if websocket.org was evil, it could try to communicate with my local WS server and redirect every message it receives from localhost to any other server:

 Local WebSocket Server            Browser            Evil Web Server at ws://localhost:1234                               at http://evil.tld         |                            |                       |         |                            |------[GET /]--------->|         |                            |<-----[HTML+EvilJS]----|         |<------[connect ws://..]----|                       |         |<----[some communication]-->|                       |         |                            |----[evil forward]---->|         |                            |                       | 

I have not tested the entire use case, but the connect to ws://localhost from the JS delivered by websocket.org definitely works.

like image 226
binwiederhier Avatar asked May 15 '14 09:05

binwiederhier


People also ask

How do I run a WebSocket server on localhost?

What you can do is place all your code inside onopen event handler that you want to execute on successful connection. So it would be like... var webSocket = new WebSocket("ws://localhost:8025/myContextRoot"); webSocket. onopen = function() { // code you want to execute };

Is WebSocket cross-origin?

WebSockets can make cross-origin requests that are not restricted by browser-based protection mechanisms such as the Same Origin Policy (SOP) or Cross-Origin Resource Sharing (CORS). Without explicit origin validation, this makes CSRF attacks more powerful.

Does CORS affect WebSockets?

SOP/CORS does not apply to WebSocket, but browsers will send an origin header that contains the hostname of the server that served the HTML with the JS that opened the WebSocket connection. A WebSocket server can then restrict access by checking origin .


1 Answers

To address the "Why?" part, the reason why browsers don't enforce the Same Origin Policy (of which CORS is a relaxation) for WebSockets as opposed to AJAX calls, is because WebSockets were introduced after the value of cross-origin requests was established, and because they're not subject to SOP to begin with, the historical reason for the CORS client-side checks doesn't apply.

For AJAX, in the days of a blanket Single Origin Policy, servers never expected an authenticated browser to send a request from a different domain1, and so didn't need to ensure the request was coming from a trusted location2, just check the session cookie. Later relaxations like CORS had to have client-side checks to avoid exposing existing applications to abuse by violating this assumption (effectively doing a CSRF attack).

If the Web were being invented today, knowing what we know now, neither SOP nor CORS would be required for AJAX and it's possible that all the validation would be left to the server.

WebSockets, being a newer technology, are designed to support cross-domain scenarios from the get go. Anyone writing server logic should be aware of the possibility of cross-origin requests and perform the necessary validation, without the need for heavy-handed browser-side precautions à la CORS.


1 This is a simplification. Cross-origin GET requests for resources (including <img>, <link> and <script> tags) and form submission POST requests were always permitted as a fundamental feature of the Web. Nowadays, cross-origin AJAX calls whose requests have the same properties are also permitted and known as simple cross-origin requests. However, accessing the returned data from such requests in code is not allowed unless explicitly permitted by the server's CORS headers. Also, it is these "simple" POST requests that are the primary reason why anti-CSRF tokens are necessary for servers to protect themselves from malicious websites.

2 In fact, a secure way to check the request source wasn't even available since the Referer header can be spoofed e.g. using an open redirect vulnerability. This also shows how poorly CSRF vulnerabilities were understood back then.

like image 163
staafl Avatar answered Oct 24 '22 00:10

staafl