前言
之前审计的是5.0.15的parseData函数漏洞导致的SQL注入。这次审的是5.1.17的parseArrayData函数漏洞导致的SQL注入。影响版本:
5.1.6<=ThinkPHP<=5.1.7 (非最新的 5.1.8 版本也可利用)。
composer create-project topthink/think=5.1.17 thinkphp5.1.17
然后改一下composer.json,再composer update就好了。

然后设置一下database.php:

index控制器里面写update:
public function index()
{
$username = request()->get('username');//以数组的格式获取$_GET中的username变量,然后作为参数传入insert()
db('users')->where(['id' => 15])->update(['username' => $username]);
return 'Update success';
}
分析
这次是update注入。还是老套路,先把/a给去掉,正常的走一遍update,看看thinkphp是怎么处理的。
?username=111
先跟进一下where()方法:

$param先获得一个数组作为元素,即['id'=>15],然后再把它弹出去,没什么用。
跟进parseWhereExp()方法,在这里return:

主要就是对$this->options['where']进行了处理:

再跟进update方法:

parseOptions主要就是影响options,产生很多无用的键,增加了'table'=>'users'这个键。然后把这个数组给$this->options['data']:

再跟进$this->connection->update()方法,在这里产生SQL语句:

再跟进一下这个$this->builder->update()方法,看一下SQL语句的产生:
/**
* 生成update SQL
* @access public
* @param Query $query 查询对象
* @return string
*/
public function update(Query $query)
{
$options = $query->getOptions();
$table = $this->parseTable($query, $options['table']);
$data = $this->parseData($query, $options['data']);
if (empty($data)) {
return '';
}
foreach ($data as $key => $val) {
$set[] = $key . ' = ' . $val;
}
'UPDATE %TABLE% SET %SET%%JOIN%%WHERE%%ORDER%%LIMIT% %LOCK%%COMMENT%';
return str_replace(
['%TABLE%', '%SET%', '%JOIN%', '%WHERE%', '%ORDER%', '%LIMIT%', '%LOCK%', '%COMMENT%'],
[
$this->parseTable($query, $options['table']),
implode(' , ', $set),
$this->parseJoin($query, $options['join']),
$this->

最低0.47元/天 解锁文章
1576





