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
How to Output an Iso 8601 Formatted String in JavaScript
How to Make a Promise from Settimeout
Constructors in JavaScript Objects
Are There Constants in JavaScript
Accessing Jpeg Exif Rotation Data in JavaScript on the Client Side
Mongodb, Remove Object from Array
How to Write a Named Arrow Function in Es2015
Trying to Fire the Onload Event on Script Tag
How to Debug JavaScript/Jquery Event Bindings with Firebug or Similar Tools
JavaScript % (Modulo) Gives a Negative Result for Negative Numbers
Getting Around X-Frame-Options Deny in a Chrome Extension
What Does (Function($) {})(Jquery); Mean
Read Environment Variables in Node.Js
Find Out Whether Chrome Console Is Open
Window.Onload VS <Body Onload=""/>
The Value of "This" Within the Handler Using Addeventlistener