7 ms·
Why does Google prepend while(1); to their JSON responses?
- andreyf 13y agoDoes anyone know what browsers allow you to override the Array constructor? I was under the impression that modern browsers don't.
- pygy_ 13y agoIf 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/
- Jare 13y agoES4 requires using the original, unmodified bindings. From a comment: http://stackoverflow.com/questions/16289894/is-json-hijacking-still-an-issue-in-modern-browsers/16880162#16880162 http://stackoverflow.com/questions/16289894/is-json-hijackin...
- primaryobjects 13y agoThat's interesting. Apparently, the __defineSetter__ call is still valid in Chrome. Example http://jsfiddle.net/V53BL http://jsfiddle.net/V53BL
- madeofpalk 13y agoI 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 13y agoIt 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 13y agoAnd that's by design. That's how setters work. There's no security risk from this, given cross-domain JSON loads.
- gsnedders 13y agoNo current browser should be vulnerable to this (ES5 requires object literals use [[DefineOwnProperty]], not [[Put]], and hence no setter on the prototype chain should be called). I believe all browsers have since fixed this.
- matchu 13y agoHere's a quick fiddle to check. This trick doesn't seem to work on Chrome 31. http://jsfiddle.net/g9R5s/ http://jsfiddle.net/g9R5s/
- aboodman 13y agoI do not think this particular attack works in any modern browser anymore. However, the while (1); (or similar tricks) is an easy defense-in-depth measure in case browsers regress in this area or new attacks are found.
- matchu 13y agoIt looks like modern Chrome doesn't trigger setters when constructing from literals, so that's encouraging. http://jsfiddle.net/KY4Sa/ http://jsfiddle.net/KY4Sa/
- frozenport 13y agoWhat happens when you visit a malicious website and your computer gets stuck on `while(1)`? Syntax error would be better?
- mbetter 13y agoYou have to throw out your computer and buy a new one.
- matchu 13y agoBecause 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.
- Jare 13y agoI recall IE showed a dialog on javascript errors to ask if the user wanted to continue. An infinite loop will get the entire script aborted because there's no obvious way to continue.
- Stealth- 13y agoI 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.
- maxtaco 13y agoI think Jakub P. was implying that the CSRF-token defense could also guard against this attack.
- smsm42 13y agoWell, one thing to do with the tokens might be that if the token were required for the GET request in question, then stealing the content via script tag may be harder. OTOH, putting one-time tokens on every request might be a bit too much for many apps, while(1) hack may be more efficient.
- deathanatos 13y ago> Modern [browsers] have security measures that do not allow scripts to capture values passed to constructors of a literal. Actually, it's not security measures so much as implementing ECMAScript 5, which explicitly says that array literals must use the built-in constructor, not any override. See 11.1.4 [1], which reads: > Let array be the result of creating a new object as if by the expression new Array() where Array is the standard built-in constructor with that name. Object works similarly, and is in 11.1.5. I'm not certain what earlier standards said here, but I suspect they didn't say anything. [1]: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf http://www.ecma-international.org/publications/files/ECMA-ST...
- jbri 13y agoOf course, the reason that language was introduced into the standard was primarily to mitigate this sort of attack.
- alixaxel 13y agoSmart!
- Kiro 13y agoWhy doesn't this prevent CSRF?
- yelnatz 13y agoCSRF 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.
- evan_ 13y agoThis is specifically dealing with reading results from a remote script- with a CSRF you often (usually? Always?) don't care about the result, because the damage has been do e by the time you are successfully able to send an authenticated request.
- robocat 13y agoWould introducing a syntax error into my JSON help prevent CSRF attacks? We don't use JSONP.
- homakov 13y agobug doesn't exist anymore
- ciniglio 13y agoSo 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 13y agoit does, but it's worst workaround. we chose request.xhr? check
- homakov 13y agoGoogle 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/12/29/remote-js--an-insecure-pattern-in-rails-code https://community.rapid7.com/community/metasploit/blog/2013/... and fixed it by adding request.xhr? check on server side. while(1) is ugly solution to currently non-existing problem.
- tzury 13y agoDoes your solution assumes referrer will not be manipulated on the client side?
- homakov 13y agomy 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.
- tzury 13y agoSorry Egor, I thought you are pointing out an article you have published.
- homakov 13y agoThis is joev's article. His explanations of the issue are better than mine ;)
- joev_ 13y agoHey 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 13y agoit works of course, but to be compatible with many environments we need something more reliable than Referrer.
- tzury 13y agoThere 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 13y agoFacebook uses "for(;;);" as it's one char shorter.
- frik 13y agoChrome 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 :(
- silon3 13y agoIs 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).
- blhnigga 13y agoI know why ask me!
- dontdownload 13y agoIt's the bot.
- jbrackett 13y agoAfter 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-considerations http://docs.angularjs.org/api/ng.$http#description_security-...
- CCs 13y agoA good description: http://stackoverflow.com/questions/6339790/what-does-a-ajax-call-response-like-for-json-data-mean http://stackoverflow.com/questions/6339790/what-does-a-ajax-... 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.