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