Ken*_*Ken 81 php security session csrf
我正在尝试为我网站上的表单添加一些安全性.其中一种形式使用AJAX,另一种形式是直接的"联系我们"形式.我正在尝试添加CSRF令牌.我遇到的问题是令牌只在某些时候出现在HTML"值"中.剩下的时间,值是空的.这是我在AJAX表单上使用的代码:
PHP:
if (!isset($_SESSION)) {
session_start();
$_SESSION['formStarted'] = true;
}
if (!isset($_SESSION['token']))
{$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
}
Run Code Online (Sandbox Code Playgroud)
HTML
<form>
//...
<input type="hidden" name="token" value="<?php echo $token; ?>" />
//...
</form>
Run Code Online (Sandbox Code Playgroud)
有什么建议?
Sco*_*ski 252
对于安全代码,请不要以这种方式生成令牌: $token = md5(uniqid(rand(), TRUE));
rand()
是可以预测的uniqid()
最多只能添加29位熵md5()
不添加熵,它只是确定性地混合它试试这个:
session_start();
if (empty($_SESSION['token'])) {
$_SESSION['token'] = bin2hex(random_bytes(32));
}
$token = $_SESSION['token'];
Run Code Online (Sandbox Code Playgroud)
旁注:一个我的雇主的开源项目是反向移植的倡议random_bytes()
,并random_int()
到PHP 5个项目.这是麻省理工学院的许可,可以在Github和Composer上以paragonie/random_compat的形式获得.
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'];
Run Code Online (Sandbox Code Playgroud)
不要只使用==
甚至===
使用hash_equals()
(仅限PHP 5.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
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过使用进一步限制令牌仅适用于特定表单hash_hmac()
.HMAC是一种特殊的键控哈希函数,即使使用较弱的哈希函数(例如MD5)也可以安全使用.但是,我建议使用SHA-2系列哈希函数.
首先,生成第二个令牌以用作HMAC密钥,然后使用这样的逻辑来呈现它:
<input type="hidden" name="token" value="<?php
echo hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
?>" />
Run Code Online (Sandbox Code Playgroud)
然后在验证令牌时使用全等操作:
$calc = hash_hmac('sha256', '/my_form.php', $_SESSION['second_token']);
if (hash_equals($calc, $_POST['token'])) {
// Continue...
}
Run Code Online (Sandbox Code Playgroud)
在不知情的情况下,为一种形式生成的标记不能在另一种形式中重复使用$_SESSION['second_token']
.使用单独的令牌作为HMAC密钥非常重要,而不是刚刚放在页面上的令牌.
使用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']);
}
)
);
Run Code Online (Sandbox Code Playgroud)
使用此Twig功能,您可以使用这两个通用令牌:
<input type="hidden" name="token" value="{{ form_token() }}" />
Run Code Online (Sandbox Code Playgroud)
或锁定的变体:
<input type="hidden" name="token" value="{{ form_token('/my_form.php') }}" />
Run Code Online (Sandbox Code Playgroud)
Twig只关注模板渲染; 你仍然必须正确验证令牌.在我看来,Twig策略提供了更大的灵活性和简单性,同时保持了最大安全性的可能性.
如果您有安全要求允许每个CSRF令牌只能使用一次,那么最简单的策略是在每次成功验证后重新生成它.但是,这样做会使之前的每个令牌无效,这些令牌与一次浏览多个标签的人不能很好地混合.
Paragon Initiative Enterprises 为这些极端案件维护着一个反CSRF库.它仅适用于一次性使用的单一形式令牌.当足够的令牌存储在会话数据中时(默认配置:65535),它将首先循环出最旧的未兑换令牌.
dat*_*age 24
安全警告:
md5(uniqid(rand(), TRUE))
不是生成随机数的安全方法.有关更多信息和利用加密安全随机数生成器的解决方案,请参阅此答案.
看起来你需要另外一个if.
if (!isset($_SESSION['token'])) {
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
}
else
{
$token = $_SESSION['token'];
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
104448 次 |
最近记录: |