Cross-site request forgery prevention
Cross-Site Request Forgeries is the new buzzword in web-security these days. What it is? Why it’s dangerous? How to prevent it?
Bill Zeller offers a good description of what this is
CSRF vulnerabilities occur when a website allows an authenticated user to perform a sensitive action but does not verify that the user herself is invoking that action. The key to understanding CSRF attacks is to recognize that websites typically don’t verify that a request came from an authorized user. Instead they verify only that the request came from the browser of an authorized user. Because browsers run code sent by multiple sites, there is a danger that one site will (unbeknownst to the user) send a request to a second site, and the second site will mistakenly think that the user authorized the request.
This means the potential hacker will insert a bit of code into a page, or trick a user to load one of their pages up. Then they will be able to post forms as the user.
GMail has been hit by several of these flaws, one being users having filters added to their gmail account (fixed now). With this, the hijacker could e.g. filter all emails from Godaddy.com to his own account and then take over the targets’ domain names. They are easy to do, and can be automated.
Google isn’t alone, many of the major websites have these kinds of vulnerabilities. Do you?
Luckily it is easy to stop these attacks
One way of doing it is to generate a random string and add that to a cookie and a hidden form element. Then make sure that they match before you process the form. This way the hacker has to guess what the random string is to be able to post the form. The chance of this happening is slim to none, so it is a pretty good way of doing it
Now, how do we do this in php?
First off, we have to generate a random string, this is easily done with the random function. Keep in mind, this string doesn’t have to be very random before it becomes difficult to impossible for the hacker to guess. I’ll keep it simple
$randomString = md5(rand(0,100000));
That should give us about 100 000 possibilities.
Next step is to send the cookie to the user
setcookie("XSRF_filter",
$randomString,
time() + 3600,
"/",
".yourdomain.com",
0);
And the hidden form element would look something like this
<form action="" method="POST">
<input type="hidden" name="XSRF_filter" value="<? echo $randomString; ?>">
<br>...other form elements
<br><input type="submit" name="submit" value="submit">
</form>
Pretty simple so far right? Good, now comes the validation checking
if ($_POST['XSRF_filter'] != $_COOKIE['XSRF_filter'])
{
echo "You're trying to do an XSRF attack! Can't allow you to post this form";
}
else
{
//process form
}
That’s it!
Demo and complete source code can be found in the playground
Here is a tool for testing for XSRF vulnerabilities