Live data from Hacker News

Stealing secrets from developers using WebSockets

medium.com

41–50 of 146 posts

Re: Stealing secrets from developers using WebSockets

#42
post #2

This 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.

It is not subject to CORS, same as any regular img load isn't, but the browser will send an Origin header with websocket handshakes, which you're supposed to check server-side.

Re: Stealing secrets from developers using WebSockets

#43
post #13

And this is why you are supposed to check the origin and host headers before sending sensitive data to a web socket

create-react-app may already be doing so according to https://news.ycombinator.com/item?id=23259803

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

#44
post #6

Earlier 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.

Or you can have this on firewall level.

Re: Stealing secrets from developers using WebSockets

#45

Earlier 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.

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

#46
This is why you don't let @wongmjane inject code into websites. Imagine what features she'd learn about with tracebacks from developer machines! /s

In 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

#47
post #40
post #33

Forget 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.

I can still attack your local non-http-servers with a regular post, e.g. something like http://bugs.proftpd.org/show_bug.cgi?id=4143

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

#48
post #13

And this is why you are supposed to check the origin and host headers before sending sensitive data to a web socket

Yeah, keep pimping these "mitigations" instead of a better security model that doesn't require everyone perfectly jumping through hoops. When you get fucked over by one of such security exploits it will be a great relief to know that it could have been prevented if only the software vendor did the right security voodoo dance (which gets more elaborate by the month).

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

#49
post #45

Earlier 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.

If the page does not have JS running, how would it check the time elapsed? i'm not seeing the vulnerability with noscript here.

Re: Stealing secrets from developers using WebSockets

#50

I 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…

You do realize that your evil server could in fact send something back to your exploit to ask it to send something back to the server it connected to right?

   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..."
Post reply on HN