Why Do People Put Code Like "Throw 1; <Dont Be Evil>" and "For(;;);" in Front of JSON Responses

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.

How do I get jquery.Ajax to work with throw 1; dont be evil in front of json responses?

You should probably remove the beginning part from the response:

$.ajax(url, {
dataType: "jsonp text",
success: function(data) {
var jsonString = data.replace(/^throw 1; <dont be evil> /, "");
var responseObject = $.parseJSON(jsonString);

// do something with responseObject
...
}
}


UPDATE:

To make the re-writing available in every Ajax call you could also register a global Ajax Converter in jQuery:

$.ajaxSetup({
converters: {
"text cleanedjson": function(data) {
var jsonString = data.replace(/^throw 1; <dont be evil> /, "");
return $.parseJSON(jsonString);
}
}
});

$.ajax(url, {
dataType: "jsonp cleanedjson",
success: function(responseObject) {
// do something with responseObject
...
}
});

You will still need to specify your defined dataType in the request options.


UPDATE 2:
If you need to tweak your existing calls to do the response cleanup automatically, you could patch jQuery's ajax implementation to automatically use your converter in certain situations:

// store reference to original implementation
$._ajax_original = $.ajax;

// redefine jQuery's ajax function
$.ajax = function(url, settings) {
if (… your test for applicability here (e.g. an url check) …) {
settings.dataType = "jsonp cleanedjson";
}
return $._ajax_original(url, settings);
};


Note that this redefinition has to included after loading jQuery and before the first Ajax call is made. You may also need to consider that $.ajax can also be called without a separate url parameter...

Is facebook suddenly safe against JSON hijacking?

This attack (loading JSON as a <script>) is based on a few assumtions:

1) The JSON is itself valid JS (thats what the for(;;) changes), which also means that it may not start with a { as that is a block statement, which does not contain key-value pairs:

 { "a": 1 } // invalid JS, valid JSON *
[{ "a": 1 }] // valid JS, valid JSON

2) The browser is very old (< 1% of the total users), as constructing arrays with the literal does not call the Array function in newer browsers (ES5 support is a good estimation for those).

Therefore this attack isn't possible in this case, as the API you mentioned returns an object, therefore (1) is not fullfilled. And even if the API would return an array, only a very small amount of people could theoretically be hijacked:

1) The browser has to be very old, and then the browser itself is probably a bigger risk, and the browser has to even support JavaScript.

2) The client has to visit a malicious site, which is very unlikely due to spam filters / blacklists at various levels.

3) The user has to be logged in at facebook while visiting the malicious website.

Worth to mention that there are still others responses with infinite loop

I guess this is generally a thing of the past. It will take a while until all APIs got refactored / migrated. I assume adding/removing these 5 characters causes a significant overhead if you think at Facebook's scale.


*: If you try to load { a: 1 } you'll find out that it does not throw a SyntaxError! However this is neither valid JSON, nor does it create an object (it's a labelled 1 inside of a blocn statement).

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.

What does a Ajax call response like 'for (;;); { json data }' mean?

I'm a bit late and T.J. has basically solved the mystery, but I thought I'd share a great paper on this particular topic that has good examples and provides deeper insight into this mechanism.

These infinite loops are a countermeasure against "Javascript hijacking", a type of attack that gained public attention with an attack on Gmail that was published by Jeremiah Grossman.

The idea is as simple as beautiful: A lot of users tend to be logged in permanently in Gmail or Facebook. So what you do is you set up a site and in your malicious site's Javascript you override the object or array constructor:

function Object() {
//Make an Ajax request to your malicious site exposing the object data
}

then you include a <script> tag in that site such as

<script src="http://www.example.com/object.json"></script>

And finally you can read all about the JSON objects in your malicious server's logs.

As promised, the link to the paper.

What type is it, json gzip

Try something like:

//Get actual response from server; here we use a hardcoded response
var response = "for (;;);{\"__ar\":1,\"payload\":null,\"domops\"....";

var fixedresponse = response.Substring(9);

Or, alternatively:

var fixedresponse = new Regex(@"^for \(;;\);").Replace(response, string.Empty);

Or...

var fixedresponse = response.Substring(response.IndexOf("{"));

Or, alternatively (but less 'safe' since the actual JSON content may also contain an empty for-loop):

var fixedresponse = response.Replace("for (;;);", string.Empty);

...or any other string operation you can think of actually; whatever gets the job (removing the stuff before the actual JSON) done.

You can read the "possible duplicates" I editted in your question for an explanation on why the empty for-loop is there in the first place.

Add unparsable cruft to ASP.NET MVC JsonResult

You could write a custom action result to perform this:

public class SafeJsonResult: JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.Write("</*");
base.ExecuteResult(context);
}
}

and then use it instead of the default one:

public ActionResult Index()
{
return new SafeJsonResult
{
Data = new { Foo = "bar" },
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
};
}


Related Topics



Leave a reply



Submit