天天看點

代碼審計之_douphp20190711漏洞代碼審計之_douphp20190711漏洞

代碼審計之_douphp20190711漏洞

  • 代碼審計之_douphp20190711漏洞
    • 1.安裝時參數控制不嚴謹getshell
      • 1.1 審計過程
      • 1.2 分析漏洞
    • 2.背景任意檔案删除
    • 3.遇到的坑
      • 3.1 對于檔案上傳進行審計
      • 3.2對于賬戶登入的記錄的ip是否可注入的猜測
    • 4.總結
    • 4.總結

代碼審計之_douphp20190711漏洞

下載下傳連結http://down.douco.com/DouPHP_1.5_Release_20190711.rar

1.安裝時參數控制不嚴謹getshell

1.1 審計過程

在審計的時候,直接使用了被動加主動掃描,安裝douphp以及進行正常測試,在沒有頭緒的時候看了一下掃描日志,發現了代碼執行,檢視漏洞點在/install/index.php下161-173行,由于對傳入的參數沒有嚴格過濾,并且對于寫入的參數進行雙引号包裹,導緻傳入的參數會被直接當作函數執行

代碼審計之_douphp20190711漏洞代碼審計之_douphp20190711漏洞

1.2 分析漏洞

首先檢查data/install.lock檔案是否存在,如果不存在進行下一步的操作

對于傳入的參數進行了全局過濾,使用addslashes進行處理,但是,沒有對其他參數進行過濾,将檔案直接寫入之後并且進行包含即可檢視代碼執行結果。

<?php
$dbpass   = "${@eval(phpinfo())};";
?>
           

直接寫下如下代碼也會産生如此漏洞

在新版中修複了這個問題,把單引号替換成雙引号

代碼審計之_douphp20190711漏洞代碼審計之_douphp20190711漏洞

但是一個安裝漏洞一般都是比較雞肋的,如果沒有任意檔案删除的話是沒有任何作用的于是接下來開始了任意檔案删除漏洞的挖掘

2.背景任意檔案删除

看一下官方的更新日志

代碼審計之_douphp20190711漏洞代碼審計之_douphp20190711漏洞

修正背景安全問題,檢視更新代碼

代碼審計之_douphp20190711漏洞代碼審計之_douphp20190711漏洞

發現對于删除的檔案名進行了正則過濾,繼續向上查找被過濾的參數,從資料庫的mobile_logo取出的value值

代碼審計之_douphp20190711漏洞代碼審計之_douphp20190711漏洞

我們繼續檢視value值是否可控,查找相關對于這個 字段的操作。

這裡面的act 操作參數為clear_logo,通過我們對于背景參數傳遞的觀察,發現在admin/mobile.php下有一個删除logo操作,引起了我們的主意,檢視傳遞參數,跟蹤代碼,發現時一個檔案上傳操作,嘗試修改檔案名稱上傳,但是背景的參數一直時logo.png 檢視背景代碼

核心代碼在mobile.php下62-69行

代碼審計之_douphp20190711漏洞代碼審計之_douphp20190711漏洞

檢視代碼時把post傳遞過來的鍵值和鍵名指派,之後通過update傳遞進入資料庫存儲,并沒有對檔案名進行操作,于是檢視資料包,進行修改

代碼審計之_douphp20190711漏洞代碼審計之_douphp20190711漏洞

發現可以成功修改資料庫内容,繼續檢視圖檔上傳目錄在 \m\theme\default\images目錄下,直接構造payload“…/…/…/…/data/install.lock” 存入資料庫,執行clrea_logo操作,成功删除data/install.lock檔案,之後我們就可以勇敢上面的安裝漏洞進行shell寫入。

3.遇到的坑

3.1 對于檔案上傳進行審計

function upload($file_field, $file_name = '') {
        if ($GLOBALS['dou']->check_read_write($this->full_file_dir) != 'write') {
            $GLOBALS['dou']->dou_msg($GLOBALS['_LANG']['file_dir_wrong']);
        }
        
        // 沒有命名規則預設以時間作為檔案名
        if (empty($file_name))
            $file_name = $GLOBALS['dou']->create_rand_string('number', 6, time()); // 設定目前時間為圖檔名稱
        
        if (@ empty($_FILES[$file_field]['name']))
            $GLOBALS['dou']->dou_msg($GLOBALS['_LANG']['file_empty']);

        $name = explode(".", $_FILES[$file_field]["name"]); // 将上傳前的檔案以“.”分開取得檔案類型
        $img_count = count($name); // 獲得截取的數量
        $img_type = $name[$img_count - 1]; // 取得檔案的類型
        if (stripos($this->file_type, $img_type) === false) {
            $GLOBALS['dou']->dou_msg($GLOBALS['_LANG']['file_support'] . $this->file_type . $GLOBALS['_LANG']['file_support_no'] . $img_type);
        }
        $full_file_name = $file_name . "." . $img_type; // 寫入資料庫的檔案名
        $file_address = $this->full_file_dir . $full_file_name; // 上傳後的檔案名稱
        $file_ok = move_uploaded_file($_FILES[$file_field]["tmp_name"], $file_address);
        if ($file_ok) {
            $img_size = $_FILES[$file_field]["size"];
            $img_size_kb = round($img_size / 1024);
            if ($img_size_kb > $this->file_size_max) {
                @unlink($file_address);
                $GLOBALS['dou']->dou_msg($GLOBALS['_LANG']['file_out_size'] . $this->file_size_max . "KB");
            } else {
                return $full_file_name;
            }
        } else {
            $GLOBALS['_LANG']['file_wrong'] = preg_replace('/d%/Ums', $this->file_size_max, $GLOBALS['_LANG']['file_wrong']);
            $GLOBALS['dou']->dou_msg($GLOBALS['_LANG']['file_wrong']);
        }
    }
           

對于upload函數進行審計,發現使用了白名單模式,隻能對于圖檔檔案進行寫入,如果圖檔檔案的字尾存在于白名單中,将擷取的檔案字尾直接當作檔案的字尾,并且進行寫入,通過%00截斷等方式已經沒有作用,如果沒有檔案包含等漏洞的話,是沒有辦法利用的

3.2對于賬戶登入的記錄的ip是否可注入的猜測

我們登入到背景可以發現,系統對于操作的ip進行記錄,這個ip在參數擷取時如果方式不正确,可以造成僞造,并且http header參數不在get post cookie參數裡,并沒有經過全局過濾,那麼這個時一個比較好的注入點,我們檢視登入頁面代碼

在admin/login.php下77行get_ip()函數,跟進函數

function get_ip() {
        static $ip;
        if (isset($_SERVER)) {
            if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
                $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
            } else if (isset($_SERVER["HTTP_CLIENT_IP"])) {
                $ip = $_SERVER["HTTP_CLIENT_IP"];
            } else {
                $ip = $_SERVER["REMOTE_ADDR"];
            }
        } else {
            if (getenv("HTTP_X_FORWARDED_FOR")) {
                $ip = getenv("HTTP_X_FORWARDED_FOR");
            } else if (getenv("HTTP_CLIENT_IP")) {
                $ip = getenv("HTTP_CLIENT_IP");
            } else {
                $ip = getenv("REMOTE_ADDR");
            }
        }
        
        if (preg_match('/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/', $ip)) {
            return $ip;
        } else {
            return '127.0.0.1';
        }
    }
           

檢視源代碼,心中一喜,這上面兩個參數都是可以僞造的,于是興緻沖沖的去僞造,但是發現背景并沒有成功幾率,ip反而變成了127.0.0.1 于是我們繼續檢視源碼,發現下面有一個正則,對ip進行了比對,,,,,

抱歉ip注入這個點我沒看過,我隻是一隻菜狗。

4.總結

檢視源代碼,心中一喜,這上面兩個參數都是可以僞造的,于是興緻沖沖的去僞造,但是發現背景并沒有成功幾率,ip反而變成了127.0.0.1 于是我們繼續檢視源碼,發現下面有一個正則,對ip進行了比對,,,,,

抱歉ip注入這個點我沒看過,我隻是一隻菜狗。

4.總結

對于這個cms 隻是找到了背景getshell 并且特征特别明顯,删除檔案并且重置的話這樣對于實際操作中,一旦使用這種方式很難 如果操作不當,很容易就會被警察叔叔請去喝茶,該漏洞已經在新版cms中修複。由于個人水準比較差,還沒有找到前台sql注入的方法,如果有前台sql注入,或者配合admin888或者資訊洩露等等可以進入背景,對網站進行重裝,getshell之後對資料進行修複,問題還是不大的。