My boss Jeff Williams came up with something very clever while my company (Aspect Security) was participating in NIST’s Static Analysis Tools Exposition (SATE). Basically, NIST challenged all the major static code analysis vendors to a massive bakeoff sponsored by DHS. Being a consulting company that mainly performs code reviews and penetration tests, we couldn’t stand to sit on the sidelines while our portion of the industry was basically being written off like Dunder Mifflin. So Jeff sent a tongue in cheek letter suggesting that we be allowed to enter. The response from NIST was shockingly responsive – nice to know there’s a part of NIST that I can still trust.
Anyway, in one of the bakeoff test applications, we found a piece of data that was run through a pretty good blacklist before being stuck into a Content-disposition HTTP header. Great – that means header injection! But wait – we can’t do XSS or response splitting because of the characters in the blacklist! What can we do?
(Well, in the end we actually did come up with an XSS vector using UTF-7 and some other stuff, but forget about that for now.)
Here’s the Java code that’s vulnerable to HTTP header injection:
response.setHeader(“Content-Disposition”, “attachment; filename=” + request.getParameter(“fn”) );
Jeff’s bright idea: pass in attack.bat%0a%0d%0a%0dwordpad
Let’s look at the layout of the resulting HTTP response when we pass that in:
HTTP/1.1 200 OK
Date: Thu, 27 Mar 2008 05:02:24 GMT
Set-Cookie: JSESSIONID=E35E52B9472B17666B3A77C19CDCD90E; Path=/download
What’s in red is our attack code. There’s not many special characters and it’s even more deadly than XSS – remote file execution! The user’s browser downloads a file called “attack.bat”, and kicks off a batch file containing whatever commands we want to execute. In the example we just kicked off wordpad. Notice that the remaining HTTP headers are included after our payload, but that doesn’t seem to present any real problem we can think of, especially since we may be able to control the content length and exclude that stuff in most cases. Here’s an example attack string that gets and executes a random executable off the net.
There’s a downside for attackers here though – if you try to kick off any kind of executable file extension, the browser pops up a warning. However, because the link resides on a trusted domain it remains a very effective attack. Response splitting can result in a mass-effect cache poison, but this attack (File Download Injection) is a very non-theoretical, low-tech attack that has a very realistic chance of being exploited (now that the attackers know about it – thanks, Jeff). So, the advice stays the same. Don’t click on anything, ever, despite any promises of getting nudey pictures of Jenna Fischer.
There’s more you can do besides forge a quick batch file too. Some of the extensions get kicked off automatically (no popup warning), like QuickTime’s .mov. But because this attack is a reflected link attack, the “body” of the file you want the user to download has to be relatively small as the whole thing must be contained in the malicious URL. IE has maximum of 2,083 characters in a URL, but having a massive URL is a problem more because such a large URL will look suspicious rather than because of any exploitability constraints. With that said – there’s a host of platforms, browsers, and file extensions that have not been tested – so after some research you might find a more deadly extension to use than .bat.
How does this relate to XSS?