Free Newsletters

   All InfoWorld Newsletters
Strategic Developer | Martin Heller » Subverting AJAX: Prototype Highjacking

January 08, 2007 | Comments: (0)

Subverting AJAX: Prototype Highjacking

One of the most interesting parts of the JavaScript language is the prototype property, which underpins the language's object-oriented inheritance. In JavaScript, functions are a specialized kind of object; every function (and indeed every JavaScript object) has a prototype property that refers to a predefined prototype object, which comes into play when the function is used as a constructor with the new operator.

Prototypes are not limited to user-defined classes. Even built-in JavaScript classes have prototype properties, and you can assign values to them.

This is extremely powerful. It is also extremely dangerous. Using prototyping, an attacker can hijack standard functions in a way that breaks security without causing any error message. Browsers try to prohibit this by dropping the prototype property for some of their internal functions, but there's a way around that protection.

At the 23rd Chaos Communication Congress, held at the end of December in Berlin, Stefano Di Paola and Giorgio Fedon gave a talk called Subverting AJAX (PDF), in which they explained exactly how to do this. Coupled with a cross-site scripting attack and a cleverly crafted phishing email, such an attack could turn an AJAX application into a keylogger with a man-in-the-middle attack strategy. Consider the following diagram, from Di Paola and Fedon's paper:

What's happening here is that the attacker has hijacked the browser's XMLHttpRequest object, and wrapped it with his own keylogging logic. How hard is this to do? Not very hard at all. The key code would be:

var xmlreqc=XMLHttpRequest;
XMLHttpRequest = function() {
    this.xml = new xmlreqc();
    return this;
}

This is fairly subtle, but it's devastating. XMLHttpRequest has been redefined to be a wrapper for itself. Any time a new instance of XMLHttpRequest is intended to be created in subsequent code, the wrapper method will be created instead. It now doesn't matter that the original XMLHttpRequest function didn't have a prototype property: the new one does.

Once the attacker has prototypes at his disposal, he can redefine key methods. For example, he can redefine the send method to sniff and/or modify the content, as shown in the figure above and the following code:

XMLHttpRequest.prototype.send = function (pay){
    // Hijacked .send
    sniff("Hijacked: "+pay);   //log the original message
    pay=HijackRequest(pay);    //change the message
    return this.xml.send(pay); //send it on
}

The classic response to this kind of exploit would be "disable JavaScript in your browser." Unfortunately, AJAX applications inherently require JavaScript, and most people really like the improved user experience of AJAX applications compared to conventional Web applications.

I don't have a good solution, other than constant vigilance on the part of every author and user of AJAX applications. We're back to "Don't talk to strangers," kids. In the words of the original CERT bulletin about cross-site scripting,

"users can gain some protection by being selective about how they initially visit a Web site. Typing addresses directly into the browser (or using securely stored local bookmarks) is likely to be the safest way of connecting to a site."

(Thanks and a tip of the hat to Roy M. Silvernail, who alerted me to this exploit.)

Posted by Martin Heller on January 8, 2007 10:24 AM


RATE THIS ARTICLE:





 

  •  
  • COMMENTS




Absolutely (to the "don't talk to strangers" comment).

Once you say 'cross-site scripting attack', then pretty much anything is possible, so any statement after that is pretty much moot. Nothing new has been 'found' here by those of us who have been doing 'AJAX' (DHTML, or whatever the current buzzword is for this technology this year) for years.

The ability to redefine built-in properties or to add functionality to built-in objects is an extremely powerful feature of most dynamic languages, not just JavaScript. It is what allows programmers to make built-in objects respond to a common API that they're defining, not just what the language designer defined. In the object-oriented world, this is what we call 'polymorphism' and is an absolute requirement for a true object-oriented language.

Cheers,

- Bill

Posted by: William J. Edney at January 8, 2007 11:22 AM

I'm glad to hear from the "nothing new" end of the opinion spectrum. Up until now, I've mostly heard from people who think that this is the end of Web 2.0 as we know it.

Posted by: Martin at January 8, 2007 01:56 PM

So what? That hacker can only hack his self or someone else's browser he has access to. Why do I care if he is key logging himself?

Posted by: Darold James at January 9, 2007 04:54 AM

One scenario is:

1) The victim gets a phishing email luring him to a legit-looking Web site, and clicks on the link.

2) The victim arrives at the Web site via the provided link. By one means or another (a silent intermediate site, or cross-site scripting on the final site), his browser executes code that redefines XMLHttpRequest and hijacks its send method.

3) The victim is then passed to a legitimate AJAX application, perhaps for banking, and the attacker captures the message stream to his own site.

Posted by: Martin at January 9, 2007 07:36 AM

"I don't have a good solution, other than constant vigilance on the part of every author and user of AJAX applications."

What should authors look out for? Can they clear away prototypes on predefined functions they use?

Posted by: Lars at January 9, 2007 08:47 AM

Interesting idea! Maybe someone with better JavaScript skills than mine can offer up a solution along those lines.

I was specifically thinking of checking your sites carefully for vulnerabilities, of which cross-site scripting is the prime example.

Posted by: Martin at January 9, 2007 10:31 AM

How is this any different from some yahoo sending you a link to a bogus site in the first place? He doesn't have to hijack XMLHttpRequest to get your Visa card # if you are stupid enough to type it into a text field.

Any object extensions die when you drop that session. I see no method of dropping a key logger onto your system unless your security is so bad you allow an unknown site to install an ActiveX control on your box anyhow.

Tempest in a teapot and a lot of work for no more return.

Posted by: Doug at January 9, 2007 03:27 PM

The point is that it can defeat all the protections you build into the real site. It doesn't matter if the site requires 2-factor authentication and uses HTTPS encryption: the attacker has inserted himself into the middle of the data stream between the victim and the real site, at the client, where the data is not encrypted.

Posted by: Martin at January 9, 2007 05:32 PM

Once again a demonstration that downloadable code cannot be trusted, even if (as in this case) it is trustworthy. Reason is, a previous site downloaded code that made the entire browser untrustworthy.

AJAX et other rich client tools need to give up - they can't win this one, ever.

Posted by: paul tndal at January 11, 2007 03:15 PM

I tried this hack and it does work (allows you to inject additional code in XMLHTTPRequest(), however it only compromises that page, not other pages (in other tabs) I have open in Firefox, so the chances of it changing behavior on legitimate sites open in other windows/tabs appear to be nil in my limited testing.

I understand the presented scenario:

--------------

One scenario is:

1) The victim gets a phishing email luring him to a legit-looking Web site, and clicks on the link.

2) The victim arrives at the Web site via the provided link. By one means or another (a silent intermediate site, or cross-site scripting on the final site), his browser executes code that redefines XMLHttpRequest and hijacks its send method.

3) The victim is then passed to a legitimate AJAX application, perhaps for banking, and the attacker captures the message stream to his own site.
Posted by: Martin at January 9, 2007 07:36 AM

--------------

Has anyone actually coded an example of this? Or it this just a theoretical exploit so far?

Posted by: Mark Carson at January 11, 2007 04:01 PM

I would only expect this exploit to compromise one browser session. I doesn't matter if that browser session is in a tab or a window, it's still one browser session.

But compromising one session is plenty, if it concerns something valuable, like a banking or stock-trading session, or a corporate email session discussing marketing plans of interest to competitors.

Posted by: Martin at January 12, 2007 08:12 AM

I Know this is an old post, but I'll comment on this anyway.

I understand that this here method, would intercept the communication, by altering the XMLHttpRequest. So to protect your own scripts, you should always alter the XMLHttpRequest yourself, so as to eliminate the hackers altering.

Would this be a fix?

Posted by: Jan Nielsen at January 14, 2007 11:38 PM

I wouldn't do that. I might put code on my page that makes sure that XMLHttpRequest doesn't have a prototype property, however. It would warn about that if it detected it, and would then refuse to start the secure AJAX application.

Posted by: Martin at January 15, 2007 08:55 AM

Technology White Papers

 

InfoWorld Technology Marketplace

» Technology White Papers Library

Technology White Papers by Topic

Technology White Papers E-mail Alert

Find out when the latest white paper is available:
 
 
» BUY A LINK NOW

Sponsored Technology Links