Does AntiForgeryToken in ASP.NET MVC prevent against all CSRF attacks?
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
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.