JavaScript Object Notation (JSON) is a language and platform independent format for data interchange. JSON is in widespread use with a number of JSON parsers and libraries available for different languages. While some information is available for JSON hijacking this attack is not very well understood.
JSON Hijacking as the name suggests is an attack similar to Cross-Site Request Forgery where an attacker can access cross-domain sensitive JSON data from applications that return sensitive data as array literals to GET requests. An example of a JSON call returning an array literal is shown below:
[{"id":"1001","ccnum":"4111111111111111","balance":"2345.15"},{"id":"1002","ccnum":"5555555555554444","balance":"10345.00"},{"id":"1003","ccnum":"5105105105105100","balance":"6250.50"}]
This attack can be achieved in 3 major steps:
- Step 1: Get an authenticated user to visit a malicious page.
- Step 2: The malicious page will
try and access sensitive data from the application that the user is logged into.
This can be done by embedding a script tag in an HTML page since the
same-origin policy does not apply to script tags.
<script src="http://<json site>/json_server.php"></script>
- The browser will make a GET request to json_server.php and any authentication cookies of the user will be sent along with the request.
- Step 3: At this point while the malicious site has executed the script it does not have access to any sensitive data. Getting access to the data can be achieved by using an object prototype setter. In the code below an object prototypes property is being bound to the defined function when an attempt is being made to set the “ccnum” property.
Object.prototype.__defineSetter__('ccnum',function(obj){
secrets = secrets.concat(" ", obj);
});
- At this point the malicious site has successfully hijacked the sensitive financial data (ccnum) returned by json_server.php
It should be noted that not all browsers support this method; the proof of concept was done on Firefox 3.x. This method has now been deprecated and replaced by the use Object.defineProperty There is also a variation of this attack that should work on all browsers where full named JavaScript (e.g. pi=3.14159) is returned instead of a JSON array.
There are several ways in which JSON Hijacking can be prevented:
- Since SCRIPT tags can only generate HTTP GET requests, only return JSON objects to POST requests.
- Prevent the web browser from interpreting the JSON object as valid JavaScript code.
- Implement Cross-Site Request Forgery protection by requiring that a predefined random value be required for all JSON requests.

Good explanation.
Does it work on latest browsers (IE8) ?
Posted by: Satishb3 | 17 January 2013 at 04:52
Article is good. Keep it up!
But can you explain if you meant Cross Site Scripting rather than Cross Site Request Forgery. As, in my knowledge, an attacker can not access data using csrf attack but can generate an unauthorized requests from a victim’s machine to improperly initiate an action. So, its the victims machine which will receive the response and not the attacker's machine. In simple, CSRF can not be used to view someones data. XSS can be used to perform CSRF as well as to access the data, other than lot other flavors of the attacks like defacing, hijacking, etc.
Posted by: Security | 28 September 2012 at 05:22
The most easy way to prevent that is to always return JSON data as part of an object literal.
A valid JSON document can be a string, number, a boolean, null, an array literal, or an object literal.
In JavaScript, expressions are usually valid statements, which is why JSON data can potentially be executed as a script, with the exception of the object literal notation. If the document start by the curly brace of the object notation, it won't be valid script and then won't be executed. This hack will then not be able to access to the data.
In simple words, never return directly an Array, embed it into an object:
{"result": [{"id":"1001","ccnum":"4111111111111111","balance":"2345.15"},{"id":"1002","ccnum":"5555555555554444","balance":"10345.00"},{"id":"1003","ccnum":"5105105105105100","balance":"6250.50"}]}
Posted by: Amorgaut | 24 September 2012 at 16:58