DedeCMS任意前台用户登录漏洞(cookie伪造) - 颓废's Blog

DedeCMS任意前台用户登录漏洞(cookie伪造)

  • 内容
  • 相关

漏洞触发点在include/memberlogin.class.php中MemberLogin类中的登录校验函数

//php5构造函数
    function __construct($kptime = -1, $cache=FALSE)
    {
        global $dsql;
        if($kptime==-1){
            $this->M_KeepTime = 3600 * 24 * 7;
        }else{
            $this->M_KeepTime = $kptime;
        }
        $formcache = FALSE;
        $this->M_ID = $this->GetNum(GetCookie("DedeUserID"));
        $this->M_LoginTime = GetCookie("DedeLoginTime");
        $this->fields = array();
        $this->isAdmin = FALSE;
        if(empty($this->M_ID))
        {
            $this->ResetUser();
        }else{
            $this->M_ID = intval($this->M_ID);
            
            if ($cache)
            {
                $this->fields = GetCache($this->memberCache, $this->M_ID);
                if( empty($this->fields) )
                {
                    $this->fields = $dsql->GetOne("Select * From `#@__member` where mid='{$this->M_ID}' ");
                } else {
                    $formcache = TRUE;
                }
            } else {
                $this->fields = $dsql->GetOne("Select * From `#@__member` where mid='{$this->M_ID}' ");
            }
                
            if(is_array($this->fields)){
                #api{{
                if(defined('UC_API') && @include_once DEDEROOT.'/uc_client/client.php')
                {
                    if($data = uc_get_user($this->fields['userid']))
                    {
                        if(uc_check_avatar($data[0]) && !strstr($this->fields['face'],UC_API))
                        {
                            $this->fields['face'] = UC_API.'/avatar.php?uid='.$data[0].'&size=middle';
                            $dsql->ExecuteNoneQuery("UPDATE `#@__member` SET `face`='".$this->fields['face']."' WHERE `mid`='{$this->M_ID}'");
                        }
                    }
                }
M_ID参数是由GetNum(GetCookie("DedeUserId"))赋值的。

之后通过intval()函数对M_ID进行整数转换便没有再进行任何处理和过滤,然后通过

SQL语句
Select * From '#@__member' where mid='{$this->M_ID}'

查询来判断用户的身份。

跟进GetCookie()函数和GETNum()函数,看是否过修改M_ID参数来进行越权

/**
 *  获取Cookie记录
 *
 * @param     $key   键名
 * @return    string
 */
if ( ! function_exists('GetCookie'))
{
    function GetCookie($key)
    {
        global $cfg_cookie_encode;
        if( !isset($_COOKIE[$key]) || !isset($_COOKIE[$key.'__ckMd5']) )
        {
            return '';
        }
        else
        {
            if($_COOKIE[$key.'__ckMd5']!=substr(md5($cfg_cookie_encode.$_COOKIE[$key]),0,16))
            {
                return '';
            }
            else
            {
                return $_COOKIE[$key];
            }
        }
    }
}
/**
     *  获取整数值
     *
     * @access    public
     * @param     string  $fnum  处理的数值
     * @return    string
     */
    function GetNum($fnum){
        $fnum = preg_replace("/[^0-9\.]/", '', $fnum);
        return $fnum;
    }

根据传入字符串,找到cookie相应的值,但校验了$_COOKIE[$key.'__ckMd5']

使用的$ cfg_cookie_encode是在程序安装时设置的。无法破解$key.'__ckMd5'

GetNum()函数则是对GetCookie()函数返回的$_COOKIE[$key]值进行处理,获取整数值。

漏洞利用

在文件/menber/index.php中,找到这么一段代码

/*-----------------------------
//会员空间主页
function space_index(){  }
------------------------------*/
else
{
    require_once(DEDEMEMBER.'/inc/config_space.php');
    if($action == '')
    {
        include_once(DEDEINC."/channelunit.func.php");
        $dpl = new DedeTemplate();
        $tplfile = DEDEMEMBER."/space/{$_vars['spacestyle']}/index.htm";

        //更新最近访客记录及站点统计记录
        $vtime = time();
        $last_vtime = GetCookie('last_vtime');
        $last_vid = GetCookie('last_vid');
        if(empty($last_vtime))
        {
            $last_vtime = 0;
        }
        if($vtime - $last_vtime > 3600 || !preg_match('#,'.$uid.',#i', ','.$last_vid.',') )
        {
            if($last_vid!='')
            {
                $last_vids = explode(',',$last_vid);
                $i = 0;
                $last_vid = $uid;
                foreach($last_vids as $lsid)
                {
                    if($i>10)
                    {
                        break;
                    }
                    else if($lsid != $uid)
                    {
                        $i++;
                        $last_vid .= ','.$last_vid;
                    }
                }
            }
            else
            {
                $last_vid = $uid;
            }
            PutCookie('last_vtime', $vtime, 3600*24, '/');
            PutCookie('last_vid', $last_vid, 3600*24, '/');
$last_vid为空把$uid赋值给$last_vid,而$uid是可控的用户名,再通过PutCookie()函数写到cookie中。

这里加入构造出类似0000001的用户名,用last_vid_ckMd5的值 == ($cfg_cookie_encode.$_COOKIE['last_vie'])的MD5的前16位,满足条件。

接着在登录类的构造函数中,midGetNum()intval()函数的过滤,就形成了1,接着进入数据库查询再展示到页面。

复现

前台注册普通用户,这里注册一个0001
访问/member/index.php?uid=0001,获取last_vid__ckMd5的值


1.jpg



接下来使用0001账号登录,登录后的未修改的cookie。

2.jpg

last_vid的值赋给DedeUserIDlast_vidckMd5的值赋给DedeUserIDckMd5修改后的cookie。

3.jpg

修改后刷新页面

4.jpg

本文标签:

版权声明:若无特殊注明,本文皆为《颓废》原创,转载请保留文章出处。

收录状态:[百度已收录] | [360已收录] | [搜狗已收录]

本文链接:DedeCMS任意前台用户登录漏洞(cookie伪造) - https://www.0dayhack.com/post-833.html

严重声明:本站内容来自于互联网,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规,黑客不是骇客,黑客维护网络安全

发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论

2条评论
  1. avatar

    一个人 Lv.1 uBrowser 8.7 uBrowser 8.7 Windows Windows 回复

    登陆了会员  如何开始提权

    河北省衡水市冀州市 联通

    1. avatar

      15601581465 Lv.1 Chrome 65.0.3325.181 Chrome 65.0.3325.181 Windows 7 x64 Edition Windows 7 x64 Edition 回复

      表情

      江苏省南京市 电信