Thinkphp 3.2.3 where注入 select/delete

    public function test01()
    {
        $data = M('user')->find(I('GET.id'));
        var_dump($data);
    }

payload:http://tp32.com/index.php/home/index/test01?id[where]=1 and 1=updatexml(1,concat(0x7e,database(),0x7e),1)

漏洞分析:

首先在如下地方进行下断点分析

一开始肯定是触发自动加载机制,实例化一个数据库操作对象

返回接着进入到 I 方法中对接收的参数进行分割判断

然后 I 方法中进行一次 htmlspecialchars 和 think_filter 的过滤处理

随后从I方法中出来之后就进入到了 find 方法中

接着来到进入 _parseOptions 方法中,来进行字段的验证的处理

主要是这段代码,当我们id[where]是这样的时候,这段代码是不走的,因为is_array($options['where'])这个条件不满足

出来了之后接着继续走select 方法

之后的都很正常数据也没被处理,最后导致了SQL注入

那么最主要的原因其实也就是 _parseOptions 方法中 字段类型验证 ,如果is_array($options['where'])这个条件满足,那么我们注入的SQL语句都会被_parseType 进行强转,如果是id[where]则导致不满足,从而产生了SQL注入!

那么我们来跟下如果传入的url是http://tp32.com/index.php/home/index/test01?id=1 and 1=updatexml(1,concat(0x7e,database(),0x7e),1),结果会如何

首先这里会让$options[where]下面成为一个数组

然后继续进入到 _parseOptions 方法中

此时该条件满足 所以进入到 字段类型验证的操作

接着继续进入到 _parseType 的方法中该id字段下的内容,就是sql注入的内容就会被强转为 int 类型 导致最后无法触发!!!

修复代码:

https://github.com/top-think/thinkphp/commit/9e1db19c1e455450cfebb8b573bb51ab7a1cef04

v3.2.4 将 $options 和 $this->options 进行了区分,从而传入的参数无法污染到 $this->options,也就无法控制sql语句了

参考文章:https://y4er.com/post/thinkphp3-vuln/

原文地址:https://www.cnblogs.com/zpchcbd/p/12551624.html