PHP Cross-Site Request Forgery (CSRF


Cross-Site Request Forgery (CSRF) is a type of attack where a malicious site tricks a user's browser into making unwanted requests to another site where the user is authenticated. This can result in unauthorized actions being performed on behalf of the user. To protect against CSRF attacks, PHP provides several mechanisms and best practices for implementing CSRF protection.

Understanding CSRF Protection

CSRF attacks exploit the trust that a site has in the user's browser. They typically involve tricking a user into making an unwanted request to a site where they are logged in, such as changing account settings or performing actions that affect their data.

Implementing CSRF Protection

1. Using CSRF Tokens

A CSRF token is a unique, random value generated by the server and included in each form. When the form is submitted, the server checks if the token matches the one it issued. If it doesn't match, the request is rejected.

Steps to Implement CSRF Tokens:

  1. Generate a CSRF Token

    • Store the token in the user’s session.
    • Generate a unique token for each form.

    Example:

    <?php session_start(); // Generate a unique token function generateToken() { return bin2hex(random_bytes(32)); // Securely generate a random token } // Store the token in the session $_SESSION['csrf_token'] = generateToken(); ?>
  2. Include the Token in Forms

    Add the token as a hidden field in your forms.

    Example:

    <form action="process.php" method="post"> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"> <label for="name">Name:</label> <input type="text" id="name" name="name" required> <input type="submit" value="Submit"> </form>
  3. Validate the Token on Form Submission

    Check if the token sent with the form matches the one stored in the session.

    Example:

    <?php session_start(); // Validate the CSRF token if ($_SERVER["REQUEST_METHOD"] == "POST") { if (isset($_POST['csrf_token']) && $_POST['csrf_token'] === $_SESSION['csrf_token']) { // Token is valid // Process the form data $name = htmlspecialchars($_POST['name']); echo "Name: " . $name; } else { // Token is invalid echo "Invalid CSRF token."; } } ?>
  4. Regenerate Tokens Periodically

    For additional security, regenerate CSRF tokens periodically, such as after a successful login or during certain actions.

    Example:

    <?php session_start(); // Regenerate the token after login if ($login_successful) { $_SESSION['csrf_token'] = generateToken(); } ?>

2. Using HTTP-Only Cookies for CSRF Tokens

To enhance security, you can use HTTP-only cookies for storing CSRF tokens. This prevents client-side scripts from accessing the token, adding an additional layer of protection.

Example:

  1. Set the Token as an HTTP-Only Cookie:

    <?php session_start(); $csrf_token = generateToken(); $_SESSION['csrf_token'] = $csrf_token; // Set token as HTTP-only cookie setcookie('csrf_token', $csrf_token, 0, '', '', false, true); ?>
  2. Include Token in Requests Using JavaScript:

    <script> // JavaScript to include CSRF token in headers var token = document.cookie.split('; ').find(row => row.startsWith('csrf_token=')).split('=')[1]; function submitForm() { fetch('process.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-Token': token }, body: new URLSearchParams(new FormData(document.querySelector('form'))) }) .then(response => response.text()) .then(text => console.log(text)); } </script>
  3. Validate Token from HTTP Headers:

    <?php session_start(); if ($_SERVER["REQUEST_METHOD"] == "POST") { $token = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? ''; if ($token === $_SESSION['csrf_token']) { // Token is valid // Process form data $name = htmlspecialchars($_POST['name']); echo "Name: " . $name; } else { // Token is invalid echo "Invalid CSRF token."; } } ?>

Best Practices for CSRF Protection

  1. Use Secure Tokens: Generate tokens using a secure method like random_bytes() to ensure they are unpredictable.

  2. Include Tokens in All Forms: Ensure that every form that modifies data includes a CSRF token.

  3. Validate Tokens on Every Form Submission: Check the token on every request that modifies data to ensure its validity.

  4. Regenerate Tokens Regularly: Consider regenerating tokens after sensitive actions, such as login or data changes.

  5. Use HTTPS: Ensure that your site uses HTTPS to prevent token interception via man-in-the-middle attacks.

  6. Combine with Other Security Measures: Use CSRF protection alongside other security practices, such as input validation and sanitization, to enhance overall security.