随机数种子爆破

image-20241116165931510

在PHP中,变量以$符号开头,后面拼接变量名。上述代码的基本 含义是:从$str变量中随机取32次字符(字符可重复),并拼接成字符 串,最后将该字符串赋值给变量$password。执行代码后会输出 $password变量的前10个字节,此时通过POST请求传递password参数到 服务端,如果password参数的值与$password变量的值完全相等,那么 就会输出flag。

理论上,如果选取字符的时候是完全随机的,那么几乎不可能出现 password参数值与$password变量值相等的情况(概率极低)。但由于 代码中使用mt_rand()函数来生成随机数,因此如果可以得知该函数生 成的一段随机数序列,就可以通过工具爆破出其选取的随机数种子 (该种子由$_Session[‘seed’]变量生成),从而预测之后的所有随机数序 列。在这里,我们使用php_mt_seed工具来爆破随机数种子。该工具的 下载地址为:https://www.openwall.com/php_mt_seed/php_mt_seed- 4.0.tar.gz

image-20241116165647076

访问题目页面,可得到前10个字节的随机字符,将输出的随机字符转换为php_mt_seed可识别的数据格式。使用

Python3脚本进行转换:

image-20241116165703575

str1变量的值就是PHP代码中的$str的值,str2变量的值就是PHP代码中 输出的$password的前10个字节。这段代码的基本作用就是将$password 中的前10个字节(即变量str2)进行定位,得到其在str1中的具体下标 位置,然后按照具体格式输出。以str2中的第一个字母A为例,字母A 在变量str1中的下标是36(字符串下标从0开始)

将输出的字符输入到编译好的php_mt_seed工具中,具体指令如下:

image-20241116165734372

最终我们找到一个随机数种子 19290735(PHP7.1)。在这一步需要注意的是,mt_rand()函数本身确 实存在问题,但是根据PHP版本的不同,其生成的随机数会略有区别。 所以,在实际题目中一定要注意PHP版本问题,不能脱离PHP版本来做 题。

利用得到的随机数种子编写PHP脚本,如下所示:

image-20241116165751773

尝试将该结果提交给服务端,即可成功得到flag。

本质上是因为mt_rand()函数的不安全性导致的。所以,我们需要明确 以下几点:

  1. mt_rand()函数的不安全性是考点的核心。

2)要爆破随机数种子,首先需要得到mt_rand()函数生成的随机数序

列。

3)mt_rand()函数生成的随机数序列可能以不同的形式表现(例如生成 随机字符串)。

4)相同函数在不同的PHP版本(大版本)中的实现代码可能是不一样 的。例如,在PHP7和PHP5中,mt_rand()函数的实现算法是完全不同 的。

5)计算机中不存在真正的随机数,这是mt_rand()函数存在安全问题的 根本原因。