Fixing CSRF vulnerability in PHP applications
Cross Site Request Forgery or CSRF is one of top 10 OWASP vulnerabilities. It exploits the website’s trust on the browser. This vulnerability harms users’ and can modify or delete users’ data by using user’s action. The advantage of the attack is that action is performed as a valid user but user never knows that he has done something. If the target account is of website administrator, attacker can perform admin’s action of the web application. Poor coding and wrong assumptions are the main reason why the vulnerability exists on the web application.
Sometimes, it is typical to understand how this vulnerability is exploited by attackers. In this detailed article, we will understand Cross Site Request Forgery vulnerability. And we will also create a form with strong protection from this vulnerability. We will also see popular frameworks, scripts and methods that can be used to patch this vulnerability.
What is Cross Site request forgery attack?
Cross Site Request Forgery or CSRF is an attack that forces a malicious action to an innocent website from end user’s (valid user) browser when he/she is running a valid session of the website. If user is authenticated on a website, every action performed from his browser will belong to him. The website also thinks that the request is coming from the user and it has been made by him.
Most common effects of this attack are change of password, fund transfer from bank account, purchase of an item etc.
This attack is performed by making fake forms or requests that behaves exactly same as in original website. When these requests are sent to a website from an authenticated user’s browser, the website thinks the request has been made by the user. In the next section, we will see how CSRF works.
How CSRF works
Most of the times, the attacker uses a third party trusted website to perform this attack. Fake links are posted on forums and social networking websites that may lead to CSER. The attack follows a sequence of requests and responses. Suppose a victim is logged in on target website. He finds a link on a forum. The link performs a malicious link on the target website. He clicks on the link and the link sends the malicious request to the target website.
Now for example:
- You are logged in on a website http://targetwebsite.com.
- This website has a delete account action via button method on a page. This button submits a delete request via a form link this.
<form action=’http://targetwebsite.com/deleteaccount.php‘ method=’post’>
<input type=’text’ value=’Delete’ name=’delete’>
- Once the button is clicked, website will delete the account of the logged in user. So, it relies on the active session to identify the user.
- Attacker has created a fake page that submits this form onload. He has posted the link of that page on a forum.
- You found the link interesting and clicked.
- Once you clicked on the link, that page submits the form. Form action will delete your account because you have an active session.
- In this way, your account has been deleted by the attacker without your knowledge. But request had been made from your browser.
I am sure; this simple example had made it clear how the vulnerability affects website’s users. Similarly, we can show how it can affect your bank accounts if vulnerability exists on your banking applications.
If the action is performed by a get request, the attacker can also craft the request in an image tag. The SRC attribute of the image will be the action link on the form. When the image loads on the page, it will perform the action.
<img src=”http://targetwebsite.com/app/transferFunds?amount=25000&targetAccount=attackersAcctnumber” width=”0″ height=”0″ />
Misconceptions of CSRF attack
Cross Site Request Forgery is one of most dangerous web application vulnerabilities. So, it must be checked and patched carefully. But there are few misconceptions about the patching. Generally developers use few ways to patch the vulnerability. But those ways are not enough to prevent this vulnerability. There are the few wrong ways of patching CSRF:
Use of Post Requests for Critical Tasks.
- Another bad example of CSRF patching is URL Rewriting. Developers create the URL rewriting method with unique session id’s in a URL. This makes the URL unpredictable. But this method also exposes the user’s credentials in the URL. May be it prevents CSRF, but it’s equally harmful for users.
- Sometimes websites use multi-step transaction process. If we do it in a previous account delete example, suppose website asks for confirmation after requesting account deletion. If both requests have no prevention against CSRF, attacker can predict and perform all steps or reduce the steps of transaction request via some ways.
There are few other weak prevention methods which are not so important to discuss here.
Proven ways to prevent CSRF vulnerability
Checking for Referral Header
Checking for a referral header can help in preventing the CSRF. If the request is coming from some other domain, it must be the fake request so block it. Always allow requests coming from the same domain. This method fails if the website has open redirection vulnerabilities. Attackers can perform GET CSRF by using open redirection.
Now these days, most of the applications use HTTPS connection. In this the referrer will be omitted. So this method will not help if a website is using https. So, we will have to search another way.
Captcha Verification in forms
This is another nice way to prevent CSRF attacks on forms. Captcha verification process was initially developed to prevent BOT spam in forms. But it can also be helpful in preventing CSRF. As the captcha is generated on the client side randomly, an attacker cannot guess the pattern. So, he will never be able to send the correct Captcha with a fake request. And all fake requests will be blocked by a Captcha verification function.
This method is not user friendly. Most of the users don’t want to fill the Captcha on the website. So, we should try to find ways that prevent CSRF vulnerability without adding any extra burdens on users.
Unpredictable Synchronizer Token Pattern
This is the most secure method for preventing CSRF. Unlike captcha verification, this method has nothing to do with users. So, users will never know that something has been added to protect them. In this method, the website generates a random token in each form as a hidden value. This token is associated with the users’ current session. Once the form is submitted, website verifies whether the random token comes via request. If yes, then verify whether it is right. By using this method, developers can easily identify whether the request was made by the user of attacker.
<form action=”accountdelete.php” method=”post”><input type=”hidden” name=”CSRFToken” value=”OWY4NmQdwODE4hODRjN2DQ2NTJlhMmZlYWEwYzU1KYWQwMTVhM2JmLNGYxYjJiMGI4jTZDE1ZDZjMTViMGYwMGEwOA==” />
Strength of this method depends on the token generation method. So, always try to generate the token in the manner that it is always unpredictable.
So, if you are thinking to implement this by your own, try to randomize it.
You can use:
$randomtoken = md5(uniqid(rand(), true));
or try this
$randomtoken = base64_encode( openssl_random_pseudo_bytes(32));
by using base64_encode, it ensures that the generated value will not break your HTML layout with html chars.
Generate this $randomgtoken, once the session is initiated after login. And add this to your session variables.
Add this to every form for users.
<input type=’hidden’ name=’csrfToken’ value='<?php echo($_SESSION[‘csrfTOken’]) ?>’ />
The csrfToken is unique to each session. In every new session, it will generated again and then varified with form requests.
You can either use a single CSRF token for all forms in single session. But using different for all forms may be more secure. But using this method for generating a different csrfToken for different forms can create trouble when users open multiple forms in multiple tabs and submit one by one.
There are few opensource PHP classes and libraries are also available. You can use these opensource classes to implement a strong protection against CSRF vulnerabilities.
Few opensource libraries are:
Clfsrpm is a popular PHP class that gives a strong way of preventing CSRF. It gives few public functions that you can use to generate and validate CSRF tokens. Complex part has already been done by the developer.
You can read more and download the class from the link: http://www.clfsrpm.net/csrf/
NoCSRF is another simple anti-CSRF token generation and checking class written in PHP5. It also comes with easy to understand examples to learn how to properly implement this class on your web application.
You can download NoCSRF from here: https://github.com/BKcore/NoCSRF
3. csrf by Skookum
This is another PHP implementation of CSRF protection in PHP. Code is available for free. SO you can copy and use in your application.
Get the code from here: https://github.com/Skookum/csrf/blob/master/classes/csrf.php
anticsurf is another small PHP library that can be used for preventing CSRF in PHP web applications. This library claims to give strong entropy for brute force attacks. It also implements a one-time use token and provide timeout restriction.
Read more about this PHP library and download from here: https://code.google.com/p/anticsurf/
CSRF-Magic is another strong implementation that can prevent CSRF attack on a website. The library is available for free with an online demonstration. You can only include a file on the top of your PHP files. And this library will do the rest of the work. It re-writes the scripts and forms on your websites and then intercepts the POST request to check the token injected but it means that it automatically adds everything in your traditional insecure forms. You don’t need to add extra codes for this. Only include the library file at the top.
One of the easiest CSRF protection libraries available for PHP applications…
Download the library and see the demo here: http://csrf.htmlpurifier.org/
6. CSRF Protection
CSRF Protection is also a nice and simple class. Although, it doesn’t come with tutorials. It has fully commented codes to understand how to use this library. It gives you few functions to generate and then validate the CSRF tokens. On the download page, it has given few sample codes to show how to use this class to generate and then validate the CSRF tokens on your own web application.
Download the CSRF Protection library from github via this link: https://github.com/XCMer/csrfprotect
You can use any of the above classes or libraries according to your choice. But do not forget to share with us via comments.
User side prevention
CSRF is a harmful vulnerability so, users should also follow few steps to ensure their security. These are the few important points:
- Always logout important web accounts when not in use.
- Never use important web accounts (such as online banking) along with free web surfing.
- Use No-Script browser add-on to protect yourself from malicious scripts.
In this post, we have seen that Cross Site Request Forgery is a harmful vulnerability and affects users’ accounts. We have also seen various ways to prevent this attack and protect users’ accounts. If the website has a Cross Site Scripting vulnerability, performing CSRF becomes easier. Attackers can create an automatic worm to defeat CSRF defenses.
In this post, we have discussed various open source libraries and classes. These classes can be directly used within PHP based web applications to prevent CSRF vulnerability. Web developers should take care of website’s security and follow the given tips. There are various tools and manual methods are available to test for CSRF. Most popular tool is OWASP CSRF Tester. You can download it from here: https://www.owasp.org/index.php/Category:OWASP_CSRFTester_Project
If you are thinking to start manually, you can review codes and see the forms. If the random token is not available, you should add with available open source classes. I am sure, now you know enough about CSRF and it’s patching. If you have anything to say about this, you can share it with us via comments.