Securing PHP Web Forms from CSRF Attacks - Double Submit Cookie Pattern
What is CSRF
Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they're currently authenticated. CSRF attacks specifically target state-changing requests, not theft of data, since the attacker has no way to see the response to the forged request.
With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker's choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application.(
[To see links please login or register here])
Read my previous post about Synchronizer Token Pattern: Securing PHP Web Forms from CSRF Attacks - Synchronizer Token Pattern
what is Double Submit Cookie Pattern
When a user authenticates to a site, the site should generate a (cryptographically strong) pseudo-random value and set it as a cookie on the user’s machine separate from the session ID. The server does not have to save this value in any way, that's why this pattern is also called Stateless CSRF Defense.
The site then requires that every transaction request include this random value as a hidden form value (or other request parameter). A cross origin attacker cannot read any data sent from the server or modify cookie values, per the same-origin policy.
In the case of this mitigation technique the job of the client is very simple, just retrieve the CSRF cookie from the response and add it into a special header to all the requests.(Image 1)
The job of the server is a little more complex, create the CSRF cookie and for each request asking for a protected resource, check that the CSRF cookie and the CSRF header of the request are matching.(
[To see links please login or register here])(Image 2)
Implementing CSRF Protection in PHP
In here I have implemented a PHP based money transferring application for the demonstration purpose. This application generates two CSRF tokens for the login form and the money transferring form.
This is a simple login form (login.php) with username and password (Image 3). I have hard coded the username and password as "admin":"admin". I added a token for the login form as well For greater security. if someone tries to bruteforce the login credentials, it won't work because, one token can use for a one submission. every time the form submits it checks the token and validate it.
When this page loads it will call a function named "csrf_token_gen()" in "csrf_token.php" which generates tokens.(Image 4)
When this function(Image 5) is called it will generate a token and save it in a cookie called "csrf". Then the generated token returns to the login.php.
The returned token is saved as a variable called "$token" which will print as a hidden input value named "csrf" inside the login form.(Image 6)
When the user submit the form, "csrf" token will be submitted along with the username and password.(Image 7)
The submitted data send to the "login_check.php" to validation. First it checks the cookie "csrf" is set and assign it to a variable called "csrf" and compare it with POST csrf token to check both are equal.(Image 8)
Then check if the user entered the valid credentials and username and session id are saved as cookies and unset the csrf token cookie that used for the login submission.(Image 9)
then the user will redirect to the "transfer.php". (Image 10)
If someone tries to submit the form with the same token, they will see the error message below (Image 11). Therefore, the user must refresh the page to regenerate another token.
Money transferring form
After successful login, the user will redirect to the Money transferring form (transfer.php) (Image 12). This is also a simple form which used to transfer money (only for the demonstration purpose). To make the transaction, the user has to enter the amount and click the transfer button.
When this page loads, using the below script(Image 13), AJAX sends a POST request to "csrf_token.php" to generate the token.
After receiving above request below PHP code(Image 14) checks, if it is a valid request, and call the function to generate the token.
"csrf_token_gen()" function(Image 15) is used to generate the token as earlier and save the token in a cookie callled "csrf" and returns the token.
after running this function, as above java script (Image 13), it get the token from cookie that saved in the browser and it will print as a hidden input value named "csrf" inside the money transferring form
The submitted data send to the "transfer_check.php". As below php code(Image 17), first it checks the cookie "csrf" is set and assign it to a variable called "$csrf".
Then check the POST token and the "$csrf" is equal or not. If both are equal, it will do the transaction.(Image 18)
if not, it will show an error message as below.(Image 19)