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

颓废 2019年5月19日08:52:42评论1,190 views字数 3149阅读10分29秒阅读模式
摘要

漏洞触发点在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}'

漏洞触发点在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的值

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

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

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

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

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

修改后刷新页面

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

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
颓废
  • 本文由 发表于 2019年5月19日08:52:42
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   DedeCMS任意前台用户登录漏洞(cookie伪造)http://cn-sec.com/archives/67916.html

发表评论

匿名网友 填写信息