When attempting to add a CSRF token to two different forms, one using AJAX and the other a basic contact form, it is observed that the token value in the HTML is sporadically empty. How can this issue be resolved?
The problem likely stems from the token generation method, as the provided code is vulnerable to prediction and lack of entropy. This method is also insufficient for one-time-use and per-form token validation.
Replace the token generation with secure methods for PHP 7 or PHP 5.3 :
session_start();
if (empty($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(random_bytes(32));
}
$token = $_SESSION['token'];
session_start();
if (empty($_SESSION['token'])) {
if (function_exists('mcrypt_create_iv')) { $_SESSION['token'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); } else { $_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(32)); }
}
$token = $_SESSION['token'];
Use hash_equals() to verify tokens securely:
if (!empty($_POST['token'])) {
if (hash_equals($_SESSION['token'], $_POST['token'])) { // Proceed to process the form data } else { // Log this as a warning and keep an eye on these attempts }
}
To further restrict tokens to specific forms, use hash_hmac():
echo hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
?>" />
For those using Twig templates, a simplified dual strategy can be implemented:
$twigEnv->addFunction(
new \Twig_SimpleFunction( 'form_token', function($lock_to = null) { if (empty($_SESSION['token'])) { $_SESSION['token'] = bin2hex(random_bytes(32)); } if (empty($_SESSION['token2'])) { $_SESSION['token2'] = random_bytes(32); } if (empty($lock_to)) { return $_SESSION['token']; } return hash_hmac('sha256', $lock_to, $_SESSION['token2']); } )
);
With this function, secure general tokens can be used as:
While per-form tokens can be generated with:
For one-time-use token requirements, consider using a dedicated library such as the Anti-CSRF library from Paragon Initiative Enterprises.
The above is the detailed content of Why are my CSRF tokens sometimes empty when used in AJAX and standard forms, and how can I fix this in PHP?. For more information, please follow other related articles on the PHP Chinese website!