PHPCMS MT_RAND SEED CRACK致authkey泄露。

正文

看到phpcms更新了, 看了下补丁, 分析了下他修复的漏洞。

这种漏洞在CTF中还是比较常见的, 实例我还是第一次遇到。


在INSTALL.PHP中

1
$cookie_pre = random(5, 'abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ').'_'; $auth_key = random(20, '1294567890abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ');

在安装的时候, 用random来生成了cookie_pre 和 authkey,

1
2
3
4
5
6
7
8
function random($length, $chars = '0123456789') {
$hash = '';
$max = strlen($chars) - 1;
for($i = 0; $i < $length; $i++) {
$hash .= $chars[mt_rand(0, $max)];
}
return $hash;
}

这里使用了mt_rand来生成chars的索引来生成authkey之类的。
mt_rand 在一个脚本中, 产生多个随机数的时候, 只播了一次种。
那么也就是mt_rand生成cookie_pre和authkey的种子是一样的。
cookie_pre从名字就能看出这个是cookie名称的前缀, 所以是可以拿到的, 那么只要用cookie_pre爆破到了种子的话, 那么也就是拿到了生成authkey的种子。
因为种子确定了的话, 产生的随机数序列就可以确定了, 也就是每次的索引可以确定了, 就可以拿到auth_key了。

首先看到 COOKIE_PRE 为 AZZBP

这里直接用下wonderkun大佬的脚本, 来获取一下cookie_pre的各个字符串在序列中的位置。

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$str = "AZZBP";
$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";

26 26 0 51 51 51 0 51 51 51 0 51 27 27 0 51 41 41 0 51

然后用MT_RAND SEED CRACKER来爆破一下种子。

然后把爆破到的种子, 用mt_srand设置一下种子, 再来获得随机数列, 就能拿到authkey了。
因为爆破到的种子会有多个。 就一个一个慢慢试了。

在试第三个种子的时候就拿到了正确的auth_key了。

拿到auth_key后 可以做的事情很多, 就不多说了。

修复方法

官方的已经修复了。

多次播种了, 那么根据cookie_pre拿到的种子和生成auth_key的种子是不一样的, 所以authkey生成的序列就不知道咯。