PHP Security

PHP CSRF Protection via Anti-CSRF Token

Published on: July 13, 2020

PHP CSRF Protection via Anti-CSRF Token

PHP is widely used in almost all popular CMSes on the internet today. PHP has a role to play even in this blog that you are reading. However, at times people using PHP to build their sites skip the security practices. This leaves the PHP site vulnerable and makes it susceptible to malware attacks. As a result, the internet is full of questions asked by users regarding how to secure a PHP site. What is more alarming is that in the case of a CMS, multiple modules share the same part of a PHP code. If the code is vulnerable, it can make all the modules vulnerable as well.

Today we are talking one of the biggest woes of the PHP mechanism – Cross-Site request forgery. We will learn how to secure a PHP CSRF protection through secure development practices.

For PHP, the most popular web development language, security is crucial. Recently, there have been numerous security alerts around PHP. But, in fact, the majority of them are not a result of flaws in PHP itself but are due to improper and insecure uses of PHP by application developers.

Essential PHP Security by Chris Shiflett

What is Cross-Site Request Forgery in PHP?

Owasp defines Cross-Site Request Forgery (CSRF) as a kind of attack that takes place when a malicious web resource (email, website, etc.) or program makes the user perform something unwanted on another website that the user is already authenticated for. Before explaining how to secure a PHP site against CSRF, let me explain it in more simple terms.

Suppose you have logged in to a bank website named www.example-bank.com. Now, for instance, take a malicious site i.e., www.malicious-site.com. For the attack to happen, you should be logged in to your bank site and then visit the malicious site. Thereafter, the malicious site will make you perform an unwanted action like clicking a button, and so on. As soon as that happens, the malicious site (www.malicious-site.com) will send a request to your bank site (www.example-bank.com). Now, since the bank has no CSRF mechanism, it will execute the request. This is because your browser sent that request along with your session cookies automatically. The bank is unable to determine if the request was generated by you or another malicious site. Now that you have an idea about CSRF attack, let us next learn how to secure a PHP site against it.

how to secure a php site against CSRF
Type caption (optional)

How to Protect PHP Site Against CSRF

One of the most widely used methods to secure a PHP site against CSRF is by using tokens. These are also known as Anti-CSRF tokens and contain secure and random values. So, even when the attacker makes you perform an unwanted action, the website won’t execute it because the Anti-CSRF token value will be wrong.Most of the popular PHP frameworks provide an Anti-CSRF token to secure a PHP site. However, in case you are building things from scratch or you missed something, you can do it manually too. To do so, you can follow these steps:Is your PHP site hacked due to a CSRF bug?

Clean my PHP site now!

Step 1: Creating a PHP file to manage anti-CSRF token operations

Firstly, we need to create a PHP file manually like this one which contains various functions to:

  1. Generate secure random tokens
  2. Get session tokens and cookies
  3. Verify the CSRF token and cookies
  4. Handle the timeout of a CSRF token

You can use the code of this author free of charge as it is MIT licensed. However, if you wish to make changes, beware of certain things. For instance, the PHP function rand() is predictable and the function md5() doesn’t add entropy. Also, to compare the Anti-CSRF token hashes, do not use == or even === if you wish to secure a PHP site against CSRF attacks.

Step 2: Importing functions

Once the PHP file is created to handle the Anti-CSRF token operations, the next thing to do would be to ensure that this is seen on each page. This can be done by the require_once statement. It will check if the file has already been included and if not, include it again. So, for instance, if it is in the /home/www/site/, then add it accordingly. Thereafter, import our functions to manage Anti-CSRF tokens by the use statement of PHP. When they are combined, it would look like this:

<?php

require_once __DIR__ /home/www/site/;

use steveclifton\phpcsrftokens\Csrf;

?>

Step 3: Creating session and verifying anti-CSRF token

Now start a session using the session_start() method of PHP. Thereafter, within the same block, we will call another function named verifyToken(‘home’) which is already present in the CSRF class of our imported file. This function will help us to determine token and cookie matches and mismatches. It is important to secure a PHP site against CSRF attacks. All of them combined would look like this:

<?php

require_once __DIR__ /home/www/site/;

use steveclifton\phpcsrftokens\Csrf;

session_start();

if (!empty($_GET['a'])) {
  echo (Csrf::verifyToken('home') ? 'success' : 'unsuccessful');
}

?>

Note: For PHP 7.1.0, session_start() returns FALSE when it failed to start the session instead of initializing $_SESSION.

Step 4: Embedding anti-CSRF token generating function in HTML

Finally, let us add our imported function which generates Anti-CSRF tokens into our HTML elements i.e., forms. This can be done by calling the function getInputToken(‘home’) of the CSRF class in our imported file. For more info, see the code snippet below added to an HTML form:

<!DOCTYPE html>
<html>
<head><title>Test Script</title></head>
<body>
  <form action="?a=submit" method="POST">
    <?php echo Csrf::getInputToken('home') ?>
    <input type="text" name="name">
    <button>Submit!</button>
  </form>
</body>
</html>

Now your Anti-CSRF token mechanism is ready to go. This is the final code that answers your question of, “How to secure a PHP site against CSRF attacks?”.

<?php

require_once __DIR__ /home/www/site/;

use steveclifton\phpcsrftokens\Csrf;

session_start();

if (!empty($_GET['a'])) {
  echo (Csrf::verifyToken('home') ? 'success' : 'unsuccessful');
}

?>

<!DOCTYPE html>
<html>
<head><title>Test Script</title></head>
<body>
  <form action="?a=submit" method="POST">
    <?php echo Csrf::getInputToken('home') ?>
    <input type="text" name="name">
    <button>Submit!</button>
  </form>
</body>
</html>

PHP security issues & prevention steps

PHP CSRF Protection – Conclusion

This is just one mechanism to secure a PHP site against CSRF attacks. There are a variety of other security mechanisms that can be used. Moreover, it is not easy for novice users to figure it all by themselves. Security solution such as Astra Security can help you here with its easy to use firewall and security audit. The security audit can find CSRF bugs in your PHP site while the firewall protects it any attempted CSRF attack on your site. All this comes at flexible pricing allowing every small and big sized firm to afford it. If you still have questions, get in touch with our security experts with the chat widget in the bottom right corner of this page.

Was this post helpful?

Jinson Varghese

Jinson Varghese Behanan is an Information Security Analyst at Astra. Passionate about Cybersecurity from a young age, Jinson completed his Bachelor's degree in Computer Security from Northumbria University. When he isn’t glued to a computer screen, he spends his time reading InfoSec materials, playing basketball, learning French and traveling. You can follow him on Medium or visit his Website for more stories about the various Security Audits he does and the crazy vulnerabilities he finds.
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments

Psst! Hi there. We’re Astra.

We make security simple and hassle-free for thousands
of websites and businesses worldwide.

Our suite of security products include firewall, malware scanner and security audits to protect your site from the
evil forces on the internet, even when you sleep.

earth spiders cards bugs spiders

Made with ❤️ in USA France India Germany