CSRF Protection Demo

The Attack Scenario

Without CSRF protection:

An attacker creates a page on evil.com with a form that submits to your-bank.com:

<!-- On evil.com -->
<form action="https://your-bank.com/transfer" method="POST">
    <input type="hidden" name="to" value="attacker-account">
    <input type="hidden" name="amount" value="10000">
</form>
<script>document.forms[0].submit();</script>

If you're logged into your-bank.com, your session cookie is sent automatically, and the transfer happens!

Protected Form

Current CSRF Token

This token is stored in your session and embedded in the form:

5fed08ff9f695b651854d3dd03d43dcaeab7e59ea807cb974c6cc614ffe8bf74
View Page Source to see the hidden csrf_token field. The token changes per session, so an attacker can't know what value to include.

How It Works

<?php
session_start();

// 1. Generate token (once per session)
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

// 2. On form submission, validate token
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $submittedToken = $_POST['csrf_token'] ?? '';

    // Use timing-safe comparison to prevent timing attacks
    if (!hash_equals($_SESSION['csrf_token'], $submittedToken)) {
        http_response_code(403);
        die('CSRF validation failed');
    }

    // Token valid - process form safely
    processForm($_POST);
}
?>

<!-- 3. Include token in every form -->
<form method="POST">
    <input type="hidden" name="csrf_token"
           value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
    <!-- other fields -->
</form>

Why This Works

Attacker's Form Your Form
No csrf_token field (or wrong value) Contains valid csrf_token from session
Server rejects: token mismatch Server accepts: token matches

The attacker can't read your session's token (same-origin policy), so they can't forge a valid request.


Back to Security Patterns | Flash Messages Demo | Sessions Demo