

Why does Google prepend while(1); to their JSON responses? - gs7
http://stackoverflow.com/questions/2669690

======
Stealth-
I think it's important to note that this is a bug that effects older browsers
only. Modern IE, Chrome, and Firefox have security measures that do not allow
scripts to capture values passed to constructors of a literal. That way, this
hack is only needed for older browsers and will hopefully not be needed at all
in the future. For more info:
[http://stackoverflow.com/a/16880162/372767](http://stackoverflow.com/a/16880162/372767)

Also note that this attack, JSON Hijacking, is _different_ than a CSRF (Cross
Site Request Forgery) and has little to do with CSRF tokens.

~~~
joev_
Actually, ie is still vulnerable to a very similar attack in some cases,
specifically you can leak responses containing small json array by inlining
the json as a script[src=vbscript] tag. Disclosed here:
[http://en.wooyun.org/bugs/wooyun-2013-023](http://en.wooyun.org/bugs/wooyun-2013-023)

with the status "unable to contact the vendor or actively neglected by the
vendor" :-/

Edit: I meant "injecting" not inlining. Thanks chc for pointing that out.

~~~
chc
If it has to be inlined, how is that the same vulnerability? I thought the
vulnerability was that script tags can fetch external scripts and a local
script intercept the results. If you have to inline both scripts, you can only
attack yourself.

~~~
joev_
Sorry, used the wrong term. I mean it can be injected as a script tag into an
xdomain site.

------
tzury
There is a long discussion about this at

[https://news.ycombinator.com/item?id=5168121](https://news.ycombinator.com/item?id=5168121)

(from about a year ago)

------
frik
Chrome DevTools recognice while(1) and for(;;) in the network tab (JSON
preview). Sadly, Firebug still doesn't know how to handle this and shows no
JSON preview :(

------
andreyf
Does anyone know what browsers allow you to override the Array constructor? I
was under the impression that modern browsers don't.

~~~
pygy_
If the attacker knows the structure of the reply, `__defineSetter__` can be
used to extract the JSON content as well. From [0]:

    
    
            <script type="text/javascript"> 
                Object.prototype.__defineSetter__('Id', function(obj){alert(obj);});
            </script> 
            <script src="http://example.com/Home/AdminBalances">/*Boom*/</script>
    

[0]: [http://haacked.com/archive/2009/06/25/json-
hijacking.aspx/](http://haacked.com/archive/2009/06/25/json-hijacking.aspx/)

~~~
primaryobjects
That's interesting. Apparently, the __defineSetter__ call is still valid in
Chrome.

Example [http://jsfiddle.net/V53BL](http://jsfiddle.net/V53BL)

~~~
madeofpalk
I can't get this to work with an actual API call.

    
    
        <script>
              Object.prototype.__defineSetter__('user', function(obj){alert('Hijacked!');console.log('Hijacked!', obj)});
              var trigger = [{"user":{}}];
         </script>
         <script id='current-user' src="http://my.secretapi.com/users/current"></script>
    

Where the API returns something like

    
    
        [{'user':{'name':'Joe Bloggs'}}]
    

(Un)Fortunately (depending on which side of this you're on...) they've plugged
the holes?

~~~
primaryobjects
It works on an explicit set, but not on initialization of the object. So:

var x = [{"user":"dude"}]; This won't trigger, and this is what the script
include tag executes via the response.

x.user = "wow"; This will trigger, however.

~~~
gsnedders
And that's by design. That's how setters work. There's no security risk from
this, given cross-domain JSON loads.

------
CCs
A good description: [http://stackoverflow.com/questions/6339790/what-does-a-
ajax-...](http://stackoverflow.com/questions/6339790/what-does-a-ajax-call-
response-like-for-json-data-mean)

The idea: you need such workaround only if you return JSON Array.

Most of the API returns JSON Object in which case the attack does not work, it
will result in syntax error.

------
jbrackett
After seeing this I went to see if AngularJS had anything built in to mitigate
JSON hijacking and they do. It will strip ")]}',\n" off of json responses if
included from the server.

[http://docs.angularjs.org/api/ng.$http#description_security-...](http://docs.angularjs.org/api/ng.$http#description_security-
considerations)

------
ciniglio
So does this solve the problem with using remote JS templates (advocated by
DHH and 37s), what was outlined here [1]?

[1]:
[https://github.com/jcoglan/unsafe_sjr/blob/master/README.md](https://github.com/jcoglan/unsafe_sjr/blob/master/README.md)

~~~
homakov
it does, but it's worst workaround. we chose request.xhr? check

------
robocat
Would introducing a syntax error into my JSON help prevent CSRF attacks? We
don't use JSONP.

~~~
homakov
bug doesn't exist anymore

------
silon3
Is it correct to use the Content-Type application/json on this? IMO: not.

(I've just tested Firefox network view and it breaks the response display with
syntax error -- there should be an option to select the format).

------
matchu
It looks like modern Chrome doesn't trigger setters when constructing from
literals, so that's encouraging.
[http://jsfiddle.net/KY4Sa/](http://jsfiddle.net/KY4Sa/)

------
homakov
Google is wrong IMO: there is no need to have such workaround. In rails we had
similar problem
[https://community.rapid7.com/community/metasploit/blog/2013/...](https://community.rapid7.com/community/metasploit/blog/2013/12/29/remote-
js--an-insecure-pattern-in-rails-code) and fixed it by adding request.xhr?
check on server side.

while(1) is ugly solution to currently non-existing problem.

~~~
tzury
Does your solution assumes referrer will not be manipulated on the client
side?

~~~
homakov
my solution is request.xhr? check. the link above is only to explain what
rails-bug was. I don't think checking referrer is a good idea there.

~~~
joev_
Hey Egor, article author here. How come you are not such a fan of checking
referer? It cannot be a global fix (some sites depend on serving xdomain
scripts, have lots of users with proxies that alter headers etc), but it
should work well for many cases no?

~~~
homakov
it works of course, but to be compatible with many environments we need
something more reliable than Referrer.

------
frozenport
What happens when you visit a malicious website and your computer gets stuck
on `while(1)`? Syntax error would be better?

~~~
matchu
Because the script is useless, malicious websites won't bother including it,
so the folks at Google don't really care what it actually _does_. Or, if the
site wants to be malicious by just giving you a while(1), they can do that
without Google's help.

------
Kiro
Why doesn't this prevent CSRF?

~~~
yelnatz
CSRF is different from JSON hijacking, but they're closely related.

This only prevents attacks that uses a script to execute a get method and
returns a JSON array.

JSON arrays can be "executed" as if it was javascript. The attack relies on
modifying what javascipt does when this faux script is ran.

So if you put a "while(1);" in there, it prevents it from finishing. Thus
preventing the exposure of the sensitive data.

It's similar to CSRF since that attack relies on the user to have an active
session to be able to access sensitive data, but they differ in MO.

------
frik
Facebook uses "for(;;);" as it's one char shorter.

------
dontdownload
It's the bot.

------
alixaxel
Smart!

~~~
jbeja
What?

~~~
alixaxel
The while(1) to defeat hot-linking.

