我想知道这段代码是否足以阻止对PHP Form的CSRF攻击?
<?php
session_start();
session_regenerate_id(true);
if (isset($_POST['submit'])) {
if (isset($_SESSION['token']) && ($_POST['token'] == $_SESSION['token'])) {
}
}
$token = hash('sha256', uniqid(mt_rand(), true));
$_SESSION['token'] = $token;
?>
//FORM
<form method="POST" action="page.php">
<input type="hidden" name="token" value="<?php echo $token; ?>">
<input type="submit" name="submit">
</form>
感谢。
答案 0 :(得分:2)
如果受害者没有在您的网站上查看任何表格,他的会话中将不会存储令牌。
如果攻击者向受害者提供的表单根本没有令牌字段,则受害者发出的POST请求将通过CSRF检查,因为$_POST['token']
和$_SESSION['token']
都将为空。 (或者两个空字符串取决于PHP如何初始化未知变量。)
在检查相等性之前,您还必须在会话中检查令牌是否存在,如果其中任何一个测试失败,则必须中止。
根据您的网站,可能很有可能是用户没有看过表单,也可能是极端情况。首先检查令牌是否存在,无论您在网站上有多少表单,都不会发生CSRF攻击。
除了这个小问题,我在其中看不到任何CSRF漏洞。该代码看起来会起作用。
答案 1 :(得分:1)
在我支持的产品上,我会说“不”。您的随机数生成器基于可预测的rand()。此外,看起来随机数非常短 - 它需要足够长,以至于在会话有效期内不能强制执行 - 也不能破解任何多个活动会话的CSRF令牌。
查看OWASP page on CSRF他们会给你很好的指导。
答案 2 :(得分:1)
我认为这足以达到既定目的。
uniqid(mt_rand(), true)
返回的值最多为33个字节:
mt_rand
php_combined_lcg
然而,这33个字节不提供264位的熵,但方式更少:
mt_rand
前缀这总计近81个未知位。为了强制这一点,人们平均需要2个 81 /2≈1.2·10 24 猜测,这些猜测会在散列时产生给定的令牌。要处理的数据大约为8·10 13 TB。使用今天的计算机,你应该可以在大约5.215·10 17 秒内运行它。
这足以使攻击变得不切实际。