CSRF Attacks: How to Secure PHP Forms

Cross-Site Request Forgery is a type of web security vulnerability that allows an attacker to trick a user into performing actions they did not intend to perform. This might generate unauthorized actions, cause different problems with data, and generate financial harm. This article will explain how CSRF works and how it could be prevented within the PHP environment.

Understanding CSRF Attacks

What is a CSRF Attack?

A CSRF attack is based on how the user typically without their knowledge gets tricked into submitting a malicious request to a web application where they have previously authenticated. The attacker essentially exploits the trust that the web application has in the user’s browser and performs certain actions on behalf of the user without requesting any authorization.

How Does a CSRF Attack Work?

  1. User Authentication: The user logs into a web application, and a session is established.
  2. Malicious Request: The attacker crafts a malicious request (e.g., changing the user’s email address or transferring funds) and embeds it into a seemingly harmless link or form.
  3. User Interaction: The user, while still authenticated, clicks on the link or submits the form, unknowingly sending the malicious request to the web application.
  4. Unauthorized Action: The web application processes the request, believing it to be legitimate, and performs the unauthorized action.

Example of a CSRF Attack

Consider a banking application that allows users to transfer funds using a simple form:

<form action="https://bank.com/transfer" method="POST">
    <input type="hidden" name="amount" value="1000">
    <input type="hidden" name="toAccount" value="attackerAccount">
    <input type="submit" value="Transfer Funds">
</form>

An attacker could embed this form on a malicious website. If a logged-in user visits the site and clicks the “Transfer Funds” button, the funds would be transferred without their consent.

Securing PHP Forms Against CSRF Attacks

Developers can implement many security measures to protect PHP forms against the Cross-Site Request Forgery (CSRF) attack. Here are some of the best methods:

1. Use CSRF Tokens

A CSRF token is a unique, random value associated with a user’s session. This token is passed with every form submission, and server-side verification occurs. If the token is missing or invalid, the request is denied.

CSRF Tokens Implementation in PHP

Step 1: Generate a CSRF Token

<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>

Step 2: Include the Token in the Form

<form action="process_form.php" method="POST">
    <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
    <!-- Other form fields -->
    <input type="submit" value="Submit">
</form>

Step 3: Validate the Token on the Server

<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
        die("CSRF token validation failed.");
    }
    // Process the form data
}
?>

2. Use SameSite Cookies

The SameSite attribute for cookies can help mitigate CSRF attacks by preventing the browser from sending cookies in cross-site requests. This ensures that cookies are only sent in first-party contexts.

Setting SameSite Cookies in PHP

<?php
session_start([
    'cookie_samesite' => 'Strict',
]);
?>

3. Validate the Origin and Referer Headers

Another layer of defense is to validate the Origin and Referer headers of incoming requests. These headers indicate where the request is coming from, and if they don’t match the expected domain, the request should be rejected.

Example of Origin/Referer Validation

<?php
$allowed_domains = ['https://yourdomain.com'];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
    $referer = $_SERVER['HTTP_REFERER'] ?? '';

    if (!in_array($origin, $allowed_domains) || !in_array(parse_url($referer, PHP_URL_HOST), $allowed_domains)) {
        die("Invalid request origin or referer.");
    }
    // Process the form data
}
?>

4. Use Double Submit Cookies

In this approach, a CSRF token is stored both in a cookie and as a hidden form field. The server then compares the two tokens to ensure they match.

Implementing Double Submit Cookies

Step 1: Set the CSRF Cookie

<?php
setcookie('csrf_cookie', bin2hex(random_bytes(32)), [
    'samesite' => 'Strict',
    'httponly' => true,
    'secure' => true,
]);
?>

Step 2: Include the Token in the Form

<form action="process_form.php" method="POST">
    <input type="hidden" name="csrf_token" value="<?php echo $_COOKIE['csrf_cookie']; ?>">
    <!-- Other form fields -->
    <input type="submit" value="Submit">
</form>

Step 3: Validate the Token on the Server

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_COOKIE['csrf_cookie']) {
        die("CSRF token validation failed.");
    }
    // Process the form data
}
?>

5. Implement CAPTCHA

CAPTCHA can be used to ensure that the form submission is made by a human and not an automated script. While this is not a direct defense against CSRF, it can add an additional layer of security.

Example of CAPTCHA Integration

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $captcha_response = $_POST['g-recaptcha-response'];
    $secret_key = 'your_secret_key';

    $response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secret_key&response=$captcha_response");
    $response_data = json_decode($response);

    if (!$response_data->success) {
        die("CAPTCHA validation failed.");
    }
    // Process the form data
}
?>

By understanding the nature of CSRF attacks and implementing appropriate countermeasures, web developers can protect their applications from this type of exploitation. Using CSRF tokens, SameSite cookies, Origin and Referer validation, double submit cookies and CAPTCHA, developers can greatly improve their form PHP security.

It is important to remember security is a continuous process. Stay Ahead of the Game Now that you have the basics covered, the next step is to keep up with security updates. Taking these steps will ensure your users and your application are protected from the debilitating effects of CSRF attacks.

Disclaimer: The information provided in this article is for educational purposes only. Always consult with a security professional before implementing any security measures in your application.