php - CSRF token 和随机数中的熵

标签 php security zend-framework hash nonce

我正在使用 Zend Framework 制作一个分类广告网站(出于投资组合的目的,是的,我知道世界上没有空间容纳“另一个 Craigslist 克隆”)。我正在尝试实现无需帐户即可发布/编辑/删除的功能。

为此,我觉得我需要在提交后生成一个随机数并将其存储在数据库中。然后通过电子邮件将链接发送给发出 GET 删除请求的用户,如下所示:

http://www.somesite.com/post/delete/?id=123&nonce=2JDXS93JFKS8204HJTHSLDH230945HSLDF

只有用户拥有这个唯一的 key 或随机数,提交后我会检查帖子 ID 下的数据库并确保随机数在删除之前匹配。

我的问题是随机数实际上有多安全。如果我使用 Zend Framework 的 Zend_Form_Element_Hash,它会创建如下哈希:

protected function _generateHash()
{
    $this->_hash = md5(
        mt_rand(1,1000000) 
        .  $this->getSalt() 
        .  $this->getName() 
        .  mt_rand(1,1000000)
    );
    $this->setValue($this->_hash);
}

在阅读 mt_rand() 时,one commenter said此函数的熵有限。因此,如果您想创建随机字符串,无论字符串的长度如何,它都只会产生大约 20 亿个不同的字符串。如果您使用此类字符串,这可能会导致严重的安全问题用于 session 标识符、密码等。

由于应用程序中随机数/ token 的生命周期(可能是用户选择删除帖子之前的几天或几周),我认为将为潜在的黑客攻击提供足够的时间。

我意识到 mt_rand() 是对 rand() 的巨大升级,如 this visual 中所示。左侧使用 rand 映射像素,右侧使用 mt_rand 映射像素。但这就足够了吗?是什么让“20 亿个不同的字符串”成为安全问题?

最终,如何增加随机数/ token /哈希的熵?

最佳答案

对于这样的安全性,输出的长度并不重要。它会计算您创建它时使用了多少随机性。

对于mt_rand(),随机性的来源是它的种子和状态(自它被播种以来您使用它的次数)。更多的 mt_rand() 调用只会让您对相同的随机源进行更多的重新排序(没有新的熵)。

mt_rand() 的种子只有 32 位(任何小于 128 位的值都会让密码学家产生怀疑;)

具有 32 位熵的 key 的强度是 40 亿除以(大致)您将生成的 key 数量(例如,在使用 100K 次之后,将有大约 1:43000 的机会猜测任何有效 key ,这接近实用暴力破解)。

你在其中添加了盐,这使得它变得更强,因为除了猜测种子攻击者还必须知道盐之外,所以如果盐很长,那么总的来说, key 可能会相当强,尽管“低”熵。

为了增加熵,你需要添加更多来自与 mt_rand 不同来源的随机内容(即使是轻微随机也可以,只是提供更少的位):microtime()、使用的内存量、进程 ID ...或者只是使用 /dev/random,它收集它可以获得的所有熵。

(编辑:uniqid() 具有弱熵,因此它在这里没有帮助)

关于php - CSRF token 和随机数中的熵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9796216/

相关文章:

php - 没有谷歌电子表格的谷歌图表

php - 添加列脚本在 Magento 中无法正常工作

php - 如何保护没有表单的php页面

security - CORS 和 XSS 有什么联系吗?

Symfony 4.3 - 无法 Autowiring 引用类 "Symfony\Component\Security\Core\Security"的服务参数

php - Zend Layout 中的 $this 变量

php - mysql_ping 与 Amazon RDS 一起挂起

php - Zend 2::在 Controller 操作中轻松获取公用文件夹路径或 basePath()

php - Zend Framework 随机丢失 session ?

PHP session 为空或无法正常工作