XSS Prevention in GMail
28 February, 2011 § Leave a comment
Many popular web applications use JSON as their data interchange format. The format is very compact, easy for humans to read, and is based on a subset of JavaScript.
I’ll start by showing an example. Consider a website that wants its clients to query the server for the most recent 3 public messages. The client may send a GET
query to the following address: https://mail.google.com/recent_messages/
The response can be written as follows:
var messages = [ {"user": "foo", "m": "I like turtles", "t": 123423550}, {"user": "bar", "m": "Turtle power!", "t": 1234543245}, {"user": "baz", "m": "Cowabunga dude", "t": 1234567643} ];
When mail.google.com
requests this JSON feed, it could then run eval()
on the source code. Afterwards, it will have a messages
object in global scope that it can reference.
This could work out good for GMail, but it can also allow other websites to make the same call. Modern web browsers will not allow asynchronous HTTP requests to cross domain boundaries, so it is easy to think that this is safe. However if the location is added as the src
attribute of a script
tag, then the browsers will load the content.
To work around this, GMail adds while(1);
to the beginning of the JSON response.
When requesting JavaScript through a script
tag’s src
attribute, the DOM does not give access to modifying the content of the response. This keeps the while(1);
present. If a client tries to eval()
this JSON request, their browser will simply hang.
Pretty interesting, huh? There still are workarounds that can defeat this, such as setting up a server-side proxy that will make the request and strip the while(1)
.
If you’re looking for more details, Adobe Labs has a page on their website that covers Preventing the Execution of Unauthorized Script in JSON.
Leave a Reply