A week ago Joe Walker posted a note on the insecurity of JSON. I’m using JSON for almost anything so I was shocked a bit by his findings. Sleepless nights went by and then I thought of a counter hack so one could secure his JSON again. I remembered a post by Dean Edwards (yeah, the packer guy) about subclassing Array objects. In this article I’ll present a way to take over the hacked Array object, and secure it again.

Summary: Subclassing the Javascript Array object

This is just a summary of the post on the blog of Dean Edwards about subclassing the Array object. This is what he learned me:

Every JavaScript environment (i.e. a browser window or iframe) has its own copy of the
core JavaScript objects and classes. What if we “borrow” one of those objects?

// create an iframe
var iframe = document.createElement("iframe");
iframe.style.display = "none";
document.body.appendChild(iframe);

// write a script into the iframe and steal its Array object
frames[frames.length - 1].document.write(
   "<script>parent.Array2 = Array;<\/script>"
);

Array2.prototype.each = function(iterator) {
    // iterate
};

var list1 = new Array(1, 2, 3);
list1.each(print); // => ERROR!

var list2 = new Array2(1, 2, 3);
list2.each(print); // => 1, 2, 3

// hooray!

Ok, this code shows us how to create a clean, ‘unprototyped’ Array2 object, which acts the same as a native Array object.

Summary: JSON is not as safe as people think it is

This is a summary of the post by Joe Walker about the insecurity of JSON.

I believe that JSON is unsafe for anything but public data unless you are using unpredictable URLs.

There are 2 problems. CSRF (Cross Site Request Fogery) allows attackers to bypass cookie based authentication. I blogged about it a while ago. Wikipedia talks about it. CSRF allows you to invoke cookie protected actions on a remote server. It allows Mr. Evil to trick Mrs. Innocent into transferring money from her bank account into his.

Far less known perhaps, is the JSON/Array hack that allows a user to steal JSON data on Mozilla and any other platform with a modern JavaScript interpreter.

function Array() {
  var obj = this;
  var ind = 0;
  var getNext = function(x) {
    obj[ind++] setter = getNext;
    if (x) alert("Data stolen from array: " + x.toString());
  };
  this[ind++] setter = getNext;
}

var hack = [ 42 ]; //=> alerts 42

Applying the fix

You’ll probably know by now which way we’re heading. When the Array hack’s been applied we need to clean up the hacked Array object. Dean’s showed us a simple way by taking the Array object from an iframe and overwrite the one in the parent document. Here’s the fix, you can test it here:

var applyArrayHack = function(){
	//hackzor the Array object using Joe Walker example
	this.Array = function() {
	  var obj = this;
	  var ind = 0;
	  var getNext = function(x) {
	    obj[ind++] setter = getNext;
	    if (x) alert("Data stolen from array: " + x.toString());
	  };
	  this[ind++] setter = getNext;
	};
};

var applyArrayFix = function(){
	//Create an iframe, I know this is not the best way,
	//doesn't work in Safari blah blah
	var iframe = document.createElement("iframe");
	iframe.style.display = "none";
	document.body.appendChild(iframe);

	//Write a script into the iframe and steal its Array object
	//Overwrite the hacked Array with the one from the iframe.
	frames[frames.length - 1].document.write(
	    "<script>parent.Array = Array;<\/script>"
	);
};

applyArrayHack(); //apply the hack
var hack1 = [ 40 ]; //=> alerts 40

applyArrayFix(); //apply my fix
var hack2 = [ 40 ]; //=> doesn't alert! Yay!

The downside

The downside of this fix is that you don’t know when to apply the fix. A hacker can use a delayed or interval function to apply the hack, so basically each time you touch an Array object you’ve to apply the fix to be sure it’s safe to send data.

Update: note on security

Because a lot of so-called ‘security experts’ are saying I’m not improving security with this experiment I’m adding this paragraph. The main reason I wrote this article is because I wanted to show that a hack like the one Joe Walker showed us isn’t making JSON more insecure than it already is. I am aware of the fact that Mr. Evil can break this fix like a snap. I totally agree with Joe:

I believe that JSON is unsafe for anything but public data unless you are using unpredictable URLs.

Please stop bugging me about it.