How should web app developers defend against JSON hijacking?

The first defence is to stick to the specification by using valid JSON which requires an object as top level entity. All known attacks are based on the fact that if the top level object is an array, the response is valid Java Script code that can be parsed using a <script> tag.

If the JSON response contains any confidential/non-public data, only serve the response if the request is authenticated (e.g., comes with cookies that indicate an authenticated session).

That's the pre requisite for the attack, not a mitigation. If the browser has a cookie for site A, it will include it in all requests to site A. This is true even if the request was triggered by a <script> tag on site B.

If the JSON data contains anything confidential or non-public, host it at a secret unguessable URL (e.g., a URL containing a 128-bit crypto-quality random number), and only share this secret URL with users/clients authorized to see the data.

URLs are not considered a security feature. All the common search engines have browser addons/toolbars that report any visited URL back to the search engine vendor. While they might only report URLs that are explicitly visited, I wouldn't risk this for JSON URLS either.

Have the client send requests for JSON data as a POST (not a GET), and have the server ignore GET requests for JSON data.

This will prevent the <script> include.

Put while(1); at the start of the JSON response, and have the client strip it off before parsing the JSON.

I suggest a modified version of this approach: Add </* at the beginning. while(1) is problematic for two reasons: First it is likely to trigger maleware scanner (on clients, proxies and search engine). Second it can be used for DoS attacks against the CPU of web surfers. Those attacks obviously originate from your server .


Google uses "unparseable cruft" to defend itself against this type of attack. This vulnerability was fixed in firefox 3. The vulnerability arises from how browsers implement the JSON specification.


1) If the JSON response contains any confidential/non-public data, only serve the response if the request is authenticated (e.g., comes with cookies that indicate an authenticated session). 2) If the JSON data contains anything confidential or non-public, host it at a secret unguessable URL (e.g., a URL containing a 128-bit crypto-quality random number), and only share this secret URL with users/clients authorized to see the data.

There's no good reason to do both (1) and (2).

The first is ABAC and the second is ZBAC. Trying to get defense-in-depth by using multiple access-control schemes is just over-complicating things.

3) Put while(1); at the start of the JSON response, and have the client strip it off before parsing the JSON.

4) Have the client send requests for JSON data as a POST (not a GET), and have the server ignore GET requests for JSON data.

These sounds like fine ideas and do add defense in depth since it helps ensure that credentials can't be misappropriated.

Additionally,

5) Only serve JSON with sensitive data over SSL or some other secure channel.

to prevent leaking data via MITM.