首页 > 代码库 > ThinkPHP 3.1,3.2中对IN和BETWEEN正则匹配不当导致的一个SQLi

ThinkPHP 3.1,3.2中对IN和BETWEEN正则匹配不当导致的一个SQLi

 1     // where子单元分析
 2     protected function parseWhereItem($key,$val) {
 3         $whereStr = ‘‘;
 4         if(is_array($val)) {
 5             if(is_string($val[0])) {
 6                 if(preg_match(‘/^(EQ|NEQ|GT|EGT|LT|ELT)$/i‘,$val[0])) { // 比较运算
 7                     $whereStr .= $key.‘ ‘.$this->comparison[strtolower($val[0])].‘ ‘.$this->parseValue($val[1]);
 8                 }elseif(preg_match(‘/^(NOTLIKE|LIKE)$/i‘,$val[0])){// 模糊查找
 9                     if(is_array($val[1])) {
10                         $likeLogic  =   isset($val[2])?strtoupper($val[2]):‘OR‘;
11                         if(in_array($likeLogic,array(‘AND‘,‘OR‘,‘XOR‘))){
12                             $likeStr    =   $this->comparison[strtolower($val[0])];
13                             $like       =   array();
14                             foreach ($val[1] as $item){
15                                 $like[] = $key.‘ ‘.$likeStr.‘ ‘.$this->parseValue($item);
16                             }
17                             $whereStr .= ‘(‘.implode(‘ ‘.$likeLogic.‘ ‘,$like).‘)‘;                          
18                         }
19                     }else{
20                         $whereStr .= $key.‘ ‘.$this->comparison[strtolower($val[0])].‘ ‘.$this->parseValue($val[1]);
21                     }
22                 }elseif(‘exp‘==strtolower($val[0])){ // 使用表达式
23                     $whereStr .= ‘ (‘.$key.‘ ‘.$val[1].‘) ‘;
24                 }elseif(preg_match(‘/IN/i‘,$val[0])){ // IN 运算
25                     if(isset($val[2]) && ‘exp‘==$val[2]) {
26                         $whereStr .= $key.‘ ‘.strtoupper($val[0]).‘ ‘.$val[1];
27                     }else{
28                         if(is_string($val[1])) {
29                              $val[1] =  explode(‘,‘,$val[1]);
30                         }
31                         $zone      =   implode(‘,‘,$this->parseValue($val[1]));
32                         $whereStr .= $key.‘ ‘.strtoupper($val[0]).‘ (‘.$zone.‘)‘;
33                     }
34                 }elseif(preg_match(‘/BETWEEN/i‘,$val[0])){ // BETWEEN运算
35                     $data = is_string($val[1])? explode(‘,‘,$val[1]):$val[1];
36                     $whereStr .=  ‘ (‘.$key.‘ ‘.strtoupper($val[0]).‘ ‘.$this->parseValue($data[0]).‘ AND ‘.$this->parseValue($data[1]).‘ )‘;
37                 }else{
38                     throw_exception(L(‘_EXPRESS_ERROR_‘).‘:‘.$val[0]);
39                 }
40             }else {
41                 $count = count($val);
42                 $rule  = isset($val[$count-1])?strtoupper($val[$count-1]):‘‘;
43                 if(in_array($rule,array(‘AND‘,‘OR‘,‘XOR‘))) {
44                     $count  = $count -1;
45                 }else{
46                     $rule   = ‘AND‘;
47                 }
48                 for($i=0;$i<$count;$i++) {
49                     $data = is_array($val[$i])?$val[$i][1]:$val[$i];
50                     if(‘exp‘==strtolower($val[$i][0])) {
51                         $whereStr .= ‘(‘.$key.‘ ‘.$data.‘) ‘.$rule.‘ ‘;
52                     }else{
53                         $op = is_array($val[$i])?$this->comparison[strtolower($val[$i][0])]:‘=‘;
54                         $whereStr .= ‘(‘.$key.‘ ‘.$op.‘ ‘.$this->parseValue($data).‘) ‘.$rule.‘ ‘;
55                     }
56                 }
57                 $whereStr = substr($whereStr,0,-4);
58             }
59         }else {
60             //对字符串类型字段采用模糊匹配
61             if(C(‘DB_LIKE_FIELDS‘) && preg_match(‘/(‘.C(‘DB_LIKE_FIELDS‘).‘)/i‘,$key)) {
62                 $val  =  ‘%‘.$val.‘%‘;
63                 $whereStr .= $key.‘ LIKE ‘.$this->parseValue($val);
64             }else {
65                 $whereStr .= $key.‘ = ‘.$this->parseValue($val);
66             }
67         }
68         return $whereStr;
69     }

第24行的preg_match(‘/IN/i‘,$val[0])

第34行的preg_match(‘/BETWEEN/i‘,$val[0])

两个正则表达式没有设置起始,因此xxxinxxxx,xxxbetweenxxx的字符串都可以匹配成功,因而构成了注入。

ThinkPHP 3.1,3.2中对IN和BETWEEN正则匹配不当导致的一个SQLi