thinkPHP5.x SQL注入

发布于 2021-08-06  65 次阅读


漏洞信息

漏洞编号:CVE-2018-16385

影响版本:ThinkPHP框架<5.0.16

漏洞类型:SQL注入漏洞

ThinkPHP基础知识

ThinkPHP目录结构:

├─application 应用目录(可设置)

│ ├─common 公共模块目录(可更改)

│ ├─index 模块目录(可更改)

│ │ ├─config.php 模块配置文件

│ │ ├─common.php 模块函数文件

│ │ ├─controller 控制器目录

│ │ ├─model 模型目录

│ │ ├─view 视图目录

│ │ └─ ... 更多类库目录

│ ├─command.php 命令行工具配置文件

│ ├─common.php 应用公共(函数)文件

│ ├─config.php 应用(公共)配置文件

│ ├─database.php 数据库配置文件

│ ├─tags.php 应用行为扩展定义文件

│ └─route.php 路由配置文件

├─extend 扩展类库目录(可定义)

├─public WEB 部署目录(对外访问目录)

│ ├─static 静态资源存放目录(css,js,image)

│ ├─index.php 应用入口文件

│ ├─router.php 快速测试文件

│ └─.htaccess 用于 apache 的重写

├─runtime 应用的运行时目录(可写,可设置)

├─vendor 第三方类库目录(Composer)

├─thinkphp 框架系统目录

│ ├─lang 语言包目录

│ ├─library 框架核心类库目录

│ │ ├─think Think 类库包目录

│ │ └─traits 系统 Traits 目录

│ ├─tpl 系统模板目录

│ ├─.htaccess 用于 apache 的重写

│ ├─.travis.yml CI 定义文件

│ ├─base.php 基础定义文件

│ ├─composer.json composer 定义文件

│ ├─console.php 控制台入口文件

│ ├─convention.php 惯例配置文件

│ ├─helper.php 助手函数文件(可选)

│ ├─LICENSE.txt 授权说明文件

│ ├─phpunit.xml 单元测试配置文件

│ ├─README.md README 文件

│ └─start.php 框架引导文件

├─build.php 自动生成定义文件(参考)

├─composer.json composer 定义文件

├─LICENSE.txt 授权说明文件

├─README.md README 文件

├─think 命令行入口文件

ThinkPHP助手函数:

img
img

漏洞环境搭建

PHPstudy:Apache2.4.39 + MySQL5.7.26 + PHP7.3.4nts

PHPstrom + Xdebug

  1. 数据库创建create database thinkphp;
    use thinkphp;
    create table users(
    id int primary key auto_increment,
    username varchar(50) not null
    );
  2. application/index/controller/Index.php 文件代码设置<?php
    namespace app\index\controller;

    class Index
    {
    public function index()
    {
    $username = request()->get('username/a');
    db('users')->insert(['username' => $username]);
    return 'Update success';
    }

    }
  1. \thinkphp\application\database.php数据库配置填写配置文件中,自己数据库的相关信息,即可。
  2. \thinkphp\application\config.php调试模式配置// 应用调试模式
    'app_debug' => true,
    // 应用Trace
    'app_trace' => true,
  3. 打入payload:http://localhost/thinkphp5/public/index.php/index/index?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1
image-20210321185741748

出现如图所示的页面,及漏洞环境配置成功

漏洞分析

image-20210321192322468

在关键传参处设置断点,使用动态调试进行跟踪。

我们知道 insert 方法存在漏洞,那就查看 insert 方法的具体实现。该方法位于 thinkphp\library\think\db\Builder.php 文件中,我们可以看到在函数开头调用了 parseData 方法,并将 $data 作为参数传入

image-20210321193537595

我们跟进 parseData 方法,该方法也在 thinkphp\library\think\db\Builder.php 文件中。可以看到,在结尾处有个switch语句,而且进入该语句后,会跳到case ‘inc’的地方,这里关键就是看看 $this->parseKey 是否有对 $val[1] 变量进行过滤了,因为 $val[1] 变量就是我们payload中的updatexml(1,concat(0x7,user(),0x7e),1)

image-20210321193658930

继续跟进parseKey,发现没有任何过滤

image-20210321193934613

观察最开始的insert方法

image-20210321194047347

不难发现,我们的payload第一处传参username[0]=inc 是为了跳转到switch语句中的case ‘inc’,

然后username[1]注入我们完整的payload,利用报错信息携带出来,这里没有对我们的SQL语句进行过滤,最后的username[2]=1就是很简单的为了完整传递参数。

至此,ThinkPHP5的SQL注入漏洞复现完毕。