Thinkphp框架 3.2.x sql注入漏洞
前言:
北京时间 2018年8月23号11:25分 星期四,tp团队对于已经停止更新的thinkphp 3系列进行了一处安全更新,经过分析,此次更新修正了由于select()
,find()
,delete()
方法可能会传入数组类型数据产生的多个sql注入隐患。
环境搭建:
程序下载地址:地址 PHPstudy:Apache+php7.1+MySQL 工具:PHPstorm
首先建立一个数据库名为:thinkphp
建立一个表名为:user
添加两个字段:name,pass
thinkphp3.2版本和之前的5版本略有不同,它的数据库信息文件是在 这个文件:thinkphp/ThinkPHP/Conf/convention.php
在这里面填上刚才建立的数据库信息:
打开thinkphp的调试模式: 在刚才的文件:thinkphp/ThinkPHP/Conf/convention.php 然后修改为true:
'SHOW_ERROR_MSG' => true, // 显示错误信息
3.2版本的控制器位置和5版本有点区别。文件位置thinkphp/Application/Home/Controller/IndexController.class.php在里面写一个简单的update的例子
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller
{
public function index()
{
$tj['name'] = I('name');
$data['pass'] = '111111';
$res = M("user")->where($tj)->save($data);
}
}
I函数和5版本的input助手函数差不多,地址
因为仅仅执行基本的CURD操作,所以用M方法来实例化数据库对象就行了。 实例化模型可以看:地址
漏洞分析:
这里也是用phpstorm+debug进行动态分析,如有不懂可以去查阅。 我们先在I函数这里下一个断点,看下I函数有没有过滤掉我们的输入。
然后访问我们payload,它会跳到入口文件,我们只要分析的是I函数执行的地方,所以我们直接F8跳到执行I函数地方:
F7跟进,它会跳到文件:thinkphp/ThinkPHP/Common/functions.php
这里。 判断传入的值是用什么方式:
接下来就是对我们传入的值进行过滤:
对我们传入的bind
值进行过滤:
然后执行我们的数据库更新的操作:
我们F7继续跟下去,有些影响不大的函数可以直接F8跳过去,到save
函数:
执行到update
函数我们F7跟进去:
我们继续往下,F7进入parseSet
函数,可以看到赋值了一个占位符0给pass
,代替我们的密码111111
。
parseSet
函数执行完后,我们继续F7进入parseWhere
函数。
我们再往下面的parseWhereItem
函数进行分析,这里写到,$exp
=$val[0]
也就是我们传入的bind
。
$exp = strtolower($val[0])
这里判断如果我们传入的数组[0]为bind
就进行拼接:
从拼接这里也能看出我们为什么要把第二个数组构造的时候填0,因为是要对应上面parseSet
函数,赋值了一个占位符为0,用来代替上面的密码111111
,而接下来就没有这种赋值操作了,所以我们如果填其他值得话执行SQL语句的时候就会报错,到后面我会点出在哪里的。
我们继续,F7进去执行预处理语句的地方:
我们可以看到这里用到了bindValue
,绑定一个值到一个参数,也就是把111111
密码绑定到:0这里。
继续跟下来,到SQL语句执行报错的地方,可以很清楚看到直接了我们的报错语句updatexml
的值:
我们再往error
函数跟,可以看到替换掉占位符的语句:
- 如果我们把0换成1会是怎么样的结果呢? 访问payload,注意已经把数组第二个0改成1了。
http://127.0.0.1/thinkphp/index.php?name[0]=bind&name[1]=1 and updatexml(2,concat(0x7e,user()),0)
我们把断点直接断在SQL执行的地方:
F7进去然后F8直接走,走到执行报错的地方,我们就会看到如果为1的话那SQL就无法执行下去了。
漏洞复现:
Payload:http://127.0.0.1/thinkphp/index.php?id[]=bind&id[]=1%27&money[]=1123&user=liao
那么我们将id[1]数组的参数变为0呢?id[]=bind&id[]=0%27&money[]=1123&user=liao
最终Payload: http://127.0.0.1/thinkphp/index.php?name[0]=bind&name[1]=0 and updatexml(2,concat(0x7e,user()),0)
修复建议:
更新最新补丁ht#tps#:/#/githu#b.com/t#op-think/thi#nkphp/commit/7e47e34af72996497c90c20bcfa3b2e1cedd7fa4