thinkphp5框架SQL注入分析:parseWhereItem

前言

漏洞位置在Mysql类的parseWhereItem方法,select注入

漏洞影响版本: ThinkPHP5全版本

环境搭建

下载源码

1
composer create-project --prefer-dist topthink/think=5.0.10 tp501

创建数据库,在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');
$result = db('users')->where('username','exp',$username)->select();
return 'select success';
}
}

漏洞复现

payload

1
?username=) union select updatexml(1,concat(0x7,user(),0x7e),1)--+

Wwhk9K.png

漏洞分析

先在控制器这里打断点

WwhPtx.png

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

调用parseWhereExp,然后返回$this

WwhCA1.png

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

进入parseWhereExp,主要是对输入的查询表达式进行分析,然后赋值给$this->options[‘where’]

Wwhih6.png

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

接下来进入select。

  1. 首先调用parseExpress,功能是取出$this->options的值赋值给$options数组。
  2. 然后把$options数组作为参数传递给think\db\Builder类的select方法,生成sql语句。
  3. 最后调用query方法执行sql语句

WwhA1O.png

$options数组

WwhEcD.png

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

进入think\db\Builder类的select方法,用str_replace替换模板生成sql语句。这里详细看一下parseWhere方法

WwhVje.png

经过一系列parseXXX方法后生成的sql语句

WwhmBd.png

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

由于$options[‘soft_delete’]为空,所以这里只执行了buildWhere。

WwhenH.png

经过buildWhere后生成的whereStr

WwhnHA.png

最后返回的结果就是$whereStr前面拼接上WHERE

1
WHERE ( `username` ) union select updatexml(1,concat(0x7,user(),0x7e),1)--  )

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

进入buildWhere,看看sql语句具体是怎么拼接的

首先遍历$where也就是$options[‘where’],然后把里面的值作为参数传入parseWhereItem

WwhKAI.png

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

在parseWhereItem中,直接拼接了sql语句

WwhMNt.png

只要$exp等于EXP就会直接拼接sql语句

WwhQ4P.png

总结

Wwh19f.png