Server-Side Magazine

PHP Security Measures Against CSRF Attacks

CSRF stand for Cross Site Request Forgeries, it’s a method that allows an outside attacker to send malformed HTTP requests to a website, but from a victim’s computer. In this case the actual victim is the accomplice to this attack.

Stronger security measures must be implemented in order to avoid CSRF attacks, and to make sure the website and it’s users are not vulnerable.

To better understand CSRF attacks let’s look at an example. Let’s say you’re signed in to Facebook, you browse around and in the mean time you open a new window or a new tab and visit another site. It’s a typical scenario. Now, your still signed in at Facebook on the other tab and you visit a site where there’s a CSRF attack implemented. Now the CSRF site actually could send out spam to your Facebook friends or even delete your account, all this using your credentials, because a session is saved when you logged into Facebook (remember, on the other tab).

CSRF Attack Example:

1
2
3
4
5
<form action="process.php" method="get">
   <input type="text" name="amount" value="33" />
   <input type="text" name="destination_card_number" value="1111222233334444" />
   <input type="submit" name="submit" value="Transfer" />
</form>

Consider the above fictive card payment transfer form. The request method GET is used to simplify the example, but CSRF is not immune against POST requests either.

The actual request would look something like this if it’s posted let’s say to example.com:

   http://www.example.com/process.php?amount=33&destination_card_number=1111222233334444

The only thing an attacker has to do is include a request on the “attack web page” (e.g. csrfhacker.com, this is just a fictive site), when you visit this site, the request will be sent to example.com and a transfer would be made with your credentials.

The most common form to fire requests from an attack website is to use the img HTML tag, because before the browser shows you the image, it actually sends a request to the server for that image resource. Now if the attacker includes this on his attack web page:

<img src="http://www.example.com/process.php?amount=33&destination_card_number=1111222233334444" />
and a user visits this website the request will be sent to example.com and the transfer will be made. What’s worst that this attack is completely transparent for users, all they would see is a broken image on the website.

As a user you can’t do anything against CSRF attacks, as a webmaster you can. Although a webmaster cannot control his website’s visitors, but fortunately he can filter out CSRF attacks just as easily as the attack could be implemented.

Let’s see the security measures a web developer should take in order to successfully knock out CSRF attacks:

  1. Protection against XSS attacks
  2. Using a form token
  3. Using form timeout

1. Protection Against XSS Attacks

You should make sure your website is protected against XSS (cross site scripting) attacks, if not then it’s useless to protect against CSRF, because with any security measure an attacker could bypass this with a counter XSS attack.

Also using POST requests doesn’t eliminate CSRF attacks, it makes a little harder for the attacker, and this is the point.

2. Using a Form Token

The root problem with CSRF vulnerability is the failure to verify the source request. A good web developer should already know that by simply relying on $_SERVER['REMOTE_ADDR'] is not effective, almost useless. With the help of a form token we could verify the request’s source.

A token could be a simple random number that can be injected in the target form as a hidden input element, and also saved in the session when the form is rendered. When the form is submitted the token from the request can be compared to the token that is saved in the session. If the two doesn’t match the form should be discarded.

Generating a form token in PHP is easy:

1
$token = md5(uniqid(rand(), true));

Implementing the token is also easy, just save it in user’s session and inject it in the target form:

1
$_SESSION['token'] = $token;
1
2
3
4
5
6
<form action="process.php" method="post">
   <input type="hidden" name="token" value="<?php echo $token; ?>">
   <input type="text" name="amount" />
   <input type="text" name="destination_card_number" />
   <input type="submit" name="submit" value="Transfer" />
</form>

When the request was sent the token should be compared like this:

1
2
3
4
5
6
 
if ( (!empty($_SESSION['token'])) && (!empty($_POST['token'])) ) {
	if ($_SESSION['token'] == $_POST['token']) {
	   //process the form
	}	
}
Keep in mind to filter and validate any form request.

3. Using Form Timeout

Using form timeout adds extra security to the form and to the web application itself, which is always a good thing to do.

Form timeout consists of saving the time when the form is rendered and compare it to the time when the form request was sent to the server. From this time-frame we could filter out potential attacks, not just CSRF, but also spam bots too.

Setting a maximum time-frame in which the form must be submitted is recommended, but don’t forget to also set a minimum time-frame in which if the form is submitted would be discarded, because we’re dealing with either spam bots or an automated CSRF attack. It is unrealistic that a human can submit a form with 4 – 5 fields under 2 seconds.

To implement this security measure the following code or similar is required:

1
$_SESSION['time'] = time();

When the request was made the comparison should look like this:

1
2
3
4
5
6
7
8
9
10
$min_allowed_time = 20;
$max_allowed_time = 60;
 
if  ( (time() - $_SESSION['time']) < $min_allowed_time ) {
   echo 'form discarded';
}
 
if  ( (time() - $_SESSION['time']) > $max_allowed_time ) {
   echo 'form timeout';
}

Related Posts

Tags: , , , ,

About the Author

Server-Side Magazine

Server-Side Magazine is a place where users can contribute articles. Strictly server-side posts are presented in the following programming languages: PHP, Ruby, ASP.Net, Java, Python

Our philosophy is that knowledge should be free and available to anyone. We designed this site to be an open platform, meaning that anyone can contribute and share their knowledge on the above areas.

Although, it's an open platform we don't accept all articles, because it would result in a "just another", mediocre website. A minimum standard of quality is required from every submitted article.

Comments

Leave a Comment

Your email address will not be published. Required fields are marked *

Markdown enabled. Click here to see the syntax.

 
More in PHP (5 of 9 articles)