WooYun-2014-67410:Hdwiki设计缺陷知邮箱可改密码(包括管理员)

漏洞作者: ′雨。认证白帽子

来源:http://www.wooyun.org/bugs/wooyun-2014-067410

简要描述

上Hdwiki官网 发现更新日期一直都没变。 还以为一直都没更新了, 结果今天下载一个下来看看。 发现之前发的洞竟然都补掉了。 看了看之前这个改密码那个 对比了一下。 发现增强了点验证。 加入了一个算法。

不过。。。。。。

——————————————————————————————————

ps. 更新程序了应该还是把日期更新了一下 要不别人会一直以为没更新的。

详细说明

http://**.**.**.**/bugs/wooyun-2014-055786

上次的 现在来看看现在的。

依旧是control/user.php

}else{

            $timetemp=date("Y-m-d H:i:s",$this->time);

            $auth = util::strcode($timetemp, 'ENCODE');

            $verification= rand(1000,9999);

            $encryptstring=md5($this->time.$verification.$auth);

            $reseturl=WIKI_URL."/index.php?user-getpass-".$user['uid'].'-'.$encryptstring;

            $_ENV['user']->update_getpass($user['uid'],$encryptstring);

            $mail_subject = $this->setting['site_name'].$this->view->lang['getPass'];

            $mail_message = $this->view->lang['resetPassMs1'].$user['username'].$this->view->lang['resetPassMs2'].$timetemp.$this->view->lang['resetPassMs3']."<a href='".$reseturl."' target='_blank'>".$reseturl."</a>".$this->view->lang['resetPassMs4'].$this->setting['site_name'].$this->view->lang['resetPassMs5'].$this->setting['site_name'].$this->view->lang['resetPassMs6'];

            $this->load('mail');

            $_ENV['mail']->add(array(), array($email), $mail_subject, $mail_message, '', 1, 0);

            $this->message($this->view->lang['emailSucess'],'index.php?user-login',0);

        }

    }

$encryptstring=md5($this->time.$verification.$auth);

现在所验证的 对比之前的可以发现多了一个$auth 来看看怎么来的。

$timetemp=date("Y-m-d H:i:s",$this->time);

$auth = util::strcode($timetemp, 'ENCODE');

这里获取了一下时间 然后

function strcode($string,$action='ENCODE'){

        $key    = substr(md5($_SERVER["HTTP_USER_AGENT"].PP_KEY),8,18);

        $string    = $action == 'ENCODE' ? $string : base64_decode($string);

        $len    = strlen($key);

        $code    = '';

        for($i=0; $i < strlen($string); $i++){

            $k        = $i % $len;

            $code  .= $string[$i] ^ $key[$k];

        }

        $code = $action == 'DECODE' ? $code : base64_encode($code);

        return $code;

    }

主要关注他的key怎么来的。

$key = substr(md5($_SERVER["HTTP_USER_AGENT"].PP_KEY),8,18);

首先对USER_AGENT.PP_KEY MD5一次 然后再来取。

等等。。 user agent 是用户可控的, PP_KEY呢?

竟然没有初始化, 那么PP_KEY就是PP_KEY 那么这个$key 全部就可控了。

所以我们可以想对什么加密就对神马加密了。

$timetemp=date("Y-m-d H:i:s",$this->time);

$auth = util::strcode($timetemp, 'ENCODE');

然后这个是对时间加密一次 如果知道时间的话就能知道$auth

然后继续$this->time.$verification.$auth

第一个就是时间戳 第二个rand(1000,9999) 有8999种可能 直接枚举 第三个 知道时间就可以了。

漏洞证明

这里由于管理员和用户在同一个表所以可以直接改管理员的密码。

首先 http://**.**.**.**/web/hdwiki/index.php?user-getpass

然后把要管理员的邮箱输入进去。

在点提交之前打开 (提交的时候一定要改一下user agent 如果不改user agent 会对应不上的 我这里改成的是asd)

http://**.**.**.**/Tools/unixtime.aspx

然后在点提交的时候 看一下时间戳 并记录下来。

(我本地时间有点不准 无伤大雅)

以我演示的为例, 时间戳为 1405589070

然后把这个时间戳转换为时间

1405589070 -> 2014/7/17 17:24:30 (时间不准 别在意哈哈)

$timetemp=date("Y-m-d H:i:s",$this->time)

Y-m-d H:i:s 这个的格式是这样的 年份-月份-日子 小时:分钟:秒

所以把2014/7/17 17:24:30对应下来为2014-7-17 17:24:30

但是这样是不对的 因为 Y-m-d H:i:s获取的是 格林威治标准时间

与北京时间正好相差8个小时 所以$timetemp=2014-07-17 09:24:30

然后带入那个算法当中

然后这样就拿到了$auth

然后写个脚本 把8999种情况 全部遍历出来

1405589070$iBlMHBUkAVkwHBxYICw8BVw0BBA==

把8999种情况全部导出来 然后载入burpsuite

前面那uid那里就是管理员的id 肯定是为1的。

修复方案

增强验证

增强算法

随机生成一个Key咋样。