I'm sure most of you have at some point been exposed to a CAPTCHA control on the net. They come in loads of forms and are used to tell the difference between humans and computers (bots). If you have a website on the net, you are prone to lots of different kinds of attacks from bots - such as CSRF (Cross-Site Request Forgery)
You may have noticed that on some sites you get asked simple math questions or other simple questions when submitting or posting information. One of the more common controls out there is a captcha like control:
Generally these types of verification work very well, but personally I have always been annoyed by them. However, I even use a captcha control on this site from reCAPTCHA. Some users out there might not be very technical and these controls can confuse them, which may lead to a drop conversion rates. That said, this sort of verification is vital to keep our application secure.
I was recently browsing the net when I came across this article about an alternative to CAPTCHA. It involved making the user slide a slider to the end of a bar in order to verify that they are human. It really got me thinking how I could get this implemented in MVC as well as keeping it as secure as possible.
So, let's start off by creating a simple MVC application just to test this approach. First we build our model -
Then let's update our view:
We need to include the references to jQuery and the jQuery UI toolkit.
Okay, let me break this down a little and explain whats going on here. In Part 1, I'm creating a variable with a random number between 40 and 100. This variable is used to determine the max value of the slider, as well as determine how far the user has slid the control.
In Part 2, I am using the stop event on the slider. For more information on the jQuery UI slider, check out - http://jqueryui.com/demos/slider/ . Part 3 takes advantage of the random number that we set earlier and basically just checks that slider's current value has exceeded the random number. Once it has, we submit the form using jQuery submit();
Finally in Part 4, we are setting the max amount that the slider can be - ie. the random number. I decided to use a random number for this because every time the page refreshes it will generate a different number, so writing some dangerous script that could repeatedly run this would be slightly more difficult.
We have one last thing to do in our controller before this is complete. As this code stands a user could still post to our controller which raises the problem of repeat posting. We can then build an attribute that would be able to look out for this. Enter the ASP.NET MVC AntiForgeryToken. If we add the following code on our view:
It renders like so:
So, now we can create our attribute and add it to our HTTPPost method on our controller:
The ValidateAntiForgeryToken Attribute checks to see that the cookie and hidden form field left by the Html.AntiForgeryToken() HtmlHelper essentially exists and match. If they do not exist or match, it throws an HttpAntiForgeryException. Let's try and combine that with a check to see if the UrlReferrer is not null and the UrlReferrer matches this site. If it doesn't match, then we know that the post didn't come from this site - so in this instance it can't be safe.
For some more information about the ASP.net AntiForgeryToken check out this link
And some more useful information on Brad Wilson's site.
I have also created a demo project that you can download: