Why Does Google Prepend While(1); to Their JSON Responses

Why does Google prepend while(1); to their JSON responses?

It prevents JSON hijacking, a major JSON security issue that is formally fixed in all major browsers since 2011 with ECMAScript 5.

Contrived example: say Google has a URL like mail.google.com/json?action=inbox which returns the first 50 messages of your inbox in JSON format. Evil websites on other domains can't make AJAX requests to get this data due to the same-origin policy, but they can include the URL via a <script> tag. The URL is visited with your cookies, and by overriding the global array constructor or accessor methods they can have a method called whenever an object (array or hash) attribute is set, allowing them to read the JSON content.

The while(1); or &&&BLAH&&& prevents this: an AJAX request at mail.google.com will have full access to the text content, and can strip it away. But a <script> tag insertion blindly executes the JavaScript without any processing, resulting in either an infinite loop or a syntax error.

This does not address the issue of cross-site request forgery.

Strip out while(1) prepended to JSON object

Try this:

var text = ajaxResponse.responseText;
var jsonObject = JSON.parse(text.replace('while(1);', ''));

Another way without using replace:

var jsonObject = JSON.parse(text.substring(text.indexOf(';') + 1);

Updated with your function:

function myFunction() {
$.get('/v1/servers').success(function(response) {
var data = JSON.parse(response.responseText.substring(text.indexOf(';') + 1));
data.servers.forEach(function(server){
presentServer(server);
});
});
}

while(1) JSON injection

Thank you Girish very much
works :

1.php

<?php
$time=time();
$hash=md5(mt_rand(1,200000));

$arr = array('time' => $time, 'hash' => $hash);
echo "while(1);".json_encode($arr);

ajax -side

responseText=req.responseText.substring(9);
var obj=JSON.parse(responseText);

statusElem.innerHTML = obj.hash

Why do people put code like throw 1; dont be evil and for(;;); in front of json responses?

Even without the for(;;); how would the attacker get the data?

Attacks are based on altering the behaviour of the built-in types, in particular Object and Array, by altering their constructor function or its prototype. Then when the targeted JSON uses a {...} or [...] construct, they'll be the attacker's own versions of those objects, with potentially-unexpected behaviour.

For example, you can hack a setter-property into Object, that would betray the values written in object literals:

Object.prototype.__defineSetter__('x', function(x) {
alert('Ha! I steal '+x);
});

Then when a <script> was pointed at some JSON that used that property name:

{"x": "hello"}

the value "hello" would be leaked.

The way that array and object literals cause setters to be called is controversial. Firefox removed the behaviour in version 3.5, in response to publicised attacks on high-profile web sites. However at the time of writing Safari (4) and Chrome (5) are still vulnerable to this.

Another attack that all browsers now disallow was to redefine constructor functions:

Array= function() {
alert('I steal '+this);
};

[1, 2, 3]

And for now, IE8's implementation of properties (based on the ECMAScript Fifth Edition standard and Object.defineProperty) currently does not work on Object.prototype or Array.prototype.

But as well as protecting past browsers, it may be that extensions to JavaScript cause more potential leaks of a similar kind in future, and in that case chaff should protect against those too.

Rack middleware to to prepend while(1); to all ajax/json requests

There's quite a lot of questions molded into one, I think.

The middleware itself would look something(haven't checked it, but it feels right) like this:

class AntiHijackingMiddleware
def call(env)
status, headers, body = @app.call(env) # save initial state

if env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" && headers['Content-type'].to_s.include?("application/json")
body = "while(1);"+body
headers['Content-Length'] = Rack::Utils.bytesize(body.to_s).to_s
end

[status, headers, body]
end
end

You can add additional conditions on env["REQUEST_URI"] to do url matching.

Adding it to Rails' middleware stack is boilerplate.

Is there a proper way to parse JSON prepended with a loop in JavaScript?

this feels like a crude and hackish way to handle it and it only accounts for one possible variation.

No, it's exactly what you would do. Or even less generic, .slice(9). Servers don't prepend arbitrary or even dynamically generated loops, they use the shortest/simplest possible one to prevent JSON hijacking. So you have to deal only with that particular prefix used by the service your are requesting.



Related Topics



Leave a reply



Submit