views:

478

answers:

3

Using AntiForgeryToken requires each request to pass a valid token, so malicious web pages with simple script posting data to my web application won't succeed.

But what if a malicious script will first make some simple GET request (by Ajax) in order to download the page containing the antiforgery token in a hidden input field, extracts it, and use it to make a valid POST?

Is it possible, or am I missing something?

A: 

Could the user possibly have done it? If so, it can possibly be done automatically.

erikkallen
+5  A: 

Yes, this is all you need to do.

As long as you generate a new token on each protected page, with <%= Html.AntiForgeryToken() %> and always ensure it is checked in any protected action, using [ValidateAntiForgeryToken]

This implements the Synchronizer Token Pattern as discussed at the CSRF Prevention Cheat Sheet at OWASP.

In order for a script to succeed in making an acceptable request, it would have to first get the form and read the token and then post the token. Same Origin Policy will stop this from being allowed in a browser. A site canot make an AJAX style http request to another site; only to itself. If for some reason same origin policy can be breached, then you will become vulnerable.

Note that if you have a cross-site scripting vulnerability, then an attacker can abuse the xss vulnerability to circumvent the protection provided by the same origin policy (because the script is now running from your own site, so SOP succeeds). The injected script can then happily read and resubmit the token. This technique to get past CSRF protection via XSS has been common in some worms recently. Basically, if you have XSS, your CSRF-protection is a waste of time, so ensure you are not vulnerable to either.

Another thing to watch out for is Flash and Silverlight. Both of these technologies do not subscribe to the same origin policy and instead use cross domain policy files to restrict access to remote resources. Flash/Silverlight script can only access resources on your site if you publish a cross domain policy xml file on your own site. If you do publish this file, only ever allow a whitelist of trusted third-party servers and never allow *.

Read more about CSRF at OWASP See also: XSS Prevention Cheat Sheet

Cheekysoft
So apart from validating token one have to be carefull with crossdomain.xml, right? If I uderstand correctly, exposing web application for unrestricted cross domain requests (allow-http-request-headers-from domain="*" in crossdomain.xml) defeats the purpose of AntiForgeryTokens, and makes the site CSRF vulnerable?
PanJanek
yes. good point if you publish a crossdomain.xml policy file on your server you can re-open yourself to CSRF attacks made via ActionScript in a remote flash movie. If you publish this file only ever whitelist trusted third parties and never *. I'll add this to the answer
Cheekysoft
"A site canot make an AJAX style http request to another site; only to itself"How does google analytics work then?I think Same-Origin-Policy has to do with the inability of reading/modifying cookies of another site.
Marco M.
@Marco M. The Google Analytics code embeds an image hosted at GA in the page. The URL of that image contains some information to identify the page and the GA account and some other bits and bobs. The browser then goes to GA to request this image and the rest of the data is collected from the browsers HTTP Request. XmlHttpRequest is not used.
Cheekysoft
+1  A: 

But what if malicious script will make first some simple GET request (by AJAX) in order to download the page containing antiforgery token in hidden input field, extracts it, and use it to make valid POST?

Yes, this is true, but, if it's not ending up in a browser this is NOT a CSRF attack.

If it does end it up the browser (for example scraping via an HTTP Request in server side code) then what would happen the scrape code will get a CSRF token. However your legitimate, authenticated users will get a different token put on their machine. Because the token that the scraper lifts is different to the one issued to your users then the POST will fail.

If you want to stop non-browser scripts making posts then you need to take another approach to validate it's a human.

blowdart
By making GET request with AJAX, I meant theat the GET is executed by malicious script embeded on some page which is opened in a browser by user who was somehow tricked into opening such a page. This way the script would execute in user's context. So it is still CSRF, I think.
PanJanek
Ah I see. Well then that won't work because of same original policy, unless they're doing something tricksy, in which case the cookie won't flow anyway, so the token will be different
blowdart