Tuesday, November 17, 2015

JSON Hijacking

I came across something known as JSON Hijacking some days back. In fact, I was actually asked about it in an interview and being the dumb me, I had no fucking clue as to what it really was. So post the embarrassment, I went ahead to do what I am (at least I would love to think so) best at, dig in deeper. 

I went through a lot of articles and blogs about the subject and decided to put it all together in one place here. Now I know this might be boring for a lot of you guys, who already know about it, but this is just so when I need to recollect things from my digging in, I could reference back here and avoid myself the ignorance once again. 

There's an awesome article here that helped me understand the crux of the matter :
http://haacked.com/archive/2009/06/25/json-hijacking.aspx/
@haacked thanks for sharing this :)

The blog itself is pretty much self explanatory, except for a few places that my super awesome (PUN INTENDED) java script skills came in handy. So in one of the places, the blog says :


"The bad guy has tricked the victim’s browser to issue a request for the JSON containing sensitive information using the browser’s credentials (aka the auth cookie). This loads the JSON array as executable JavaScript and now the bad guy has access to this data.  "

Wait, how did JSON become exe again ?

Now, I could not quite relate to how exactly being able to load the JSON containing sensitive information causes the JSON array to be loaded as an executable. Of course, authenticated cookies would be required to fetch the JSON containing sensitive information, but I don't see the same to be any reason for loading the JS as an exe. 

So further digging (and actually also further down the blog itself) helped me understand this :
Javascript arrays are treated as objects. So if an end point (the vulnerable server in our case) returns sensitive data in JSON wrapped inside an array, then this array object is a perfectly valid piece of a whole Javascript code itself. 

Hence, in a webpage if there is a statement like :

<script type="text/javascript" src="vulnerable.com/jsondata"></script>

and if the end point returns sensitive data in JSON wrapped in an array, as :

[{"name":"victim", "phone":"88578438839", "ccNumber":"67890987898789", "pin":"2344"}]

Once the above js gets loaded in the browser, the above array object will become a part of the page.

Wait, and sure you haven't heard of the Same Origin Policy !

The script tags are not governed by the same origin policy. So a page on attacker.com can make a jsvascript src call like the above perfectly without any violations. 

By the power bestowed in me by JS :

The attacker's page consists of something like :

<script type="text/javascript"> Object.prototype.__defineSetter__('ccNumber', function(obj){alert(obj);});

Converting the above line to sanity : 

There is something known as __defineSetter__ which is a method that binds an object's property to a function to be called when an attempt is made to set that property. (What is property ? - 'Property' of an object is some piece of named data it contains)

The Object.prototype property represents the Object prototype object. All objects in JavaScript are descended from Object; all objects inherit methods and properties from Object.prototype.

So our array object also inherits properties and methods from the Object prototype object. Now one of the methods of the Object prototype object is __defineSetter__

So what we are essentially trying to do here (in the script above) is say something like this :

Whenever there is any object that tries to set a property called 'ccNumber', execute the anonymous function that alerts the object itself. 

When did my array object try doing that ? - Digging in a little deeper !

Excellent reference :
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management

In order not to bother the programmer with allocations, JavaScript does it alongside with declaring values.

Allocation in JavaScript :Value initialization
var n = 123; // allocates memory for a number
var s = "azerty"; // allocates memory for a string 
var o = {
a: 1,
b: null
}; // allocates memory for an object and contained values 
// (like object) allocates memory for the array and 
// contained values
var a = [1, null, "abra"];
So when our array object gets executed, JS allocates memory for the array along with the values contained  in it, which in our case is a json object, which is nothing but just another object (as all it has is key value pairs). So JS again (like it did above for the array object) allocates memory for the object and the properties and values contained in it. 

And that's when the ccNumber property of the object gets initialized and when that happens, because of the __defineSetter__, the anonymous function gets called which is under the attacker's control as it is part of the attacker's webpage. 


So that's all about JSON hijacking. Please feel free to correct me if I went wrong somewhere (which I am sure I might have given my relatively less experience in the field)


Also worth noting would be that modern browsers (supporting ES4 + ) do not support setters being called when setting properties in object and array initializers.
Hence, the above trick may not work anymore.