November 29, 2009 - 17:31 UTC - Tags: jsonp security xss jquery
In my previous posts
JSONp - What's the risk? and
Web2.0 - Who do you trust? I talked about the potential security problems that can occur when adding script tags and/or using jsonp. In this post I will show a couple of demos.
Demo setupThe demo setup is quite easy. I've setup up two javascript files, where one of them is contains some jsonp data, while the other one contains the same jsonp data + some javascript running inside the json object.
nice.js.php:callback({date:"17:11:36"});
evil.js.php:callback({date:"17:11:19", nothing: alert("XSS")});
Additionally I've setup up four different HTML pages. Common for all of them, is that they will load one of the two javascripts and try to replace the contents of a span tag with the data in the date property of the json object.
The pages are:
scriptonly_nice.html - Loads nice.js.php by adding a script tag using normal javascript and DOM manipulation
scriptonly_evil.html - Loads evil.js.php by adding a script tag using normal javascript and DOM manipulation
jquery_nice.html - Loads nice.js.php by using jQuery's
$.get(..., "jsonp")jquery_evil.html - Loads evil.js.php by using jQuery's
$.get(..., "jsonp")ResultsNot surprisingly, in both cases where we load the evil.js.php, the javascript inside the json object runs, and we get the popup box. Because we are loading the data client side, and the page and scripts come from different domains (which is normally the case when loading data via jsonp), the cross domain policy prevents the script in the page from reading or manipulating the code behind the json object before it's run. When loading the script, either via javascript directly, or by using jQuery, a script tag is added, the script loaded and the code behind it runs. There is no way to prevent this or do validation when using jsonp with data from different domains directly into the browser. Our only option is to trust that the remote domain has good intentions (delivers data only) and is not hacked. The only way to load the data securely, would be to load it through a proxy on the server, and do validation in the proxy before letting the jsonp data through to the browser.
Note that this is not a critique of jQuery. jQuery works as expected. This is a problem with jsonp as an integration method.