"In all seriousness, this attack vector is pretty slim. You’ve got to tempt unwitting users to visit your site, and to stay on it while they’re developing JS code."<p>Wrap the exploit up in a blog post about Rust -- or an article about gut bacteria -- and submit it to Hackernews. Boom, a virtual feast of secrets.
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<p>In seriousness, this is all because websockets aren't bound by CORS, for good reason. <a href="https://blog.securityevaluators.com/websockets-not-bound-by-cors-does-this-mean-2e7819374acc" rel="nofollow">https://blog.securityevaluators.com/websockets-not-bound-by-...</a><p>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.
Heads up to anyone who doesn't already know, uMatrix[0] can be set up to block websockets by default from 3rd-party and/or first-party domains. In the UI, websockets are grouped under the "xhr" column[1].<p>I'm a pretty big Javascript advocate, but I do recommend advanced users run uMatrix and consider disabling at least 3rd-party JS by default. uMatrix is a fantastic tool and it really doesn't take long to get used to. And honestly, a relatively large portion of the web works with only 1st party Javascript, and a surprising chunk of the web still works just fine with no Javascript at all.<p>This is also why I advise advanced users to run Firefox. uMatrix isn't available for Safari, and it's looking extremely likely that it'll be at least underpowered in Chrome once Manifest v3 comes out. Or I guess run Brave or Vivaldi or whatever. Dang kids running around with their hipster browsers, I can't keep track of them all.<p>The point is, even though I'm extremely bullish on the web as a secure application platform, part of the reason I'm bullish is because the web makes it relatively easy to take simple security measures like disabling scripts by default. You should absolutely take advantage of that, you should absolutely be disabling at least some Javascript features when you browse.<p>You can even globally turn off fingerprinting vectors like WebGL[2]/Canvas[3] in Firefox, and just swap to a different profile whenever you want to visit the rare game/app that requires them. Although with more and more people trying to embed their own DOM models in Canvas, maybe that'll be harder in the future.<p>[0]: <a href="https://github.com/gorhill/uMatrix" rel="nofollow">https://github.com/gorhill/uMatrix</a><p>[1]: <a href="https://github.com/gorhill/uMatrix/wiki/The-popup-panel#the-type-cells" rel="nofollow">https://github.com/gorhill/uMatrix/wiki/The-popup-panel#the-...</a><p>[2]: about:config -> `webgl.disabled` -> true<p>[3]: <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=967895" rel="nofollow">https://bugzilla.mozilla.org/show_bug.cgi?id=967895</a>
Given the news this has made, I sure hope browser vendors don't overreact with blocking this too hard:<p>I genuinely have a use-case for this. We have an internal company wide business app, that works in any browser. The usual create-read-update-delete stuff, reports, factory forms etc.<p>With websockets we solve communication with local devices on the shopfloor - some computers have serial-port attached thermal printers, others have usb attached notification lights. We have small python scripts that listen for commands with websockets on 127.0.0.1 and control the printers and lights.<p>That way we can control each users local devices from the web app - without configuring internal firewalls or installing special browser add-ons (an in-house browser add-on is a bigger security risk, than a websocket on 127.0.0.1)
Node debug mode runs a websocket, but the address is something like ws://0.0.0.0:9229/1cda98c5-9ae8-4f9a-805a-f36d0a8cdbe8 - without the correct guid at the end, you can't open the websocket and communicate. You can only detect the port being open by timing.
Is anybody keeping a list of potential security threats so browser vendors can check them off and the community can verify that they are correctly dealt with?
I just tested an approach to deny access to WebSockets in the browser. This only applies if the JavaScript and the page comes from a location you both control and your goal is to limit access from third party scripts and you don't have access to the page's server to add a Content Security Policy (CSP) rule restricting web socket addresses/ports to specified rules.<p>TypeScript code:<p><pre><code> const sock:WebSocketLocal = (function local_socket():WebSocketLocal {
// A minor security circumvention.
const socket:WebSocketLocal = <WebSocketLocal>WebSocket;
WebSocket = null;
return socket;
}());
</code></pre>
TypeScript definitions (index.d.ts):<p><pre><code> interface WebSocketLocal extends WebSocket {
new (address:string): WebSocket;
}
</code></pre>
If the 'sock' variable is not globally scoped it cannot be globally accessed. This means third party scripts must know the name of the variable and be able to access the scope where the variable is declared, because the global variable name "WebSockets" is reassigned to null and any attempts to access it will break those third party scripts.
This websockets thing is getting more interesting very fast. I wonder how long it'll be before someone finds something truly scary? This is the 3rd post this week, and each one has found a little bit more. Nothing that seems panic worthy yet. From this one:<p>"In all seriousness, this attack vector is pretty slim. You’ve got to tempt unwitting users to visit your site, and to stay on it while they’re developing JS code."
I wonder if this could be used to grab more sensitive data from apps that support browser extensions (e.g. from password managers that use websockets to communicate with browser extensions).
You're likely not even safe from this if you are using Chrome OS. It does sandbox the localhost web server [1] [2], but it does not restrict access to it from the host.<p>[1]: <a href="https://youtu.be/pRlh8LX4kQI?t=954" rel="nofollow">https://youtu.be/pRlh8LX4kQI?t=954</a><p>[2]: <a href="https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/vm_tools#chunnel" rel="nofollow">https://chromium.googlesource.com/chromiumos/platform2/+/HEA...</a>
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?
I get the following output when trying this with Create React App running:<p>{"type":"error","data":"Invalid Host/Origin header"}<p>I don't think I changed any significant settings in CRA, this is pretty close to the default. Not sure what exactly determines whether this works or not.
The server didn't work for me, not sure if it's a traffic issue or what.<p>I have at least 3 create-react-app and one next app running. I even ran a quick websocket server on port 3000 just to see but nada.
Interesting, history repeats. Didn't browsers implement firewalls a while ago to prevent arbitrary requests? Remember doing things like CSRF attacks on SMTP, POP (any text based protocol basically) and stuff like that long ago, but Firefox added mitigations to prevent connections to certain ports - I guess that browser Firewall feature can be used as mitigation to prevent these attacks.
> browsers allow websockets from public origins to open websockets connections to localhost without many protections<p>Excuse me, but what in the world? XHR has all kinds of cross-site request protections that even make developing apps locally a pain. How come websockets don't come with such protections?<p>Are there apps that take over this responsibility?
I'm assuming this can be mitigated by using SSL/TLS. Have a read over at <a href="https://crossbar.io/docs/Secure-WebSocket-and-HTTPS/" rel="nofollow">https://crossbar.io/docs/Secure-WebSocket-and-HTTPS/</a> - Not sure how you would do certificate pinning though.
Can't you use CSRF to protect against this?<p><a href="https://dev.solita.fi/2018/11/07/securing-websocket-endpoints.html" rel="nofollow">https://dev.solita.fi/2018/11/07/securing-websocket-endpoint...</a>
when I disable websocket with network.websocket.max-connections = 0, then whatsappweb doesn't work, so perhaps someone can develop a related attack here?
Is the TL;DR here just "webpack-dev server doesn't verify Origin headers for hot reloading?"<p>Is there a whole group of people that are just learning about Websockets for the first time?