DiscuzX系列命令執行分析公開(三連彈)

tang3 · 2015/01/15 18:55php

0x00 漏洞概要


昨天360補天發了這樣的一條微博:chrome

enter image description here

而後打聽了一下細節,發現竟然是我13年7月報給TSRC的漏洞,看今天你們玩的挺開心,與TSRC的人聊了兩句,說這個系列能夠發幾個了,因此我也來湊個熱鬧,把原來的分析發出來給你們看一下(這裏作個廣告,TSRC提交Discuz的漏洞,獎品棒棒噠~~)。這個漏洞原來我是做爲前臺命令執行發個TSRC的,雖然有限制,可是我的感受仍是不錯的。只發一個怕各位不過癮,就再來一發這個點比較直觀的後臺命令執行和繞過前臺命令執行的修復。原TSRC上的漏洞標題是《Discuz! X系列遠程命令執行漏洞(二)》、《Discuz! X系列遠程命令執行漏洞(三)》和《Discuz! X系列遠程命令執行漏洞(四)》。網絡

下面是原漏洞報告的概要部分:curl

「騰訊旗下Discuz! X系列cms存在遠程命令執行漏洞,經測試在其2013年6月20日發佈的最新版本的Discuz! X3中仍存在此問題。目前這個漏洞還沒有在網絡中流傳,屬於0day漏洞。 這個漏洞存在於圖片裁剪功能中,須要管理員啓用ImageMagick上傳圖片功能方可觸發。此漏洞只需一個可訪問論壇內容的帳號,便可利用。」函數

0x01 原理分析


0. 必定條件下前臺命令執行


這個漏洞出如今\source\class\class_image.php文件中的Thumb_IM()函數,問題代碼以下:測試

#!php
function Thumb_IM() {
        switch($this->param['thumbtype']) {
            case 'fixnone':
            case 1:
                if($this->imginfo['width'] > $this->param['thumbwidth'] || $this->imginfo['height'] > $this->param['thumbheight']) {
                    $exec_str = $this->param['imageimpath'].'/convert -quality '.intval($this->param['thumbquality']).' -geometry '.$this->param['thumbwidth'].'x'.$this->param['thumbheight'].' '.$this->source.' '.$this->target;
                    $return = exec($exec_str);
                    if(!file_exists($this->target)) {
                        return -3;
                    }
                }
                break;
//省略部分代碼
複製代碼

從第一行紅色代碼中能夠看出,程序經過一些變量的拼接造成一條系統命令,在第二行使用exec方法進行執行。若用戶能夠控制這些變量中的任何一個,那麼就可能致使任意命令的執行。fetch

1. 同點後臺命令執行


這個漏洞出如今\source\class\class_image.php文件中的Thumb_IM()函數,問題代碼以下:ui

#!php
function Thumb_IM() {
        switch($this->param['thumbtype']) {
            case 'fixnone':
            case 1:
                if($this->imginfo['width'] > $this->param['thumbwidth'] || $this->imginfo['height'] > $this->param['thumbheight']) {
                    $exec_str = $this->param['imageimpath'].'/convert -quality '.intval($this->param['thumbquality']).' -geometry '.$this->param['thumbwidth'].'x'.$this->param['thumbheight'].' '.$this->source.' '.$this->target;
                    $return = exec($exec_str);
                    if(!file_exists($this->target)) {
                        return -3;
                    }
                }
                break;
//省略部分代碼
複製代碼

從第一行紅色代碼中能夠看出,程序經過一些變量的拼接造成一條系統命令,在第二行使用exec方法進行執行。若用戶能夠控制這些變量中的任何一個,那麼就可能致使任意命令的執行。this

[email protected]! X系列遠程命令執行漏洞分析(二)》報告中提到過這個問題,也已經提交給騰訊修復了,使用的利用點是param['thumbwidth']和param[' thumbheight']。而此次我使用到param['imageimpath']這個參數,這個參數對應的是後臺配置中的「ImageMagick程序安裝路徑」。url

這個利用點應該是最後一個可控點了,由於param['thumbwidth']和param[' thumbheight']在提交給騰訊後添加了整形校驗轉換,沒法傳遞字符串。而source和target須要在前面進行文件和文件是否存在的驗證,沒法自由發揮☹。

下面來看一下傳遞param['imageimpath']這個參數的代碼,它的位置在\source\admincp\admincp_checktools.php文件中:

#!php
$settingnew = $_GET['settingnew'];
    if(!empty($_GET['previewthumb'])) {
        $_G['setting']['imagelib'] = $settingnew['imagelib'];
        $_G['setting']['imageimpath'] = $settingnew['imageimpath'];
        $_G['setting']['thumbwidth'] = $settingnew['thumbwidth'];
        $_G['setting']['thumbheight'] = $settingnew['thumbheight'];
        $_G['setting']['thumbquality'] = $settingnew['thumbquality'];

        require_once libfile('class/image');
        @unlink(DISCUZ_ROOT.$_G['setting']['attachdir'].'./temp/watermark_temp1.jpg');
        @unlink(DISCUZ_ROOT.$_G['setting']['attachdir'].'./temp/watermark_temp2.jpg');
        $image = new image;
//省略部分代碼
複製代碼

能夠從紅色代碼出看到imageimpath參數沒有進行任何過濾,便傳入到全局變量中了。在後面的image類中使用它也是直接從全局變量中提取,沒有作任何的過濾和校驗,下面是image類的構造函數代碼:

#!php
function image() {
        global $_G;
        $this->param = array(
            'imagelib'      => $_G['setting']['imagelib'],
            'imageimpath'       => $_G['setting']['imageimpath'],
            'thumbquality'      => $_G['setting']['thumbquality'],
            'watermarkstatus'   => dunserialize($_G['setting']['watermarkstatus']),
            'watermarkminwidth' => dunserialize($_G['setting']['watermarkminwidth']),
            'watermarkminheight'    => dunserialize($_G['setting']['watermarkminheight']),
            'watermarktype'     => $_G['setting']['watermarktype'],
            'watermarktext'     => $_G['setting']['watermarktext'],
            'watermarktrans'    => dunserialize($_G['setting']['watermarktrans']),
            'watermarkquality'  => dunserialize($_G['setting']['watermarkquality']),
        );
}
複製代碼

2. 前臺命令執行修復繞過


[email protected]! X系列遠程命令執行漏洞分析(二)[email protected]! X系列遠程命令執行漏洞分析(三)》兩篇報告中,將視角盯死在了Thumb_IM這個方法上。在修復後,這個方法的命令執行失敗,致使利用後續操做中止。

可是若是讓這個方法正常完成它的工做,那麼他後面的操做中仍是有不少修復中沒有考慮到的利用點。下面咱們來看下其中的一個利用點,source/class/class_image.php中的Cropper_IM方法:

#!php
function Cropper_IM() {
        $exec_str = $this->param['imageimpath'].'/convert -quality 100 '.
            '-crop '.$this->param['srcwidth'].'x'.$this->param['srcheight'].'+'.$this->param['srcx'].'+'.$this->param['srcy'].' '.
            '-geometry '.$this->param['dstwidth'].'x'.$this->param['dstheight'].' '.$this->source.' '.$this->target;
        exec($exec_str);
        if(!file_exists($this->target)) {
            return -3;
        }
}
複製代碼

從上面代碼能夠看出,這個方法先拼接命令,而後經過exec函數執行。在拼接的過程當中不少變量的內容是可控的,並且在到達這個方法以前沒有作足夠的校驗和過濾。從而致使攻擊者能夠經過傳遞一些帶有命令操做的內容,來達到命令執行的目的。

0x02 利用思路


0. 必定條件下前臺命令執行


看到這個漏洞點後,我就開始嘗試經過關鍵字從源碼中尋找調用Thumb_IM函數的地方。搜索到使用此函數的文件不少,可是因爲這個函數的前兩個參數都是和上傳文件的文件名相關,並且discuz對於上傳文件名作了隨機化命名和後綴白名單處理,因此致使前三個參數爲不可控點。

因此這以後我將目標點瞄準到圖片寬度和高度這幾個點,從中篩選參數未被寫死的可控調用。這樣我找到了\source\module\misc\misc_imgcropper.php文件,以後大量的時間花費在對於這個文件調用的業務邏輯的查找上。

1. 必定條件下前臺命令執行


2. 前臺命令執行修復繞過


漏洞的觸發點在source/module/misc/misc_imgcropper.php中,部分代碼以下:

#!php
$cropfile = md5($_GET['cutimg']).'.jpg';
$ictype = $_GET['ictype'];

if($ictype == 'block') {
        require_once libfile('function/block');
        $block = C::t('common_block')->fetch($_GET['bid']);
        $cropfile = block_thumbpath($block, array('picflag' => intval($_GET['picflag']), 'pic' => $_GET['cutimg']));
        $cutwidth = $block['picwidth'];
        $cutheight = $block['picheight'];
    } else {
        $cutwidth = $_GET['cutwidth'];
        $cutheight = $_GET['cutheight'];
    }
    $top = intval($_GET['cuttop'] < 0 ? 0 : $_GET['cuttop']);
    $left = intval($_GET['cutleft'] < 0 ? 0 : $_GET['cutleft']);
    $picwidth = $cutwidth > $_GET['picwidth'] ? $cutwidth : $_GET['picwidth'];
    $picheight = $cutheight > $_GET['picheight'] ? $cutheight : $_GET['picheight'];

    require_once libfile('class/image');
    $image = new image();
    $prefix = $_GET['picflag'] == 2 ? $_G['setting']['ftp']['attachurl'] : $_G['setting']['attachurl'];
    if(!$image->Thumb($prefix.$_GET['cutimg'], $cropfile, $picwidth, $picheight)) {
        showmessage('imagepreview_errorcode_'.$image->errorcode, null, null, array('showdialog' => true, 'closetime' => true));
    }
    $image->Cropper($image->target, $cropfile, $cutwidth, $cutheight, $left, $top);
    showmessage('do_success', dreferer(), array('icurl' => $cropfile), array('showdialog' => true, 'closetime' => true));
}
複製代碼

能夠看到在最後調用了$image對象的Cropper方法,而這個過程當中$cutwidth和$cutheight都是用戶可控的變量,而且在執行到Cropper方法前沒有進行過任何校驗和過濾。

0x03 技術驗證


0. 必定條件下前臺命令執行


在管理員開啓ImageMagick上傳圖片功能的前提下,攻擊者只須要一個普通用戶權限便可,後臺設置方法以下圖:

enter image description here

因爲這個功能是對圖片進行處理的,因此,要在訪問時提供一個本站有效的圖片地址。並且最好是存放在data/attachment目錄下的,由於默認就是這個目錄,不然就要用「../」來修改路徑。

因此個人訪問路徑爲:

http://localhost/Discuz_X3.0/upload/misc.php?mod=imgcropper&img=group/19/group_36_banner.jpg
複製代碼

而後使用chrome審查元素功能,修改picwidth的value爲「||whoami&」,以下圖所示:

enter image description here

而後點擊網頁右下角的裁剪按鈕就觸發了。爲了能直觀顯示,我添加了一行代碼將接受執行結果的$return變量,echo出來並exit來結束掉後面的語句,效果以下圖所示:

enter image description here

1. 同點後臺命令執行


在後臺全局->上傳設置->ImageMagick 程序安裝路徑

enter image description here

因爲這個功能是對圖片進行處理的,因此,要在訪問時提供一個本站有效的圖片地址。並且最好是存放在data/attachment目錄下的,由於默認就是這個目錄,不然就要用「../」來修改路徑。

因此個人訪問路徑爲

http://192.168.188.142/DiscuzX3.1_1122/upload/misc.php?mod=imgcropper&img=forum/201312/05/094746ub04zw03jr4wi44m.jpg
複製代碼

而後直接點擊左下角的裁剪,雖然會返回圖片訪問錯誤,可是命令卻正常執行了,以下圖所示:

enter image description here

2. ImageMagick


這個漏洞須要在後臺開啓ImageMagick功能,並確保ImageMagick功能正常運行。下圖是我在後臺中開啓的這個功能,並填寫ImageMagick安裝目錄。

enter image description here

若是這個功能開啓,咱們甚至能夠在沒有帳號的狀況下,前臺完成命令執行的觸發。

首先訪問裁切圖片的這個功能,由於這個漏洞的觸發必需要有一張有效圖片,因此咱們能夠在論壇帖子中隨便找到一張圖片來引用。例如:個人發帖圖片是:

http://192.168.188.143/discuz20140604/data/attachment/forum/201406/13/155944d557e0dtcdpouoad.jpg
複製代碼

那麼我要訪問的裁切功能的URL爲:

http://192.168.188.143/discuz20140604/misc.php?mod=imgcropper&img=forum/201406/13/155944d557e0dtcdpouoad.jpg
複製代碼

而後修改POST數據包中cutheight或者cutwidth中的內容爲「%26%26mkdir tsrc||」提交,就能夠在discuz根目錄下建立一個tsrc的目錄。

修改輸入包以下圖所示:

enter image description here

提交後效果以下圖所示:

enter image description here

相關文章
相關標籤/搜索