从中猜测下一个值的rand
能力与确定所srand
调用内容的能力有关。特别是,以预定数量播种会srand
导致可预测的输出!在PHP交互式提示符下:
[charles@charles-workstation ~]$ php -a
Interactive shell
php > srand(1024);
php > echo rand(1, 100);
97
php > echo rand(1, 100);
97
php > echo rand(1, 100);
39
php > echo rand(1, 100);
77
php > echo rand(1, 100);
93
php > srand(1024);
php > echo rand(1, 100);
97
php > echo rand(1, 100);
97
php > echo rand(1, 100);
39
php > echo rand(1, 100);
77
php > echo rand(1, 100);
93
php >
这不仅仅是fl幸。大多数PHP版本*在大多数平台**会生成序列97,97,39,77,93时,srand
“d与1024。
要明确的是,这不是PHP的问题,这是其rand
自身实现的问题。在使用相同(或相似)实现的其他语言(包括Perl)中也会出现相同的问题。
诀窍是,任何理智的PHP版本都将预先植入srand
“未知”值。哦,但这并不是真正未知的。来自ext/standard/php_rand.h
:
#define GENERATE_SEED() (((long) (time(0) * getpid())) ^ ((long) (1000000.0 * php_combined_lcg(TSRMLS_C))))
因此,这是一个数学运算符time()
,其中包含PID以及PID的结果php_combined_lcg
,它们在中定义ext/standard/lcg.c
。我不会在这里进行c&p,因为,我的眼睛发呆,所以我决定停止狩猎。
有点谷歌搜索表明PHP的其他区域没有最好的随机性生成属性,并呼吁在php_combined_lcg
这里脱颖而出,尤其是以下分析:
此函数(gettimeofday
)不仅使我们在银盘上获得了精确的服务器时间戳,而且如果我们要求“更多熵”(来自PHP uniqid
),它还会添加LCG输出。
是啊是uniqid
。似乎值php_combined_lcg
是在调用uniqid
第二个参数设置为真值后查看生成的十六进制数字时所看到的。
现在,我们在哪里?
哦是的 srand
。
因此,如果您尝试从中预测随机值的代码没有调用srand
,则需要确定由提供的值php_combined_lcg
,您可以通过调用来(间接获得)该值uniqid
。根据手中的价值,这是可行的,以蛮力价值的休息- time()
,PID和一些数学。链接的安全性问题是关于中断会话的,但是相同的技术在这里也适用。再次,从文章:
这是上面概述的攻击步骤的摘要:
- 等待服务器重启
- 获取唯一值
- 蛮力从此RNG种子
- 轮询在线状态以等待目标出现
- 将状态轮询与uniqid轮询交错,以跟踪当前服务器时间和RNG值
- 使用轮询中建立的时间和RNG值间隔对服务器进行暴力会话ID
只需根据需要替换最后一步。
(此安全问题是在比我们当前的版本(5.3.6)更早的PHP版本(5.3.2)中报告的,因此,uniqid
和/或php_combined_lcg
已更改的行为很可能,因此该特定技术可能不再可行。 YMMV。)
另一方面,如果您要尝试人工生成的代码调用srand
,那么除非它们使用的结果比的结果好很多倍,否则php_combined_lcg
您可能会更容易地猜测出值并为本地设置种子编号正确的发电机。大多数会手动调用的人srand
也不会意识到这是多么可怕的想法,因此不太可能使用更好的价值。
值得注意的是,mt_rand
同样的问题也困扰着它。mt_srand
具有已知值的播种也会产生可预测的结果。基于您的熵openssl_random_pseudo_bytes
可能是一个更安全的选择。
tl; dr:为了获得最佳结果,请不要植入PHP随机数生成器,并且出于良善起见,请不要uniqid
向用户公开。两者之一或两者都做可能会使您的随机数更容易猜测。
PHP 7更新:
PHP 7.0引入random_bytes
和random_int
作为核心功能。他们使用基础系统的CSPRNG实现,从而使它们摆脱了种子随机数生成器所具有的问题。它们实际上与相似openssl_random_pseudo_bytes
,只是不需要安装扩展程序。 Polyfill可用于PHP5。
*:Suhosin安全补丁会更改的行为,rand
并mt_rand
始终在每次调用时重新植入种子。Suhosin由第三方提供。默认情况下,某些Linux发行版将其包含在其官方PHP软件包中,而其他发行版则将其作为选项,而其他发行版则完全忽略了它。
**:根据所使用的平台和底层库调用,将生成与此处记录的序列不同的序列,但是除非使用Suhosin补丁,否则结果应仍可重复。