新聞詳情

分享 | Metinfo 6.1.2 SQL注入漏洞分析

漏洞簡介

Metinfo 米拓企業建站系統是一款適合企業網站建設的開源CMS系統,近期互聯網上公開爆出 Metinfo 6.1.2 版本存在SQL注入漏洞,隨后一秋網絡安全團隊對其漏洞進行了復現與分析。


漏洞分析

漏洞觸發的代碼在 /app/system/message/web/message.class.php 文件 第37行,add方法部分。

public function add($info) {
        global $_M;
        if(!$_M[form][id]){
           $message=DB::get_one("select * from {$_M[table][column]} where module= 7 and lang ='{$_M[form][lang]}'");
           $_M[form][id]=$message[id];
        }
        $met_fd_ok=DB::get_one("select * from {$_M[table][config]} where lang ='{$_M[form][lang]}' and  name= 'met_fd_ok' and columnid = {$_M[form][id]}");
        $_M[config][met_fd_ok]= $met_fd_ok[value];
        if(!$_M[config][met_fd_ok])okinfo('javascript:history.back();',"{$_M[word][Feedback5]}");
        if($_M[config][met_memberlogin_code]){
            if(!load::sys_class('pin', 'new')->check_pin($_M['form']['code'])){

                        okinfo(-1, $_M['word']['membercode']);
            }
        }


從上述代碼分析發現  $met_fd_ok=DB::get_one("select * from {$_M[table][config]} where lang ='{$_M[form][lang]}' and  name= 'met_fd_ok' and columnid = {$_M[form][id]}");語句中 {$_M[form][id]} 參數,沒有用單引號引起來判斷此處應該有SQL注入漏洞。

直接拼接SQL 注入payload發現,注入的payload被過濾,無法直接進行SQL注入。繼續往下分析。

繼續分析發現 message.class.php 文件 調用了 class feedback extends web  父類初始化函數,跟進web類。

web類定義在  /app/system/include/class/web.class.php 文件。分析web類,沒有發現對參數進行過濾的函數,但是發現初始化了 common類。 跟進common類,定義在/app/system/include/class/common.class.php文件。

public function __construct() {
        global $_M;//全局數組$_M
        ob_start();//開啟緩存
        $this->load_mysql();//數據庫連接
        $this->load_form();//表單過濾
        $this->load_lang();//加載語言配置
        $this->load_config_global();//加載全站配置數據
        $this->load_url_site();
        $this->load_config_lang();//加載當前語言配置數據
        $this->load_url();//加載url數據
    }


發現問題關鍵點,$this->load_form();//表單過濾,繼續跟進$this->load_form();函數。

/app/system/include/class/common.class.php文件51行、

protected function load_form() {
        global $_M;
        $_M['form'] =array();
        isset($_REQUEST['GLOBALS']) && exit('Access Error');
        foreach($_COOKIE as $_key => $_value) {
            $_key{0} != '_' && $_M['form'][$_key] = daddslashes($_value);
        }
        foreach($_POST as $_key => $_value) {
            $_key{0} != '_' && $_M['form'][$_key] = daddslashes($_value);
        }
        foreach($_GET as $_key => $_value) {
            $_key{0} != '_' && $_M['form'][$_key] = daddslashes($_value);
        }
        if(is_numeric($_M['form']['lang'])){//偽靜態兼容
            $_M['form']['page'] = $_M['form']['lang'];
            $_M['form']['lang'] = '';
        }
        if($_M['form']['metid'] == 'list'){
            $_M['form']['list'] = 1;
            $_M['form']['metid'] = $_M['form']['page'];
            $_M['form']['page'] = 1;
        }
        if(!preg_match('/^[0-9A-Za-z]+$/', $_M['form']['lang']) && $_M['form']['lang']){
            echo "No data in the database,please reinstall.";
            die();
        }
    }


這里看到把 POST、GET、COOKIE 傳遞過來的參數用daddslashes進行了全局過濾。跟進 daddslashes。


function daddslashes($string, $force = 0) {
    !defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
    if(!MAGIC_QUOTES_GPC || $force) {
        if(is_array($string)) {
            foreach($string as $key => $val) {
                $string[$key] = daddslashes($val, $force);
            }
        } else {
           if(!defined('IN_ADMIN')){
                $string = trim(addslashes(sqlinsert($string)));
            }else{
                $string = trim(addslashes($string));
            }
        }
    }
    return $string;
}


這里判斷是否開啟了get_magic_quotes_gpc() ,如果沒開啟或者 $force不為空就進入下面的邏輯。有判斷了是否定義IN_ADMIN 常量,如果沒有定義就進入 $string = trim(addslashes(sqlinsert($string)));,從代碼邏輯發現我們第一步進行SQL注入,失敗是因為注入的payload被過濾導致,那么我們傳遞的值應該就是進入了這個過濾,用sqlinsert函數進行了過濾。

看一下sqlinsert函數是怎么進行的過濾。

function sqlinsert($string){
    if(is_array($string)){
        foreach($string as $key => $val) {
            $string[$key] = sqlinsert($val);
        }
    }else{
        $string_old = $string;
        $string = str_ireplace("\\\\","/",$string);
        $string = str_ireplace("\\"","/",$string);
        $string = str_ireplace("'","/",$string);
        $string = str_ireplace("*","/",$string);
        $string = str_ireplace("%5C","/",$string);
        $string = str_ireplace("%22","/",$string);
        $string = str_ireplace("%27","/",$string);
        $string = str_ireplace("%2A","/",$string);
        $string = str_ireplace("~","/",$string);
        $string = str_ireplace("select""\\sel\\ect", $string);
        $string = str_ireplace("insert""\\ins\\ert", $string);
        $string = str_ireplace("update""\\up\\date", $string);
        $string = str_ireplace("delete""\\de\\lete", $string);
        $string = str_ireplace("union""\\un\\ion", $string);
        $string = str_ireplace("into""\\in\\to", $string);
        $string = str_ireplace(<span class="hljs-string" style="f

欧美最新精品videossexohd_激烈的床震戏大叫视频_可以直接在线看的毛片