Stealing secrets from developers using WebSockets
41–50 of 146 posts
Re: Stealing secrets from developers using WebSockets
#42This is interesting, thanks for sharing. I wonder if a remediation for the moment would be for local websocket servers to check the Host header before sending the 101 switch protocol response. Also would a CORS "Access-Control-Allow-Origin: localhost" prevent the connections being established?
> Also would a CORS "Access-Control-Allow-Origin: localhost" prevent the connections being established? WebSocket isn't bound by CORS, AFAIK.
Re: Stealing secrets from developers using WebSockets
#43And this is why you are supposed to check the origin and host headers before sending sensitive data to a web socket
EDIT: Nope, exploit worked for me against webpack-dev 3.10.3 used by react-scripts 3.4.1
Re: Stealing secrets from developers using WebSockets
#44Earlier quoted context omitted.
Super bad news about that: even if it didn't allow the `localhost` string, DNS rebinding allows the domain name of the site you visited to become 127.0.0.1. The answer to why browsers allow connections to 127.0.0.1 from external sites is probably something like "legacy reasons".
DNS rebinding can be fixed at the DNS server level. OpenWRT has an option for it. But this websocket thing in browsers can't easily be turned off/mitigated AFAICT.
Re: Stealing secrets from developers using WebSockets
#45Earlier quoted context omitted.
This issues isn't endemic to websockets. I've done this with iframes as well to portscan machines on my LAN. Additionally, the portscan capabilities are even worse than the article states: you can scan any machine reachable from the visitor's machine. Any 192.* address, anything behind your VPN, so long as the time for actively refusing the connection and failing to route are different. I don't know if you can time c…
POC https://jsfiddle.net/s9vzxctd/3/ Tested in Firefox ESR on Linux. Anything with about 3000ms time isn't a routable network address. Anything with a significantly longer or shorter time responds to a ping on my network. Timings vary from browser to browser. NoScript does block the requests before they ever leave your browser, reminding me why I use it.
Eg write a simple HTML file like
ok
If it takes different amounts of time for the page to stop loading and the text to appear depending on the port you checked, you're vulnerable to scans, even when Javascript is disabled.Re: Stealing secrets from developers using WebSockets
#46In seriousness, this is all because websockets aren't bound by CORS, for good reason. https://blog.securityevaluators.com/websockets-not-bound-by-...
There's a simple fix though - hot reload websocket listeners like Webpack should only consider the connection valid if they first receive a shared secret that's loaded into the initial dev bundle, which itself would never be transmitted over a websocket and could be set via CORS to not be accessible to non-whitelisted origins. It's a dead-simple protocol with no ongoing performance impacts. But understandable it hasn't been implemented yet.
Re: Stealing secrets from developers using WebSockets
#47Forget port scanning for a sec. Couldn't you just scan the whole local network for common vulnerabilities, like any old virus would?
You can only make a websockets request. The javascript call will fail if either the port is closed, or the port is open but doesn't act like a websockets server. So you can tell if a port is open by the time it takes for the connection to fail. If it's actually a websockets server you hit, then you might get a useable bidirectional communication channel to it.
With Websockets something like this is effectively not possible, because WebSockets were designed with this in mind
- A browser will only start transmitting data over the ws once the handshake is done. So just making a request has very limited ways for an attacker to transmit user defined data (basically the Host header/Origin header and cookies... which will not really work as an attack vector for newline-delimited or binary protocols)
- The handshake itself works by the client sending a nonce to the server which the server then has to hash together with a special uuid. Only actual websocket servers know how to do this step correctly, and thus the browser will refuse to even open connections to servers which aren't actual websocket servers. So the attacker will not be able to send truly arbitrary data or read any responses.
- Even after the handshake, browser-to-server data is masked by XORing the data with browser-picked keys. The attacker therefore cannot control what the data will end up looking like when it is sent to the server. And unaware servers will certainly not try to reverse the XORing.
What you're left with regarding websockets are timing attacks to do some port and network scanning, and attacking actual websocket servers, which do not check the Origin or use some kind of token to verify incoming connections, analog to attack-able regular http endpoints that do not do auth and csrf tokens properly.
I'll readily admit tho, that a lot of developers forget about verifying incoming websocket connections. I have fucked this up myself in the past, and I have found such issues in other websites, including one problem that let me take over user accounts via an unsecured websocket if I was able to get such users to open an attack website (or ad).
Re: Stealing secrets from developers using WebSockets
#48And this is why you are supposed to check the origin and host headers before sending sensitive data to a web socket
Edit: can't wait for the usual replies with "what is your solution?"
The obvious flaw in modern web security is that the domain isolation model does not make any sense today. It's an outdated hack. Software communication should be done thorough something resembling actor model where code running locally is thought of as completely separate entity from the web server. It shouldn't have anything to do with domains. Communication from any actor to any other actor should be subject to the same security model, regardless of where their code was loaded from. Escalating privileges between actors should be a universal and well-established process with known guarantees, not a bloody mess of ad-hoc conventions, headers and "best practices" that change with every browser, app and year.
Re: Stealing secrets from developers using WebSockets
#49Earlier quoted context omitted.
POC https://jsfiddle.net/s9vzxctd/3/ Tested in Firefox ESR on Linux. Anything with about 3000ms time isn't a routable network address. Anything with a significantly longer or shorter time responds to a ping on my network. Timings vary from browser to browser. NoScript does block the requests before they ever leave your browser, reminding me why I use it.
NoScript isn't sufficient to protect you from this. Eg write a simple HTML file like ok If it takes different amounts of time for the page to stop loading and the text to appear depending on the port you checked, you're vulnerable to scans, even when Javascript is disabled.
Re: Stealing secrets from developers using WebSockets
#50I too like to hardcode my AWS secret keys in my frontend application
Admittedly the example was a bit fake :) I /have/ put other secrets into frontend code before, strictly for small temporary projects where the cost of implementing secret management outweighs the size of the project. And obviously not in code that was anywhere close to being deployed outside my own box. Unfortunately the method outlined in the article allows access to environments that would otherwise be considered t…
evil-server
(looks at data from client)
(recognizes well known server app)
(launches exploit!)
The first one that comes to mind is built in "package updaters" where the front end server has a well defined way of updating its packages. Have your evil server send it "get a new version of fetch_user_passwords from here..."