问题可能源于令牌生成方法,因为提供的代码是容易受到预测和缺乏熵的影响。此方法对于一次性使用和每次表单令牌验证也是不够的。
将令牌生成替换为安全PHP 7 或 PHP 5.3 的方法:
session_start();
if (empty($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(random_bytes(32));
}
$token = $_SESSION['token'];
session_start();
if (空($_SESSION['令牌'])) {
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'];
使用 hash_equals() 验证令牌安全地:
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 }
}
进一步限制将令牌转换为特定形式,请使用 hash_hmac():
echo hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
?> ;” />
对于那些使用 Twig 模板的人,可以使用简化的双重策略实现:
$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']); } )
);
使用此函数,安全通用令牌可以用作:
<输入类型=“隐藏”名称=“令牌” value="{{ form_token() }}" />
虽然可以使用以下方式生成每个表单令牌: