Sometimes we’re asked for guidance on something and the result seems worth sharing; this one is about useful things to consider when using JSON for information that needs to stay secret.
If you’re using JSON for private data; make sure you’ve fixed the CSRF side of things and everything will be OK. If you want to try to protect yourself in the (hopefully unlikely) event of your CSRF protection mechanisms failing, read on.
There are 4 ways commonly used ways to transfer JSON data:
1) JSONP
2) var assignment
3) JavaScript arrays
4) plain JSON (e.g. native browser JSON support, or Crockford’s json2.js)
Of these, I can only really recommend using option 4. Let’s look at the known attacks against the others to understand why:
JSONP and var assignment are similar and designed to achieve the same goal; allow an application to consume JSON data from a server in a different domain. In the first, the data is wrapped such that the response from the server is a valid script that will call a function in the embedding application with an object supplied by the server:
callback({"secret":"the treasure is buried under the tall tree"});
In the second, the data is wrapped such that the response is a valid script that will assign the object supplied by the server to a variable that can then be accessed by the embedding application.
var result ={"secret":"the treasure is buried under the tall tree"};
Despite being designed to allow an application to consume data from servers on multiple domains, these techniques have often been used for another reason; until the advent of native JSON support in browsers, JSONP was faster (and scaled better) than the alternative means of consuming data.
The standard JSONP and var assignment attacks are essentially the same; they rely on the fact that the attacker is able to either predict or control the name of the destination; whether that be a callback or variable.
Some implement JSONP or var assignment in such a way that the destination is not predictable to the attacker (derived from session information, or similar); this alone does not guarantee the safety of the data as attacks exist against some browsers that still allow the attacker to extract any information contained (read on for a description of some such techniques).
The use of JavaScript arrays has been the cause of several well documented attacks in the past, most notably Jeremiah Grossman’s gmail contact hack. This made use of a combination of two factors: 1) that, in some older browsers, it was possible to clobber the Array constructor to steal data from arrays and 2) javascript arrays, unlike valid JSON (which should be contained within a JavaScript object), are directly executable as script by the browser.
While the above attack is not possible on any current browsers,various people have developed variants of the Array constructor attack (including attacks on javascript objects), some of which are purported to work on newer browsers in some cases (although I can’t reproduce these results), so the use of any JSON technique which results in responses that are directly executable as script is to be discouraged.
Oren Ofer wrote on