I was chatting with a Flash Developer turned Web Developer. When asked why he made the transition, he predicted that HTML 5 and the evolution of the web thereafter would lessen the demand for Flash Developers (possibly making them obsolete) and that moving towards a Web Developer / Generalist is an investment for the future. I thought that was an interesting perspective. It’s not far fetched to predict that the open web will replace proprietary browser plug-ins – in many cases digital content has already replaced print.
Anti Cross-site Request Forgery Tokens help prevent Cross-site Request Forgery (CSRF) also known as XSRF – pronounced “sea-surf” – and are usually implemented through a hidden HTML form element that contains a unique ID. This ID is passed along with subsequent requests for data and validated on the server. Anti CSRF Tokens try to ensure the identity of the user. They aren’t a replacement for CAPTCHAs and don’t prevent robots or web scrapers from manipulating your site – as you’ll soon see.
Why use an Anti CRSF Token?
An overly simple example: If I didn’t use an Anti Forgery Token on my contact page (see the source code: View or Controller), a Spammer could POST data directly against my contact form and potentially drown me with spam.
Here’s a hypothetical form created by an evil Spammer. This form is hosted on http://spammer.com (not my site):
<form action="http://adam.kahtava.com/contact/send" method="POST"> <input name="fromName" type="text" value="Johnathon Fink" /> <input name="fromAddress" type="text" value="firstname.lastname@example.org" /> <input name="subject" type="text" value="Call for your diploma now" /> <textarea name="body">Is your lack of a degree...</textarea> ... </form>
Again, note that the form action contains a reference to my site (even though it is hosted on another site).
Now, imagine this was a form prompting a user for their username and password. These credentials could be maliciously stored while the user successfully authenticates and is then redirected to the site they thought they were visiting – the way phishing usually works.
After adding an Anti CRSF Token to my contact form, a Spammer can’t access my form remotely (at least not without the token). My contact form with it’s Anti CRSF Token:
<form action="/contact/send" method="post" name="contact"> <input name="__RequestVerificationToken" type="hidden" value="0sAqY1ZKb+Qia4..." /> <input name="fromName" ...
Note the presence of the RequestVerificationToken.
Said Spammer, can’t abuse my form without including the unique token. Technically speaking the Spammer can still abuse my form, but he now needs to:
- Request (GET) my contact form
- Parse out the Anti CRSF Token
- POST their spam into my contact form along with the token
This is pretty easy to do if you have an implementation of a HTTP Client library that supports cookies.
How to hack an Anti CRSF Token protected form
Using an extended instance of .NETs Web Client here’s how our Spammer could circumvent my Anti CRSF Token.
The Spamming script by that wascaly Spammer:
// create a new HTTP Web Client that supports cookies var webClient = new WebClientWithCookies(); //download my contact page containing the Anti CRSF Token webClient = webClient.DownloadData("http://adam.kahtava.com/contact"); //parse out the Anti CRSF Token var antiCrsfToken = RegexUtilities.GetTokenString( new Regex("__RequestVerificationToken=(?<CRSF_Token>[^;]+)") .Match(webClient.ResponseHeaders["Set-Cookie"]), "CRSF_Token"); //now the Spammer can drown me in spam-spam-spam // by scraping my Anti CRSF Token and posting it into my form webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); byte response = webClient.UploadData("http://adam.kahtava.com/contact/send", "POST", Encoding.UTF8.GetBytes( "__RequestVerificationToken=" + antiCrsfToken + "&fromName=\"Johnathon Fink\"" + "&fromAddress=\"email@example.com\"" + "&subject=\"Call for your diploma now\"" + "&body=\"Is your lack of a degree...\""));
The Spammer is back at their old tricks sending me more Spam. ARGH!
What’s the use of an Anti CRSF Token?
Anti CRSF Tokens help prevent phishing attacks. They aren’t meant to prevent spammers or Dr Robotnik and his robots (or web scrapers) from running automated scripts against your web application. Keep in mind, that if your site suffers from other XSS vulnerabilities (where the privacy of your cookies or sessions are compromised) then Anti CRSF Tokens don’t work at all.
Read more about how Anti CRSF Tokens work here: Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helper or learn more about Cross-Site Request Forgery at: The Cross-Site Request Forgery (CSRF/XSRF) FAQ.
I run my site on a Windows Shared Hosting account, and every time I updated the assemblies on my ASP.NET MVC site I’d be presented with the “Validation of viewstate MAC failed” error.
The “Validation of viewstate MAC failed” error only occurred when a page contained an HTML form element that made use of MVC’s AntiForgeryToken. The quick fix was to delete my
__RequestVerificationToken cookie, but the error would rear its ugly head the minute I touched my assemblies. The long term solution was to add a machineKey element to my Web.config file – asking visitors to delete a specific cookies when visiting my site was not a viable option.
How I fixed the “Validation of viewstate MAC failed” error on Shared Hosting:
- I used the <machineKey> Generator Tool to generate a machine key
- I added the machineKey element to my Web.config file
My Web.config now looks similar to this:
<?xml version="1.0"?> <configuration> <system.web> <machineKey validationKey="..." decryptionKey="..." validation="SHA1" />
Anyhow, I hope this post helps anyone else that’s encountering this error.
Oh wait, here’s the error in its entirety for The Google Machine’s crawlers:
Server Error in '/' Application.
Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Web.HttpException: Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
If you’re reading this from an RSS feed, then the changes looks like this:
These new sections make use of the services I created earlier – my resume content is pulled directly from LinkedIn via my Resume service, the Reading Lists and Reviews are being pulled from Amazon via my Amazon service, and I’m still working on a personalized greeting module which will make use of my Whois service.
Now, when I update my resume on LinkedIn, add a new item to my Amazon wishlist, or write a new Review on Amazon the content is updated within this site and indexed by the Google.
My next steps with this site are to: finish the greeting module, update the layout (drop the WordPress theme), and finish a Github / Google Code repo widget (kind of like this one) for the sidebar.
Contribute, view, or download the openly available source code here.