34 comments

[ 2.7 ms ] story [ 69.4 ms ] thread
Kudos to JetBrains for awarding the very generous $50,000 bounty (and to the author for donating the bulk of it).

The YouCompleteMe project had a similar vulnerability[1]. I suppose a lesson here is that if your development environment/tools expose services over HTTP on localhost you should be really careful with CORS headers.

[1]: https://github.com/Valloric/ycmd#is-hmac-auth-for-requestsre...

No, that can not be at all the conclusion to make from this.

Security can not come from sending magic strings back and hoping whoever is facilitating the attack respects them.

Agreed, local IPC endpoints should be equipped with some form of authentication at minimum. For a live preview server where the endpoint has to be viewable in a browser, this may be a rare case where HTTP Basic Auth is a good solution, launching a URL like http://<random_nonce>:<random_nonce>@localhost:1337/index.ht... (with rate limiting on the server side, of course)
I'm not sure if I follow this criticism. Having the server validate an HMAC of the request does not require the attacker to respect any magic strings. The attacker cannot craft a correctly authenticated request (since they do not know the shared secret used to construct the HMAC) and thus cannot issue requests that the server will honor.
I understood your comment to say they should do CORS properly, which amounts to just magic strings sent back to a potential attacker.

HMAC is separate from CORS, or did I miss something?

I think I'm confused myself. I was interpreting the main issue in the JetBrains case to be their use of very permissive CORS headers on the locally running server, but their solution added an auth token in addition to removing the CORS policies. ycmd also doesn't appear to set any CORS headers, in addition to validating the HMAC of the request.

Is a sane cross-origin policy not enough on its own to prevent evil.com from being able to communicate with a web server running on localhost? Or is the message authentication to protect from attack vectors other than the user navigating to a malicious site?

CORS seems like a nice-to-have. You're relying on other software to always indicate something is a cross origin request, browsers should always do that but then there is a whole host of software that uses embedded web controls and the like and may navigate to webpages on the basis of external and not user input.
This seems intentional from JetBrains to target unlicensed users/pirated copies.
This is exactly why services that expose unnecessary network services drive me batty.

The extent of this vulnerability would have been significantly limited if it were only enabled for users using the feature (e.g., not Android Studio, PyCharm, or other users) and even more-so if it were enabled on-demand.

In recent memory, both CodeKit and Prepros really want to have some live preview HTTP server enabled all the time. Simply enabling it when the user hit the "Open Live Preview" button in the app would significantly reduce the attack surface. As would giving users the option to enable/disable it at will.

FYI - WebStorm's features exist in PyCharm and you can count me as one user that finds them extremely useful.

I agree with the enabled on-demand comment however.

Enabling it on demand would also allow them to randomize the listening port and generate new authentication tokens more frequently.
Wow. I'd like to quote the final section "Interactions with the vendor". It's been my experience as a user as well, of my very numerous bug reports - not because it's buggier than others but because I'm quick posting them - most have been solved within a very reasonable amount of time (I always provide a reproducible test case, which helps).

From here on it's all a quote:

"I’d like to specifically thank Hadi Hariri and the rest of the JetBrains team for their proactive response to my report. My email requesting a security contact was answered within an hour of my sending it, and the issue was resolved relatively quickly."

"They sent me a patchset against intellij-community and a binary build with their proposed solutions, and were receptive to my feedback when I mentioned potential issues."

"Lastly, even though Jetbrains doesn’t have a bug bounty program that I’m aware of, and I definitely wasn’t expecting anything, Jetbrains quite generously awarded a bounty of $50,000 for my report and help reviewing the patch. I’ve asked them to donate the bulk of this to the PyPy project to fund improved Python 3 support, fingers crossed for await/async support in PyPy :)."

Holy shit. I'm quite a cynical person, but this deserves the "restored my faith in humanity" trope. Mad respect for both JetBrains and the researcher. $50k is nothing to sneer at.
Seconded; I've been a happy JetBrains customer for like 6 years now, partially because of their awesome support.

I would have expected an intelligent response from them based on my experience, but this is above and beyond even my expectation.

When I played around with XMLHttpRequest to a locally running Jupyter server I got the following error:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

It seems that should have prevented this exploit as well?

(comment deleted)
It can be bypassed with DNS rebinding.
I did a test with packet capture just now and "Access-Control-Allow-Origin" does not prevent the request from being made, just preventing the JavaScript from getting the response back.
Little known fact: OS X has something quite similar to UNC paths, which can probably be used in the same way as an exploitation vector for this bug (and others). Specifically, there is an autofs mounted on /net which will try to mount an NFS share from any IP address if triggered by any process simply accessing a path starting with "/net/(host)/(sharename)".

Incidentally, I don't think this is accessible from an app sandbox, but I expect JetBrains' IDEs aren't sandboxed.

Interesting! I haven't spent much time looking at OS X internals, but I'll remember this for next time. Have any resources for other OS X quirks like this?
This is why you need to isolate your applications. You never know what kind of services and other things are being exposed. Use subuser (subuser.org) or at least firejail. Simple isolation eliminates this type of security problem.
A different experience: I'm working on an android project at the moment. I emailed JetBrains 10 days ago asking why the Intellij Ultimate IDE blocks the UI so generously. I characterized it as heavy handed and frequently unnecessary. I pointed out the workaround I use is to switch to a competing product during these moments. I suggested it diminishes developer productivity. I said that competing products have the same problem and solving it would be a big win for enterprise customers. I didn't get $50K (not expected) or even the courtesy of a response (expected).
A really bad security bug report is going to get a lot more attention than a feature request. Threatening them with "I will use a competitor" means loss of a single customer. Not quite the same as "my entire company was compromised and we lost millions of dollars due to a security bug"
It was written in a constructive way, not as a threat. For me, the competing product is vim. All I'm saying is, I think I deserved a response for trying to help them improve their product. Maybe that's too much to ask, idk.
> For me, the competing product is vim.

This sounds like a troll. I would expect that the guys at Jetbrains get screamed at quite often for their IDE's memory and CPU consumption (they even have a "low power" mode, which is quite telling). But on the other hand, users (I am in that group) of Jetbrains IDEs are there for the sheer awesomeness of their inspections and refactoring abilities. UI perfs notwithstanding, they have the best tools out there.

So you comparing their product to Vim shows how trollish (or really badly constructed) your argument is. You can't compare the two of them seriously, and I wouldn't be surprised if the Jetbrains team simply glanced at your email and classified it as "troll" or "don't bother with extremists".

The "low power" mode is for stopping running the many inspections on the code continuously while you are typing. That's hundreds of code checks and often an external code check tool as well (eslint in my case).

Obviously, running all those extra tools while typing uses quite a bit of extra power. It has nothing to do with "this IDE is fat" (it is, but that's a separate issue), but with the amount of features run continuously.

http://stackoverflow.com/questions/11725605/what-is-power-sa...

I didn't compare it to vim to them. The reason I mentioned vim above was because of nhumrich's inference that I was "threatening them", which was totally false.

In my message, I was very polite and constructive. My point was based on the business case for fixing something that inconveniences the customer so much. I didn't realize that I walked on such sacred ground when I tried to improve the product that you seem to love so much.

I'm still not sure why it needs to block me from editing some files while I have to wait 5+ minutes while it does an unrelated update. If that's extremist then so be it.

>"No live PoC for the Windows or OS X RCEs ‘cause I don’t want to host public-facing SMB or NFS shares :)"

I wonder what the minimum amount of code / work would be to make a Samba-lite to do this kind of testing. I'm surprised it isn't in Metasploit already.

Three things standout to me that made this attack possible.

1. JetBrains setting too broad CORS headers.

2. JetBrains listening to 0.0.0.0 instead of only listening to localhost. Seems like YCMD is also listening to 0.0.0.0 instead of only localhost though.

3. But the overlooked concern in my eyes is why web browsers support XMLHTTPRequests to localhost/127.0.0.1 at all. I can't imagine a valid use case for that outside of developers working against a local machine. Seems to me like XMLHTPPRequests to localhost should be rejected by browsers unless `--disable-web-security` or some other equivalent is used during startup.

> I can't imagine a valid use case for that outside of developers working against a local machine

it's very useful to talk to locally installed applications without having to write specific browser plugins for all browsers. Dropbox and Github are using it to detect the presence of their respective desktop apps.

And I'm personally using it (with restrictive CORS header, referrer signature checking and only listening on localhost) to read a barcode scanner and put the data into a web application. We only had to write one app per OS we support instead of one app per OS and one extension per browser (which also means that this works in all HTML5 compatible browsers, not just those we deem worthy of our support).

I should have been clearer about that, for extensions I agree that calling localhost is reasonable if you have a desktop app you want to talk to for example. My suggestion would be removing the capabilities of XMLHTTPRequests to localhost from websites wile retaining the possibility for extensions