I am looking for a way to add a CSRF token to an application I'm making. The caveat is, the application does not currently use cookies or sessions.
I would love to find a way to introduce a CSRF token without having to:
$_SESSION
/ $_COOKIE
) storageIs this at all a possibility, or am I stuck creating new state in my application.
You can, but it's not going to be very secure.
Here's an example BUT DO NOT USE THIS, IT IS PROBABLY A BAD IDEA:
// Do this somewhere
define('CSRF_SALT', '4dedMj4CWgBMNhRsoTpJlokwB5wTz7UsmF8Mq4uzFIbv');
$token = base64_encode(
hash_hmac(
'sha256',
date('Ymd') . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'],
CSRF_SALT,
true
)
);
if (\hash_equals($_POST['security_token'], $token)) {
// Form passes validation
}
The downside is that these tokens are inherently reusable, so if one leaks an attacker can simply reuse (or recalculate) it. You can also try adding the form action="" value in the hash calculation.
function getToken($action)
{
return base64_encode(
hash_hmac(
'sha256',
hash_hmac(
'sha256',
date('Ymd') . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'],
hash('sha256', $action, true),
true
),
CSRF_SALT,
true
)
);
}
echo "<form action='register.php' method='post'>\n";
echo "<input type='hidden' name='security_token' value='".getToken('register.php')."' />\n";
// ...
What's your anathema for sessions anyway?