Evert Evert - 1 month ago 13
PHP Question

CSRF token without cookies in PHP

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:


  1. Introduce state in my application.

  2. Use session or cookie (
    $_SESSION
    /
    $_COOKIE
    ) storage



Is this at all a possibility, or am I stuck creating new state in my application.

Answer Source

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?