thinkphp5框架SQL注入分析:parseWhereItem+filterValue

前言

漏洞概要:

  • 漏洞存在于 Mysql 类的 parseWhereItem 方法中,数据未经过过滤就拼接进sql语句。
  • Request 类的 filterValue 方法漏过滤 NOT LIKE 关键字,

漏洞影响版本: ThinkPHP=5.0.10

环境搭建

控制器

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');
$result = db('users')->where(['username' => $username])->select();
var_dump($result);
}
}

漏洞复现

payload

1
http://localhost/tp501/public/?username[0]=not like&username[1][0]=%%&username[1][1]=233&username[2]=) union select 1,user()%23

Wgi7Bq.png

漏洞分析

Input

我们传递的参数会先进入Request类的input方法,然后经过强制类型转换和filterValue方法的处理

1.get

$_GET数组被赋值给$this->get,然后进入input

WgiO4U.png

2.input

array_walk_recursive 会对$data数组中的每个成员递归地应用filterValue函数,

WgijCF.png

3.filterValue

调用filterExp对数组中的每一个值进行过滤

Wgiv34.png

4.filterExp

可以看到没有过滤NOT LIKE

1
2
3
4
5
6
7
8
public function filterExp(&$value)
{
// 过滤查询特殊字符
if (is_string($value) && preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i', $value)) {
$value .= ' ';
}
// TODO 其他安全过滤
}

parseWhereItem

1.控制器

Wgi5cj.png

2.where

调用parseWhere把username数组赋值给$this->options['where']['AND']

WgixgJ.png

3.parseWhereExp

主要是赋值和拼接数组的具体过程

WgiIjs.png

4.select

  • select构建sql语句
  • query执行构建好的sql语句

WgiTun.png

5.select

构造sql语句,进入parseWhere

WgiHH0.png

6.parseWhere

if条件不满足,只执行了buildWhere

WgiLNT.png

WgiqEV.png

7.buildWhere

调用parseWhereItem

WgFpuR.png

8.parseWhereItem

简化了下,只放了实际执行的代码

  1. parseKey给username拼接上了反引号
  2. $exp把小写的not like转成大写
  3. $value等于$val[1]
  4. 在这里parseValue的功能就是给传入参数拼接上单引号
  5. 逻辑操作符$logic来源于可控的$val[2],然后被拼接进sql语句,造成了sql注入

WgF9D1.png

9.query执行sql语句

Wgizv9.png


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!