对于安全代码,请不要以这种方式生成令牌:
$token = md5(uniqid(rand(), TRUE));
rand()
是可以预见的uniqid()
最多只加29位熵md5()
不添加熵,而是确定性地将其混合
试试看:
生成CSRF令牌
PHP 7
session_start();if (empty($_SESSION['token'])) { $_SESSION['token'] = bin2hex(random_bytes(32));}$token = $_SESSION['token'];旁注:我老板的一个开源项目是一项向后移植
random_bytes()并移植
random_int()到PHP
5项目中的计划。它是MIT许可的软件,可在Github和Composer上以paragonie /random_compat的形式获得。
PHP 5.3+(或ext-mcrypt)
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'];验证CSRF令牌
不要只是使用
==甚至
===使用
hash_equals()(仅适用于PHP5.6+,但适用于具有hash-compat库的早期版本)。
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()。HMAC是一种特殊的键控哈希函数,即使具有较弱的哈希函数(例如MD5),也可以安全使用。但是,我建议改为使用SHA-2系列哈希函数。
首先,生成第二个令牌用作HMAC密钥,然后使用类似以下的逻辑来呈现它:
<input type="hidden" name="token" value="<?php echo hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);?>" />然后在验证令牌时使用全等运算:
$calc = hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);if (hash_equals($calc, $_POST['token'])) { // Continue...}在不知道的情况下,无法为另一种形式重用为一种形式生成的令牌
$_SESSION['second_token']。
重要的是,您要使用一个单独的令牌作为HMAC密钥,而不是您刚刚在页面上丢弃的令牌。
奖励:混合方法+ Twig集成
使用Twig模板引擎的任何人都可以通过在其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']); } ));使用此Twig函数,您可以使用两个通用令牌,如下所示:
<input type="hidden" name="token" value="{{ form_token() }}" />或锁定的变体:
<input type="hidden" name="token" value="{{ form_token('/my_form.php') }}" />Twig只关心模板渲染。您仍然必须正确验证令牌。我认为,Twig战略提供了更大的灵活性和简便性,同时又保持了最大安全性的可能性。
一次性CSRF令牌
如果您有一个安全要求,即每个CSRF令牌只能使用一次,则最简单的策略是在每次成功验证后重新生成它。但是,这样做会使之前的所有令牌失效,而这与一次浏览多个选项卡的人不能很好地融合在一起。
Paragon Initiative Enterprises为这些极端情况维护了一个反CSRF库。它仅与一次性使用的形式令牌一起使用。当会话数据中存储了足够的令牌(默认配置:65535)时,它将首先循环出最旧的未兑换令牌。



