
Why does Google prepend while(1); to their JSON responses? - vikas0380
http://stackoverflow.com/q/2669690/1922352
======
c0achmcguirk
I believe this hack (JSON Hijacking) was discovered by Jeremiah Grossman in
2005[1].

It's fascinating to read how he discovered it and how quickly Google
responded.

[1] - [http://blog.jeremiahgrossman.com/2006/01/advanced-web-
attack...](http://blog.jeremiahgrossman.com/2006/01/advanced-web-attack-
techniques-using.html)

------
samfisher83
Why don't browsers strip cookies when they are doing cross domain javascript
fetches?

~~~
vbezhenar
Because that's the way internet works and breaking it means breaking a lot of
websites. Web security wasn't thought carefully when web was built, it's just
a bunch of dirty hacks around most obvious vulnerabilities.

~~~
captainmuon
It would be easy to make sending credentials opt-in in a new HTTP or HTML
version. The way it's done now is backwards IMHO.

Define httpsb:// do be like [https://](https://), but any site may make ajax
and similar requests to it (without credentials). Then make some kind of
exception (like csrf protection), or use legacy https, in case you need to
send cookies.

~~~
0x0
But an attacker would simply use <script src="[https://.."](https://.."),
instead of <script src="httpsb://.." ?

~~~
MereInterest
Only if that is supported by the site being attacked. If the site only accepts
httpsb connections, then the attacker would not have a way in.

~~~
hdhzy
If the site accepts httpsb it can as well support the Origin header [0] and
the problem is solved.

[0]:
[https://wiki.mozilla.org/Security/Origin](https://wiki.mozilla.org/Security/Origin)

~~~
kuschku
The whole point is to allow any site to access any other site, just like plain
TCP sockets, without stealing your cookies.

If the site wants to access google.com with its own cookies, fine, why not?

~~~
hdhzy
Could you elaborate on the "stealing your cookies" part?

Cookies are sent only to the origin that set them and (except XSS attacks) are
not revealed to anyone else. So who exactly is stealing them?

~~~
kuschku
Well, currently, nothing. But currently, the web is completely broken.

If you want web-applications to be powerful, and open, you also need to be
able to have any web application to access any URL.

Why should only mail.google.com be able to access my emails, and not also my-
little-opensource-webmail.com ?

To faciliate that, without also adding cookie stealing back in, you need to
allow any website to open standard TCP sockets.

------
westoque
I wondered the same thing years ago. I always thought that browsers would have
implemented other security measures so that websites avoid doing this.

Around 90 something percent of websites I visit don't implement that `for(;;)`
or `while(1)` solution.

So are we saying that they're vulnerable sites?

~~~
minitech
No, they’re not vulnerable; browsers fixed this bug a long time ago.

------
xg15
I had a hunch that this is to prevent people from including the resource in a
script tag - but I always wondered how they'd access the data as a JSON
expression on its own should technically be a no-op when interpreted as JS (or
so I thought).

The overridden array constructor was the missing link.

Though couldn't you have it easier by making sure your top-level JSON
structure is always an object?

As far as I know, while a standalone array expression []; is a valid JS
statement, a standalone object expression {}; is not and would produce a
syntax error.

~~~
eriknstr
Someone had the same question as you in a comment.

>Wouldn't returning an object containing the array, instead of the array
directly, also solve the problem?

And someone else replied

>No, that wouldn't solve the problem since the same attacks mentioned in the
post could still be performed. Overriding the accessor methods to retrieve the
info.

~~~
wtetzner
Except I don't think a JSON object is valid Javascript by itself.

~~~
aetherson
What about a JSON object do you think is invalid Javascript?

~~~
wtetzner
It's a valid subset of Javascript (or at least was initially meant to be), but
a JSON object (as opposed to an array) isn't a valid stand-alone Javascript
expression, and an attempt to eval it will return an error:

    
    
        > eval('{"key": "value"}');
        SyntaxError: missing ; before statement
    

You can get around this by using parens:

    
    
        > eval('({"key": "value"})');
        Object { key: "value" }
    

But accidentally including a JSON URL in a script tag should fail to evaluate
if there's an object at the top level.

------
zoren
That is one weird array in Google's reply. Looks like it could have been an
object instead, whereby JSON hijacking wouldn't be a problem.

------
maambmb
I feel like the browser could use the Content-Type header to check whether the
response is JSON or actual executable javascript - throwing an error if the
former

------
CaliforniaKarl
I haven't worked with JSON like that before. Do JSON parsers properly ignore
the stuff Google puts in, or do you have to strip it out before parsing?

~~~
RKearney
In the very first stack overflow answer:

    
    
      > an AJAX request at mail.google.com
      > will have full access to the text content,
      > and can strip it away.

------
NewEntryHN
Google use cookies to authenticate API requests?

~~~
stanleydrew
Not sure if they do, but why not? It's just an opaque token in the HTTP
request content, same as any other opaque token.

------
the_mitsuhiko
Pretty sure browsers no longer permit overriding ctors for literals.

~~~
gavinpc
The John Resig post linked by TFA indicates that this was originally dealt
with by locking the constructor altogether:

    
    
       function Array(){
         alert("hello, I found something of yours!");
       }
       // ERROR: redeclaration of const Array
    

But it appears that the restriction now applies only to literals, as I can do
this in at least Chrome and Firefox:

    
    
        function Array() {console.log("hope")}
        undefined
        var x = new Array(3);
        hope
        undefined
    

[https://johnresig.com/blog/re-securing-json/](https://johnresig.com/blog/re-
securing-json/)

------
winteriscoming
Everytime I read about such constructs, it makes me realize, as a regular
developer, how complex web application security is and how difficult it is to
think about and cover your application against each and every such potential
problem.

~~~
trav4225
Yup! In my personal (and basically worthless) opinion, this is why the entire
"web application" ecosystem is a giant, flawed mess. It's basically what
happens when a system originally designed to represent and transfer rich
textual documents (HTML/HTTP) is bastardized into a application architecture.

Yes, I'm being somewhat hyperbolic. Bring on the downvotes! ;-)

~~~
ef4
This kind of criticism misses the point. The web is not designed. It is
evolved. Various bits of it were designed at their outset, but it was
literally impossible to envision all the implications of those design
decisions.

This is not a bad thing, for the simple reason that every long-lived complex
system involving many humans _must_ behave this way.

Any attempt to top-down design the perfect, universal, distributed application
runtime hits fundamental social problems not unlike those in a centrally
planned economy: too much information to integrate, too many stubbornly
uncooperative humans with their own divergent goals and opinions.

Systems at this scale are much more like biology than like circuit design.

~~~
jondubois
Also JavaScript itself was designed to evolve in a backwards-compatible way.
The way developers use JavaScript today is quite different from how they used
it 10 years ago.

The idea that systems are fixed entities that have to be designed correctly
up-front is wrong and is one of the reasons why the Waterfall model of
software development has been superseded by Agile.

Good systems have to be designed to handle change. Change is the only constant
thing in this world.

------
frik
FB prepends a "for(;;);" which is 1 char shorter than "while(1);", has been
the case since 2012/13.

Firebug v2 and ChromeTools know how to parse such JSON and ignore that first
part. (IE11 and Firefox newer DevTools can't "handle" it aka show just a plain
text string)

~~~
Lxr
Why does it have to be a loop, couldn't you make a reliable syntax error in
less than 8 characters?

~~~
jcoffland
8 chars is already pretty short. If you're concerned about the length, don't
be. A TCP packet is at least 512 bytes.

~~~
kevan
This is definitely the sort of thing you'd want to gather data on. It's
plausible that it could save Terabytes of bandwidth per day at Facebook/Google
scale.

~~~
zepolen
That's like saying a car wash can save 3 drops of water at the end of the day.

------
Animats
Why not "while(0)"? Then an eval wouldn't do anything.

~~~
orf
Because it's not about eval(), as the link you're commenting on explains in
detail?

~~~
adrianmalacoda
If I'm understanding it correctly, though, prepending while(0) or even if(0)
to the JSON would prevent the attack, because the JSON object would not
actually be executed. I think they were asking if there was any particular
reason to prefer the infinite loop over that.

The answer that comes to mind for me is that having the script hang is a more
obvious failure state than simply skipping over the statement, and makes it
more immediate that something has gone wrong.

------
tossaway322
Jeez, why not live w/o JavaScript?

We keep trying to accomodate a defunct language with insoluble problems. Isn't
that an error in our thinking processes?

[https://www.wired.com/2015/11/i-turned-off-javascript-
for-a-...](https://www.wired.com/2015/11/i-turned-off-javascript-for-a-whole-
week-and-it-was-glorious/)

~~~
_pmf_
Not only that. They keep piling on new shit APIs. Half of the WebGL exploits
are probably yet unveiled, there's a side channel attack using the new ambient
light sensor API, but hey, my phone can get darker based on ambient light,
hooray!

