Consent

This site uses third party services that need your consent.

Skip to content
Steven Roland

Implementing Per-Form CSRF Tokens in PHP

Building on our previous discussion of simple CSRF tokens, this post will focus on implementing per-form CSRF tokens in PHP. This approach enhances security by generating a unique token for each form, reducing the risk of token reuse and potential attacks.

Why Use Per-Form CSRF Tokens?

Per-form CSRF tokens provide an additional layer of security by ensuring that each form submission is uniquely validated. This method is particularly effective in mitigating the impact of token leakage, as an attacker would only be able to exploit a specific form or action.

Generating Per-Form CSRF Tokens

To implement per-form tokens, we need to generate a unique token for each form and store it in the session with a unique identifier. Here’s how you can achieve this:

1. Token Generation and Storage

For each form, generate a secure token and store it in the session with a specific key associated with the form:

session_start();

function generateFormToken($formName) {
    $token = bin2hex(random_bytes(32));
    $_SESSION['csrf_tokens'][$formName] = $token;
    return $token;
}

$formName = 'contact_form';
$token = generateFormToken($formName);

2. Embedding the Token in Forms

Include the generated token in the form as a hidden input field. This ensures that the token is sent along with the form data:

<form method="post" action="process_form.php">
    <!-- Other form fields -->
    <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($token); ?>">
    <input type="hidden" name="form_name" value="<?php echo htmlspecialchars($formName); ?>">
    <input type="submit" value="Submit">
</form>

3. Validating the Token

Upon form submission, validate the token by checking it against the session-stored token for the specific form:

session_start();

function validateFormToken($formName, $receivedToken) {
    if (isset($_SESSION['csrf_tokens'][$formName]) && hash_equals($_SESSION['csrf_tokens'][$formName], $receivedToken)) {
        unset($_SESSION['csrf_tokens'][$formName]); // Invalidate the token after use
        return true;
    }

    return false;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $formName = $_POST['form_name'];
    $receivedToken = $_POST['csrf_token'];

    if (validateFormToken($formName, $receivedToken)) {
        // Proceed with the action
    } else {
        // Handle invalid token
        echo "Invalid or expired token.";
    }
}

Advantages of Per-Form Tokens

  • Enhanced Security: Each form has its own token, minimizing the risk of token reuse.

  • Flexibility: Allows handling multiple forms on the same page with distinct tokens.

  • Reduced Impact of Token Leakage: Limits potential exploitation to a specific form or action.

Best Practices

  • Session Management: Ensure secure session handling to prevent session hijacking.

  • HTTPS: Use HTTPS to protect token transmission.

  • Token Expiration: Consider implementing token expiration to further enhance security.

By implementing per-form CSRF tokens, you can significantly bolster the security of your PHP applications, ensuring that each form submission is uniquely validated and protected against potential attacks.

More posts

Using CSRF Tokens with AJAX in PHP

Secure AJAX requests in PHP by implementing CSRF tokens, ensuring each asynchronous submission is authorized and protected against attacks.