A problem worse than Zoom?
lapcatsoftware.com
lapcatsoftware.com
I didn’t bother to write a blog post about it because my English is not good enough.
Basically, anyone who uses this app is vulnerable to cross-infection and data leaks. Assume that user John installed this app, then hacker Alice tricked John to visit their malicious website. In this website, they added code that sends requests to “http://localhost:34344/upload” to upload malicious files to any of the services that John’s computer is connected to via Dropshare, this includes private servers via SSH, Amazon S3, Rackspace Cloud Files, Google Drive, Backblaze B2 Cloud Storage, Microsoft Azure Blob Storage, Dropbox, WeTransfer, and custom Mac network connections. The port number is also static, saving the hacker the need to run a port scanner.
I already contacted Dropshare’s developers to fix the issue, but got not response.
Think of it as long form tweeting!
Here are some resources I find useful for this:
https://www.plainlanguage.gov/guidelines/
I’m intrigued by https://www.grammarly.com/ but it sends everything you write to their cloud service, which is completely unacceptable to me. If I can’t use the tool for proprietary and private writing, it’s useless.
Agreed with the other comments, this comment = blog, looks like you know what you're talking about, short, to the point.
Good find, and thanks for sharing
off topic comment:
For all, what are people blogging on these days? I am not too fond of Medium, but I just got into Ghost and really liking it. It seems like a great short post / resource to write something. I have it installed on a cheap DO server, plain text like lapcat?
Basically everyone who says this has better English than most American technical developers. We appreciate your modesty, but please, write it up :)
I wrote lame articles years ago, to explain technical work i did on castle and nhibernate. Made me better over time.
Just now, writing this, I had to look up if the saying went "inordinate amount" or "unordinate amount". The difference between "pristine" and "immaculate". It really adds up when writing longer texts.
For what it’s worth, I think your examples are nuanced questions about fairly sophisticated terms. I look up similar things all the time, and I am a native English speaker, have a first-class education, and write regularly for my day job.
Don’t sell yourself short!
Maybe I can get you in touch?
I found a malware on a JavaScript errors notifications for Chrome in 2015 that affected 86k users and the developer was mad because apparently he made some money out of it (I was called a paranoyd).
The malware basically logged your accessed URLs and solt it to a statistics service called Fairshare.
Edit: I guess not, see Dang's reply below.
I'm sorry but WtF who is this guy, every web developer will know this, and every developer should expect it since it's just an extension of basic networking knowledge applied to web browsers. It's not horrifying, it's basics, a great many things have depended on this fact to function for a very long time.
Yes functionality can work against you when abused, no this is not a special case.
This prevents LAN enumeration from random websites. This is not a big deal for most home networks, but I shudder to think of the damage one could do in a standard corporate network.
It doesn't help with routers with well-known config URLs.
Yes, I realize that this will break a bunch of stuff.
(Edit: OK, DNS rebinding mostly breaks this proposal. Let me think about this harder.)
That isn't even the issue. It's that there is nothing inherently wrong or unusual with mixing local and internet requests.
Look at IFPS -- it runs a webserver on localhost which you can request content from by using content hashes. There is nothing wrong with a website on the internet which anticipates that you to have IFPS installed and uses it to request page elements. It can even use javascript to detect that you have it and use a different (e.g. slower or more expensive) source for the content if you don't, or show a message explaining how to install it.
Or you have a company with some internal servers where some of them have public addresses (or public IPv6 addresses) while some don't, but they arbitrarily access resources on the others because they're all managed by the same people.
This isn't a browser problem. Browsers are supposed to work this way.
You need to fix the things that are broken instead of breaking the things that are working.
As an example of legitimate use, Ubiquiti routers have a web app at ubiquiti.com that opens connections to manage your local routers. It's all authenticated with cookies. It seems like a good design.
Some larger companies use public IP addresses for everyone's desktop, but they're still behind a firewall. So these are "local" in the sense of behind their firewall, despite being "publicly" routable addresses.
An attacker can create a domain name pointing to any IP, including 127.0.0.1 and 192.168.1.1. So browsers won't gain any security by looking at the domain name.
I really struggle to see why "legitimate use" that's a minority of all use cases should forbid a consensus from cordoning off a major attack surface with an affordance for that legitimate usage.
Also, legitimate services on the local network have tools like CORS and CSPs as well as standard anti-XSS and anti-CSRF techniques to use to defend themselves.
Based on history I know which group I would expect to implement first.
Certain subnets are always private [1], and thus may safely treated as “local”. But, of course, non-private addresses could also be local, but that’s less common in a non-enterprise setting.
A script from the internet should not be allowed to interface with a script from local network (localhost, local intranet e.t.c)
The browser should have strict sandboxes. This is like when you load a site over https, browsers scream at you if you load a http resource saying it's insecure.
You can have multiple IPs for a domain name, so if I set "hack.tlb.org" to include both a server I control and 192.168.1.1, I can repeatedly do fetches from "hack.tlb.org" until one of them gets your router instead of my server. And they're in the "same origin" for CORS purposes.
You log into app.plex.com, which will connect to yourserver.account.plex.local or something like that, which resolves to an IP on your LAN. Your server will then feed the web page app with data, without going via your WAN link.
So does that mean any tab I have open on my computer can try and talk to my local development mysql server and my local development web server? That's crazy. Wasn't there also an article in the past year about how a bunch of IOT devices run unsecure on LAN because they assume they are secure?
I assume you've already setup the relevant browser settings and extensions to enforce a user-defined CSP that blocks all further requests? If so, then great, your browser won't make any requests when you visit sites. And my browser will (apart from what I've blocked with other more selective extensions). We're both happy.
Similarly, there are legitimate reasons why I might want to access a service with an invalid SSL cert. They're rare and should be discouraged for general users.
This isn't about 'garbage software'; it's about the expectation that a local LAN is not exposed to the Internet and therefore does not need the same security controls that an Internet-facing network does.
Browsers making requests on the LAN breaks this expectation.
Before someone says "but I don't expect that", well, why do you even have a firewall? With the notable exception of Google/BeyondCorp, practically every LAN in the world expects to trust its members. Having untrusted code in browsers able to send requests on the LAN violates that expectation.
b) Excepting LAN to be always secure, or okay to keep unsecured is a terrible assumption that has been proven wrong numerous times, it is time to trash that assumption once and for all.
In general though, this isn't be a problem on proper IPv6 LANs and instead of buggy and cumbersome workarounds being built into browsers we should just switch.
Such as? Breaking "website makes a call to local (localhost or RFC1918) web server" would be a feature; any use of this is an abuse. It'd take a transition period and some careful opt-outs, but any kind of call to a local web server should require the same kind of special privileges a browser extension needs, at the very least.
It's a bug. Calling it out is the right thing to do. If you're complaining that the author should have known about it already, then you're just mocking someone for not already knowing a particular fact; that shouldn't stop them from writing up a report on it and trying to get it fixed.
EDIT: please note that I'm talking about calls from Internet origins to localhost/RFC1918 origins here, not calls from one Internet origin to another or one localhost/RFC1918 origin to another.
I'm talking about requests from pages served from the Internet to servers on localhost or servers on an RFC1918 address.
Or does SOP not apply to local addresses?
I think for all cases it could make sense to enable the user to also approve CORS requests instead of just the cross origin website itself (since they are often insecure).
This comes from the same line of thinking as "shouldn't every device have a routable IP?". Yes, in theory, but a long history of not having one has made people more lax about local systems and securing services. And until the vast majority of local services address their security issues, we shouldn't make them accessible.
> Or does SOP not apply to local addresses?
It should, but that's not the world we have. Yes, we should fix the million local devices with CSRF/CORS/etc issues. We should also have an extra layer of protection in web browsers to prevent this. Defense in depth. (And note that many local devices do this intentionally, to give a website more permissions, as in the case of Zoom. The local web server wants to make itself accessible to the Internet; browsers should prevent that.)
Can you please make your substantive points without making things personal?
It's essentially 2nd order ignorance, it's not personal, it's relevant to the validity of their argument.
The online calling-out and shaming culture is particularly unwanted on HN. It has a degrading effect on the community.
This isn't necessarily an excuse to not explore mitigations through consensus in future browser behavior -- after all, that process of loose but eventual consensus of incremental UX and airquote "security" improvements is how SOP and CORS and C-S-P came about [1] and the cookie saga evolves [2][3].
But consider that legitimate uses of cross-domain requests to localhost exist (e.g. an OAuth callback endpoint), while also keeping in mind that users from all walks of life are, perhaps unbeknownst to them, are managing LANs of computing devices running dozens of servers, often with modern encryption such that communications between the program and the remote server are becoming harder to intercept and oversee, and lack a comprehensive capability to monitor, analyze, blacklist, whitelist, or snipe traffic in a way that's not cumbersome or borderline user-hostile. Such is the world where we've arrived. Etching away on one or two widely deployed corners of it won't fix the overall landscape, even if it may significantly reduce the change of "drive-by" exploitation through websites accessed through commonly used browsers.
[1] https://news.ycombinator.com/item?id=12408328#12408680 [2] https://news.ycombinator.com/item?id=13689697#13691022 [3] https://news.ycombinator.com/item?id=19853090#19855518
Safari whitelists a number of URL schemes used by its first-party and internal apps:
adir
applenews
applenewss
itms
itmss
itunes
itms-books
itms-bookss
ibooks
macappstore
macappstores
rdar
radr
radar
udoc
ts
st
x-radar
icloud-sharing
help
x-apple-helpbasicBut this leads to a bigger question, what makes private address space special? Not really all that much. Running an internal network using public addresses isn't super common these days but isn't uncommon by any stretch. Does it make any sense that any website on the internet is allowed to hit any other site accessible by your machine that uses a public address? There is definitely a security boundary being crossed here.
Say for example I run a web service that's private to my work's office. So spin up a machine on my VPS account, give it a public address, and lock down the firewall to my office's address range. Someone running Spotify in browser shouldn't have to worry about a malicious page hitting a potentially sensitive internal service.
Does it make any sense for me have to establish a VPN connection to my VPS for the sole purpose of giving it a private address so browsers will block it? Ew. I could also configure a CORS policy but we're talking about a service that used a trick to bypass this protection -- and plus nobody knows how to set that up right anyway.
The problem is that Zoom, since they didn't understand CORS, and yet did want to allow their site to make API requests, turned what should have been an harmless action (GET an image) into a dangerous one.
Browsers could block everything, but all I think would happen is that Zoom would just find some other silly (and potentially more dangerous) way of doing the same thing, because they want the site to be able to talk to the service.
If you're writing your own service to be used on an internal network, you don't need a VPN or anything. Just don't accept unauthenticated requests that make changes, and ignore CORS.
The problem here is that it’s really pretty trivial to scan a local network and get valuable metadata about the router and other devices on the network, just using JavaScript and xmlhttprequest. It’s not that the local services are at risk of being exploited, but the whole (average, unhardened home-) network could be compromised by identifying devices with known exploits and, well, exploiting them.
Now I’m trying to come up with a non-PITA way of isolating browsing from my local network while still allowing direct access to my local network!
UMatrix will protect you from most of this (with the exception of DNS rebind attacks).
I don't necessarily disagree with people who are frustrated that their browser can do this, but I also think it's completely reasonable to make it easy for browsers to send requests on an intranet. There are multiple devices in my house that wouldn't work with that capability.
The "problem", to the extent that there is a problem, is that securing these devices relies on developers doing the right thing -- and developers are untrustworthy. Theoretically, it would be better to put users in control. But that's not a specific problem with Intranet requests, that's a problem with CORS in general as it applies to the entire Internet.
Agree. But shouldn't we distinguish a request that originates from the local user's input into the browser from one that originates from a remote entity? I'm slightly ignorant here; maybe this isn't technically possible?
<img src="http://192.168.1.1/cgi-bin/reboot-router">
And it didn't have to be port 80 -- you could try fuzzing someone's X server with
<img src="http://127.0.0.1:6000/lsjdfjlk23jlrkj">
Fortunately, most protocols bail out on the first 4 bytes "GET ". One of the reasons that Gopher support was phased out was that you could make a gopher request contain more or less arbitrary bytes and attack many local servers.
Servers have always had the burden of defending against this.
I could pretty easily set up 1234.mymaliciousdomain.com to resolve to your local network.
Lots of websites will link to something like `http://localhost:9200` (e.g. Elasticsearch) in the documentation.
So you decide to make it impossible to load that page in the context of a page loaded from a public IP address. Great.
What is stopping them from tricking you into clicking it (or filling out a fake form), which is basically the same thing?
You haven't really solved the problem. You've just made it slightly more difficult.
The solution is:
a) fix your applications so that they do not expose unsafe endpoints that can cause unintended side-effects merely by navigating to them
b) stop using session cookies (at least stop using them alone) to authenticate actions. Use token-based authentication (like CSRF tokens)
Edit: and before you say "check the referer header!", no, that will not solve the problem. The bad web page can simply not include the referer with something like `rel="noreferrer"`
With the same origin policy? I think the post advocates for something like allowing localhost and private IP addresses only from those very same addresses or from the URL bar. Any other page shouldn't be able to access them.
This will probably break something but what's the case for a web app to legitimately access local host? Maybe access to some local service installed by the user and managed "from the cloud".
You can do all kinds of things that don't violate the SOP but initiate a request:
- Link to another site
- Redirect someone to another page using Javascript
- Link an image from another site
- Put a form that submits data to another site
- Embed video/audio from another site
- Embed an iframe from another site
Do you propose disallowing all of those things?
There are plenty of legitimate use cases for all of these things.
If you wanted to do this you would have to disallow any type of links to local servers.
We have ways of handling these things, they just require a bit of reading/implementation and are unfortunately non-default.
For example display a notification:
"This website wants to interact with devices in your network, if your are at home, this includes all of your
smart things, smart phones and other devices".
I mean, we have a windows firewall and sandboxing on every level and then a webrowser suddenly acts as a vpn for every website?
That can't be good security design
I would give one blanket permission for a website.
Then if possible list the devices which it connected to.
Or you alllow it only per device.
There are legitimate reasons to open a webserver locally. However, the benefits from these restrictions are great not to consider some sort of protection. Perhaps there could be an authorization request the user could allow (similar to how we got rid of the pop-ups) in the most natural way possible (we don't want to break intranets, for example).
Another security-related bad pattern that annoys me is how some of this authorization stuff steal your focus making it impossible for you to ignore them (like, you cannot move to another tab before deciding to allow or not something).
Another thing is how sometimes it is not completely clear if something is an element of a website or your browser or system. For example, imagine you have to type your user password for a random update to complete, but you are browsing some website... Suddenly you see a prompt with your username and a password field matching your system's... However, you can only know for sure this isn't phishing if you try to cmd+tab and it is still there. Heck, the system should try to detect you are on a window showing unsigned/unsafe content and paint something out of the frame (like coming from the top address bar) so you can easily identify it's legit (because a website shouldn't be able to print a portion of your screen outside of 'window').
Is there a way to know definitively if an address is "local" rather than "wide"? Should that be more granular, e.g. host, LAN, WAN? How does that work with bridged networking and such?
If I'm already browsing something on the LAN, it seems reasonable to be able to browse other sites on the LAN. But then that seems like an overly broad definition of LAN would allow privilege escalation.
If I saw a private IP (192.168, 10, etc) or a .local domain, I'd assume that was a LAN address, but that's a convention and depends very much on routing being set up properly.
This convention on the address is actually backed by RFCs. eg. rfc 1918. There is similar for ipv6.
However, blocking traffic to private IPs without careful consideration seems like it could block some legitimate use. So one does have to tread carefully when special-casing those.
If the routing table entry for the address is a single interface entry, then it's 'local', if it has a gateway hop it's probably 'wide'.
Are there any best-practices for keeping things locally safe (i.e. LAN devices like printers, testing boxes, tvs etc.) , beyond just treating them the same way you would an external facing machine?
Yeah, forget about home, this is a nightmare. Who knows how many devices are in a corporate network. Internal networks are usually not as well protected as the perimeter.
You can make XHR (aka ajax) requests only if the CORS policy allows it (concretely, this local web server you are trying to access is answering with a specific HTTP header saying "I authorize the website xyz.com to send XHR request to me via the web browser of the client of xyz.com).
Now for everything outside of XHR(ajax), you can send different type of requests : <script src="..."></script> but this let you only load js files. <img src="..." /> but this lets you only load images, you can't really do much other than try to load images with that.
So if you get into the detail of each "web api" (XHR, <img/>, <script/>, etc) you will see that you are actually very limited.
- www.mydomain.com
- stage.mydomain.com
- local.mydomain.com
The last one referred to the version of the app that developers ran on their own machines. So they had a DNS-level entry that sent local.mydomain.com to 127.0.0.1.
This isn't a browser issue at all. I think the security issue is "applications can install local web servers" and "some local web servers are insecure".
We already have XSS controls in place to prevent a domain from accessing the contents of another browser window or an iframe.
It's not a browser issue. There are plenty of legitimate reasons for wanting a browser to access a local web server. It might not be common, but it's not illegitimate nor a security issue.
Yup, that's exactly it!
What's a local area network? 10.x.x.x? That's going to break VPNs and enterprise integrations in a variety of ways. With IPv6 it's even less predictable.
The solution to this problem is CORS — accessing LAN servers, or any cross-origin destination, requires affirmative consent from the LAN server in the form of the Access-Control-Allow-Origin header.
Zoom did control the localhost server, and setting a CORS header would have helped mitigate the attack.
If zoom made the localhost server answer the cors header with '*', what you can do?
There's only so much browsers can do to mitigate hostile code running on the machine. CORS won't save me if Zoom decided to wipe my hard drive, you know?
That also makes it much harder to extract interesting information from non-HTTP servers running on localhost.
There is no equivalent of RFC1918 for IPv6 and filtering link-local addresses won't do much as every host on the LAN is still adressable by its publicly routable address. These are probably too hard to predict, though.
That is, as long as your devices on LAN do not send a access-control-allow-origin header, the web pages are not capable of getting the actual response. Also, the only http method available to them is GET (when preflight is not required) and OPTIONS (when preflight is required), which are methods that are almost always side-effect free and only return some value - which the script cannot even get due to CORS restrictions.
However, I don't really see that as the fundamental problem with the Zoom web server. They just happened to use local web requests to externally trigger the Zoom application, because it's probably the most convenient to implement. But couldn't they have, at least in theory, had the Zoom application snoop on the display output until it finds an image of a QR code and open a conference call based on the data in that QR code?
Obviously that's a more intensive listening mechanism, but my point is that the fundamental problem seems to be that their application installs a backdoor that is designed to expose the webcam without confirmation based on user actions that do not necessarily imply intent (like clicking on a web link). The local web request thing is really just an implementation detail: one that probably should be fixed by browsers, but far from the only way Zoom could have implemented this feature.
After all, the Zoom client could just have a socket connection to Zoom's servers, and start a conference call whenever someone requests one. That's how all native apps for conferencing/message work. They just usually require confirmation from the user, and they usually (I hope) uninstall that process when I uninstall the app, so people tend to be less upset.
Of course if your local webservers have a really open CORS header, that could be a problem. But it's a matter for local webserver, mostly. And DNS rebinding still applies.
private-address: 192.168.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
private-address: 169.254.0.0/16
private-address: 127.0.0.1/8
private-address: fd00::/8
private-address: fe80::/10
private-address: ::ffff:0:0/96
private-address: ::1/128[1] http://cgbystrom.com/articles/deconstructing-spotifys-builti...
Instead it's the server at api.bank.com 's responsibility to tell the browser it only accepts requests from bank.com.
And beyond that they also allow mixed content for asset requests from TLS pages to non-TLS URLs of any IP address (for instance an AT&T modem configuration page at 192.168.1.254).
This site detects all kinds of services running on your local network: https://github.com/wybiral/localtoast
I wrote a more in-depth explanation of this behavior here: https://davywybiral.blogspot.com/2019/05/always-secure-your-...
You sure about your claims? Your own website exhibits a countering argument.
But it was able to successfully ping my running Steam Client. The page works like an acid test; if it's clean, you're clean. If it finds something, it says what and the port.
Doesn't seem to affect Windows version though.
It also works in Brave Browser even when in "Tor mode" (which seems very wrong).
Chrome v75.0.3770.100: "Mixed Content: The page at 'https://wybiral.github.io/localtoast/' was loaded over HTTPS, but requested an insecure image 'http://192.168.1.254/images/att_globe_logo.png'. This content should also be served over HTTPS."
Firefox v69.0b4: "Loading mixed (insecure) display content “http://fritz.box/css/rd/images/fritzLogo.svg” on a secure page"
Edge v44.18362.1.0: "SEC7137: [Mixed-Content] The origin 'https://wybiral.github.io' was loaded in a secure context and loaded an optionally blockable insecure image resource at 'http://fritz.box/css/rd/images/fritzLogo.svg'."
For localhost-only you don't get those warnings because browsers treat localhost as TLS even if it's not, such as this: https://github.com/wybiral/wtf
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simpl...
CORS mediates the ability of JavaScript running in one origin to _read_ responses from another origin. If Zoom wanted JavaScript on any site to read data from the local installation, their local web server would need only return appropriate CORS headers. This was not necessary for the use case of joining a meeting.
CORS will solve the javascript/ajax part, BTW.
"Is this possibility not surprising to you?"
> no
"It was surprising to me!"
> that is because you don't understand the web
"The problem is actually worse than this."
> I wouldn't call it a problem
"The major browsers I've tested — Safari, Chrome, Firefox — all allow web pages to send requests not only to localhost but also to any IP address on your Local Area Network!"
> Yes, that's called conforming to a standard and it took years of work to get them all to behave the same.
In other news, the sky is blue, trees are green, and shooting yourself in the foot still makes you bleed.
CORS also works on the local network, or even localhost, as the author has discovered for himself here. Uses in these spaces are less ubiquitous, but if you have ever needed to set up a web enabled resource in these spaces, you may need CORS. I'll give some theoretical uses here:
1. A company sells routers. They host a webpage at company.com that makes requests to your router at <scary ip>
2. A company sells a big, expensive hardware component that attaches to your computer. To manage this component, they set up a website at company.com, and the component sets up a website on your computer. Company.com makes requests to localhost, to manage that big, expensive component.
The actual issue here is that companies setting up these websites at localhost and in your local network do not securely set up CORS (see Zoom, other issues). Although it would be unreasonable to kill these use cases, it would be reasonable to require the user of the browser to check off that a localhost or local network request is okay.
Disallowing access to localhost seems more plausible, especially if there’s an exception for extensions so that things like 1Password can continue to work.
As always, you should practice defense in depth and work to secure your internal network from potential bad actors attacking from within your internal network. NATs offer you partial security and make some attacks harder; but you can't just throw up a private web server without authentication and say, "it's on a NAT, so it's secure."
This is especially true in the IOT world, where the threat to your network may not even be coming from a browser/website. Multiple layers of defense are the way to go, because no single layer is impenetrable.
I guess this should serve as a cue that there is something off in what you are writing. You did not just discover a major security flaw in all web browsers while not being an experimented (at least web) software engineer.
Wait, what? Is this sarcasm? This is by definition how networking operates.
Scary times.
An evil web page at example.com/evil can certainly contain an img tag for http://localhost/me.jpg or http://dropbox.com/private-photo.jpg. You will see your private images displayed on their web site, but while that may be disturbing (or even useful for phishing), the evil web page cannot transmit the image data back to itself. For example, it can't use JavaScript to load the image into a canvas, base64 encode the canvas, and POST it back to itself, because the canvas will become "dirty" as soon as the image is loaded into it, and the browser will not allow JavaScript code to dump a dirty canvas to any inspectable format.