sql注入实战——thinkPHP
sql注入实战——thinkPHP
thinkPHP前期环境搭建
下载thinkPHP文件
解压,将framework关键文件放到think-5.0.15中,改名为thinkphp
再将think-5.0.15放到WWW文件夹中
输入localhost/WWW/think-5.0.15/public/index.php,访问应用入口文件
搭建完成
创建数据库
登入mysql
创建数据库
修改数据库连接文件 \phpstudy_pro\WWW\think-5.0.15\application\database.php
编写控制器——编写一个get传参,传参uesrname,默认值为a
将上面get传参获得的username插入到数据库users里面
db('users')->insert(['username' => $username]);
开始寻找漏洞点
输入SQL注入语句
http://localhost/think-5.0.15/public/index.php?username[0]=inc&username[1]=updatexml(1,concat(0x7e,user(),0x7e),1)&username[2]=1
注入成功
漏洞分析
官方发布的5.0.16版本更新说明中,发现其中提到了该版本修复了一个漏洞
查阅commit记录,发现其修改的Builder.php文件代码比较可疑 从官网的更新日记中可以看到(绿色为新添加补丁)漏洞大概率出于此处
接着我们直接跟着上面的攻击payload看看漏洞原理。首先payload数据经过thinkphp内置方法的过滤后直接进入了$thik->builder的insert方法,所以从insert函数开始
断点下到insert语句,可以看到username传参1个数组,分别是我们输入的三个变量
- username[0]=inc
- username[1]=updatexml(1,concat(0x7e,user(),0x7e),1)
- username[2]=1
之后走到db类中的insert方法
这是数据库的连接,跳出,来到insert函数
此处的$data中一个数组,三个变量即
- username[0]=inc
- username[1]=updatexml(1,concat(0x7e,user(),0x7e),1)
- username[2]=1
来到sql语句,传递data,options,replace三个传参
data:一个数组三个变量,同上
options:表名table=“users”
进入builder的insert方法中
而 Mysql类继承于 Buider 类,即上面的this->builder->insert()最终调用的是 Builder 类的 insert方法。在 insert 方法中,我们看到其调用 parseData方法来分析并处理数据,而 parseData方法直接将来自用户的数据val[1]进行了拼接返回。我们的恶意数据存储在val[1]中,虽经过了 parseKey 方法处理,当丝毫不受影响,因为该方法只是用来解析处理数据的,并不是清洗数据。
进入parseData
data = [username=array(3)]
key = “username”
val = array(3)=
- array(0)=“inc”
- array(1)=“updatexml(1,concat(0x7e,user(),0x7e),1)”
- array(2)=“1”
往下滑,找到补丁处
从上面可以看到直接将用户数据进行拼接,然后再回到Builder类的insert方法,直接通过替换字符串的方式,将data填充到sql语句中,造成sql注入漏洞
break跳出,得到result
退出insert函数
keys和values的处理
最后进行sql的拼接,其中values等于我们的报错注入语句,所以漏洞出现,完成sql注入
实验错误
找不到用户
原因:新建的数据库内没有创建表和用户
创建表users,里面有两列username和password
查看表格和内部结构
向表内插入用户
查看表内用户数据
创建用户成功
成功报错