42

What is the best defense against JSON hijacking?

Can anyone enumerate the standard defenses, and explain their strengths and weaknesses? Here are some defenses that I've seen suggested:

  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.
  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.

Are these all secure? Are there any reasons to choose one of these over the others? Are there any other defenses I'm missing?

Hendrik Brummermann
  • 27,118
  • 6
  • 79
  • 121
D.W.
  • 98,420
  • 30
  • 267
  • 572

3 Answers3

28

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 .

Hendrik Brummermann
  • 27,118
  • 6
  • 79
  • 121
  • when it comes to authenticated data: Make sure to additionally use Challenge Tokens in your application against CSRF-attacks, this makes JSON Hijacking very hard. – GNi33 Sep 10 '11 at 00:00
  • Is doing only 1) from this list a good protection against JSON hijacking? I [read](http://stackoverflow.com/a/3147804/841064) that it's possible to override behaviour of Object but I can't reproduce it in modern browsers. Is it reproducible? – Andrei Botalov Dec 09 '11 at 21:07
  • 1
    @AndreyBotalov, no, it is not sufficient as there is still a large number of users out there which use browsers that still allow redefining of build in functions. – Hendrik Brummermann Dec 09 '11 at 21:57
  • What browsers allow redefining of built in functions that may be used by attacker to hijack JSON if only 1 item is done? – Andrei Botalov Dec 12 '11 at 16:32
  • 1
    @AndreyBotalov, the first hit on google is a document from 2007 naming Firefox 2, Opera 9, and Safari 3 as being vulnerable to the array redefinition. A bit further down is an article from 2009 naming Chrome 2.0.172.31 and Firefox 3.0.11 for the Object.prototype.__defineSetter__ attack. Spending a bit more time on this is likely to return more recent articles on more recent browsers. But as those old browser are still in use, this does not make much of a difference anyway. – Hendrik Brummermann Dec 12 '11 at 17:59
  • Question - see: http://www.sitepen.com/blog/2008/09/25/security-in-ajax/ - a different cruft method - and, does serving the json over SSL prevent hijacking and protection of the json data? – Jason Apr 26 '12 at 17:50
  • 7
    The spec does allow an array as a top level object - your post suggests though that this is not valid JSON. Your answer still stands though (+1) and having a top level object is (currently) secure against hijacking. – SilverlightFox Nov 21 '13 at 12:10
  • 3
    An array as the top-level structure is very valid, see [RFC 4627](https://tools.ietf.org/html/rfc4627) for details. Most JSON parsers even consider primitive literals alone as valid JSON. – Bergi Feb 26 '14 at 04:17
  • Anyone can put "while(1);" on their own site to "DoS attack" a web surfer. You don't need to send a cross-origin get request to an endpoint serving json arrays to make "while(1);" happen. – Alexander Taylor Dec 19 '17 at 18:11
  • You could also add the following to the json `{"
", "
"}` (or some variation of that, a `
` ([Line Seperator U+2028](http://www.fileformat.info/info/unicode/char/2028/index.htm)) is not a valid character in javascript (so it gives a parse error before running any code), but is valid in JSON, because JSON is not a subset of Javascript (Edit: SE filters out the character, so I cannot post it lterally, – Ferrybig Mar 27 '18 at 08:03
3

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.

Bob Stein
  • 175
  • 1
  • 7
rook
  • 46,916
  • 10
  • 92
  • 181
2

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.

Mike Samuel
  • 3,873
  • 17
  • 25
  • Question - see: sitepen.com/blog/2008/09/25/security-in-ajax - a different cruft method - and, does serving the json over SSL prevent hijacking and protection of the json data? – Jason Apr 26 '12 at 17:51