S0cke3t
文章33
标签25
分类10
ThinkPHP3.2.3 SQL injection analysis

ThinkPHP3.2.3 SQL injection analysis

漏洞成因

该注入出现在后端对数组型参数处理不当,可绕过参数过滤设置。导致恶意sql语句执行

环境设置

数据库配置

在/application/home/conf/config.php中添加如下代码

 <?php  
return array(  
  //'配置项'=>'配置值'  
  'DB_TYPE' => 'mysql',  
  'DB_HOST' => 'localhost',  
  'DB_NAME' => 'tp',  
  'DB_USER' => 'root',  
  'DB_PWD' => 'root',  
  'DB_PORT' => '3306',  
  'DB_FIELDS_CACHE' => true,  
  'DB_CHARSET' => 'utf8',  
  ''  
);

参数值根据具体情况进行填写
随后在mysql中新建与配置名称相同的数据库,并新建user表在其中添加三个字段id,username,password.并设置id为自增主键,最后在表中插入一条数据。

项目设置

在/Application/Home/Controller/IndexController.class.php文件index()函数中添加如下代码

 $id = I('id');  
$res = M('user')->find($id);  
var_dump($res);

在浏览器中访问http://localhost/index.php?m=Home&c=Index&a=index&id=1,如果出现

则证明设置正常

漏洞分析

将网上公开的poc带入到url中,进行断点调试。poc如下

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

先来看I函数,首先进行参数来源的判断,默认自动判断为param随后通过$_SERVER['REQUEST_METHOD']获取参数传递方式

随后调用C函数获取配置文件的DEFAULT_FILTER加载默认filter,然后调用array_map_recursive进行参数过滤

跟进array_map_recursive

依次取出data值,使用call_user_func对data值进行过滤。最后调用thinkphp底层过滤函数think_filter

跟进

可以看到整个过程未对我们的poc产生影响,那么问题应该出现在后续的操作中。继续往下走进入到find函数中

首先对$option也就是我们传入的参数值进行判断,如果为数字或者字符串则使用默认where条件,此处option为数组并不满足条件,继续往下走进行复合主键的查询,由于我们的user表中只有一个主键所以条件也不满足,随后进入到_parseOptions函数进行表达式解析,跟进


此处虽然使用了_parseType对参数进行类型强转,但是根据我们传入的参数列表option[where]并不满足字段类型检测条件,所以就成功的进行了绕过

继续往下走,在分析完表达式后调用db->select()

跟进

继续调用buildselectsql进行sql语句的解析

继续调用parseSql

此函数负责将%xxxx%的表达式替换为sql语句,其中在进行表达式替换时直接使用的前端传入的option[‘where’],随后在parseWhere中也未进行合法性校验,直接使用了传入的字符串where条件


随后将sql语句带入到db->driver->query()中进行查询


调用堆栈如下

本文作者:S0cke3t
本文链接:https://www.saferoad.cc/Analysis/ThinkPHP3-2-3-SQL-injection-analysis.html
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可
×