1. 程式人生 > >DedeCMS---V5.7_UTF8_SP1、SP2---任意前臺用戶登錄(cookie偽造)

DedeCMS---V5.7_UTF8_SP1、SP2---任意前臺用戶登錄(cookie偽造)

!= 為我 BE OS tex AD gpo cut body

漏洞觸發點在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‘。所以一般情況下,我們是無法破解$key.‘__ckMd5‘這類值的。

GetNum()函數則是對GetCookie()函數返回的$_COOKIE[$key]值進行處理,獲取整數值。

正常情況下,程序中的DedeUserID就是當前用戶的用戶ID。但是如果將其中的DedeUserID和DedeUserID__ckMd5都替換為其他的賬戶,是否就意味著我們可以以其他的賬戶登錄呢?

那麽現在的問題就在於,如何進行偽造呢?我們知道管理員admin的mid是1,但是我們如何得到對應的DedeUserID__ckMd5呢?所以目前的問題轉變為我們需要得到1所對應的DedeUserID__ckMd5的。

漏洞利用點:

在文件/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或1abcde這樣的用戶名,用我last_vid_ckMd5的值 == ($cfg_cookie_encode.$_COOKIE[‘last_vie‘])的MD5的前16位,滿足條件。

接著在登錄類的構造函數中,mid經GetNum()和intval()函數的過濾,就形成了1,接著進入數據庫查詢再展示到頁面。

在用戶空間主頁:

http://localhost/DedeCMS/member/index.php?uid=001

這裏代碼根據用戶提交的參數uid調用了Getcookie()函數生成了cookie值即相應的$_COOKIE[$key]和$_COOKIE[$key.‘__ckMd5‘]值。

由於GetNum()函數的處理,我們在復現的時候註冊攻擊賬號時應使用001、0001、00001之類的用戶名來繞過該函數,從而達到以管理員的身份登錄前臺。

---V5.7_UTF8_SP1、SP2---

DedeCMS---V5.7_UTF8_SP1、SP2---任意前臺用戶登錄(cookie偽造)