Over the holidays I had a chance to talk to some of my old compadres from the XML team at Microsoft and we got to talking about the JSON as an alternative to XML. I concluded that there are a small number of key reasons that JSON is now more attractive than XML for kinds of data interchange that powers Web-based mashups and Web gadgets widgets. Expect a series of posts on this later today. 

I wasn't sure I was going to write about this until I saw Mike Arrington's blog post about a GMail vulnerability which implied that this is another data point in the XML vs. JSON debate. On reading about the vulnerability on Slashdot I disagree. This seems like a novice cross site scripting vulnerability that is independent of JSON or XML, and is succintly described in the Slashdot comment by TubeSteak which states

Here's the super simple explanation

1. Gmail sets a cookie saying you're logged in
2. A [3rd party] javascript tells you to call Google's script
3. Google checks for the Gmail cookie
4. The cookie is valid
5. Google hands over the requested data to you

If [3rd party] wanted to
keep your contact list, the javascript would pass it to a form and your computer would happily upload the list to [3rd party]'s server.

Mitigations to this problem are also well known and are also summarized in another Slashdot comment by buro9 who writes

When you surface data via Xml web services, you can only call the web service on the domain that the JavaScript calling it originates from. So if you write your web services with AJAX in mind exclusively, then you have made the assumption that JavaScript is securing your data.

The problem is created at two points:
1) When you rely on cookies to perform the implicit authentication that reveals the data.
2) When you allow rendering of the data in JSON which bypasses JavaScript cross-domain security.

This can be solved by doing two things:
1) Make one of the parameters to a web service a security token that authenticates the request.
2) Make the security token time-sensitive (a canary) so that a compromised token does not work if sniffed and used later.
.

The surprising thing is that I'd assumed that the knowledge of using canary values was commonplace but it took a lot longer than I expected to find a good bite size description of them. And when I did, it came from co-worker Yaron Goland in a comment to Mark Nottingham's post on DOM vs. Web where Yaron wrote

There are a couple of ways to deal with this situation:

Canaries - These are values that are generated on the fly and sent down with pages that contain forms. In the previous scenario evil.com wouldn't know what canary site X was using at that instant for that user and so its form post wouldn't contain the right value and would therefore be rejected. The upside about canaries is that they work with any arbitrary form post. The downside is that they require some server side work to generate and monitor the canary values. Hotmail, I believe, uses canaries.

Cookies - A variant on canaries is to use cookies where the page copies a value from a cookie into the form before sending it up. Since the browser security model only allows pages from the same domain to see that domain's cookie you know the page had to be from your domain. But this only works if the cookie header value isn't easily guessable so in practice it's really just canaries.

XMLHTTP - Using XMLHTTP it's possible to add HTTP headers so just throw in a header of any sort. Since forms can't add headers you know the request came from XMLHTTP and because of XMLHTTP's very strict domain security model you know the page that sent the request had to come from your site.

I guess just because something is common knowledge among folks building Web apps and toolkits at Microsoft doesn't mean it is common knowledge on the Web. This is another one of those things that everyone building Web applications should know about to secure their applications but very few actually learn.


 

Categories: Web Development
Tracked by:
http://just.shelleypowers.com/juststuff/dare-to-stay/ [Pingback]
http://sitecore.alexiasoft.nl/2007/01/02/json-in-the-news/ [Pingback]
http://www.25hoursaday.com/weblog/PermaLink.aspx?guid=f0e7bb6e-eb81-4497-b9ae-ad... [Pingback]
http://viezbaq.net/freebsd/index.html [Pingback]
http://fwmwly7.net/post/sitemap1.html [Pingback]
http://yftbsy1.net/games/sitemap1.html [Pingback]
http://restablog.com/automotive/sitemap1.html [Pingback]
http://eofw1lk.net/california/sitemap1.html [Pingback]
http://gator393.hostgator.com/~rocata/sitemap2.html [Pingback]
http://tulanka.readyhosting.com/online/sitemap1.php [Pingback]
http://kiva.startlogic.com/sitemap1.html [Pingback]
http://host239.hostmonster.com/~blogford/sitemap3.html [Pingback]
http://gator413.hostgator.com/~digital/gift/sitemap1.html [Pingback]
http://umatutman.com/classes/sitemap1.html [Pingback]
http://rrvptrt.net/career/sitemap1.html [Pingback]
http://qw6yfnf.net/sitemap1.html [Pingback]
http://d579737.u108.floridaserver.com/sitemap2.html [Pingback]
http://gator442.hostgator.com/~hockteam/arizona/sitemap1.html [Pingback]

Tuesday, 02 January 2007 17:43:22 (GMT Standard Time, UTC+00:00)
The major problem with the HTTP header approach arises when a misconfigured proxy (which are legion) removes or otherwise mangles your header because it doesn't understand it. It's a useful approach for an intranet, where you can find and berate the person responsible for messing things up, but on the www a custom header is going to fail for at least some users, some of the time. It's not even possible to do reliable content negotiation for this reason, despite there being no reason for a proxy to mess with an Accept header.

On the wider issue of correct authentication and authorisation in web apps, it is truly shocking how many people working in the field know nothing at all about the possible risks and their mitigations. I was rather surprised to find such a basic error in one of Google's apps, though.
Tuesday, 02 January 2007 18:23:13 (GMT Standard Time, UTC+00:00)
My solution for this problem which I posted in Slashdot ( http://it.slashdot.org/comments.pl?sid=214454&cid=17428358 )
1. Check for the HTTP Request method. If it is POST, send the data. For other request methods like HEAD, GET send HTTP Status code 405(Method Not Allowed).
2. For Google applications, they should use XMLHttpRequest and POST method to retrieve the data. This will be allowed due to same domain policy.
3. Unless otherwise specified, browsers does a GET request for a required resource. So javascript url in scripts tag of third party web sites will be processed as GET by browser and will get a 405 response code. So third party websites must use POST to get google data which is impossible due to same domain restrictions.


>> Expect a series of posts on this later today.
As a webapp developer I am looking forward for your blog posts on this topic.
Saravanan
Wednesday, 03 January 2007 04:00:10 (GMT Standard Time, UTC+00:00)
I've never heard of the term "canaries." It sounds like what crypto protocols refer as a "nonce." Well-known for avoiding replay attacks.
Zachary Hartley
Wednesday, 03 January 2007 12:48:38 (GMT Standard Time, UTC+00:00)
Dare, thanks for the great posts. I've learned a great deal from your last couple posts alone, so please don't kill off your blog! Happy New Year!
Kris
Wednesday, 03 January 2007 18:52:35 (GMT Standard Time, UTC+00:00)
You can inject the canary just about any way you want. POST it in a form, put it in a URL or query parameter. As long as it's secret between the server and a trusted page coming from the server and no other pages can steal it.

http://server.example.com/mydata/canaryvalue
Cookie: canary=canaryvalue

easy enough to check.
Comments are closed.