前言

ThinkPHP是一个免费开源的,快速、简单的面向对象的轻量级PHP开发框架,是为了敏捷WEB应用开发和简化企 业应用开发而诞生的。ThinkPHP从诞生的12年间一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码 的同时,也注重易用性。目前ThinkPHP框架是国内使用量最大的框架之一,国内用户量众多。
3月26号ThinkPHP更新到5.0.16。5.0.16之前的版本存在一个sql注入漏洞,在 insert 和 update 方法中,传入的参数可控,且无严格过滤,最终导致本次SQL注入漏洞发生。
ThinkPHP-5.0.16-1.png

环境搭建

thinkphp官网下载5.0.14版本下载:http://www.thinkphp.cn/down/1107.html
创建数据库:

create database thinkphp;
create table user(id int auto_increment primary key,username varchar(50),password varchar(50));
insert into user(id,username,password) values(1,"test","thinkphp");

配置连接数据库文件:\thinkphp\application\database.php
ThinkPHP-5.0.16-2.png

打开thinkphp的调试和trace模式:\thinkphp\application\config.php
ThinkPHP-5.0.16-3.png

写一个update功能的demo,内容如下:\thinkphp\application\index\controller\Index.php
ThinkPHP-5.0.16-4.png

变量获取

$name = input("get.name/a");
input()为TP框架的助手函数,get.name/a 表示获取get传入的name变量,并将其强制转换为数组类型

数据库查询

Db::table("users")->where(["id"=>1])->insert(["username"=>$name]);
TP框架采用的是PDO方式对数据库进行查询

访问payload触发漏洞:

http://172.16.110.166/thinkphp_5.0.14_full/public/index.php?password[0]=inc&password[1]=updatexml(2,concat(0x7e,user()),0)&password[2]=1
![ThinkPHP-5.0.16-5.png][6]

漏洞分析

在index.php处下断点,进行动态调试跟踪。
ThinkPHP-5.0.16-6.png

F7跟进后来到helper.php,这里是数据库连接操作,这里的调用非常深,不用进入,F8直接跳过
ThinkPHP-5.0.16-7.png

来到query.php,这里是分析的关键
ThinkPHP-5.0.16-8.png

接着往下看,来到Builder.php,这里是生成UPDATE的SQL语句,F7跟进去看
ThinkPHP-5.0.16-9.png

这里有两个操作,parseTable和parseData。F7跟进后发现在parseData进行了sql语句拼接。
ThinkPHP-5.0.16-10.png

跟进后发现,当$val是数组,根据$val[

发现parseKey并没有对$key做任何过滤处理,返回任然是updatexml(2,concat(0x7e,user()),0)
floatval($val[2])返回1,即是传入的password[2]=1
最后回到parseData进行下一步操作,返回sql语句
ThinkPHP-5.0.16-13.png

接着往下走语句被执行,造成SQL注入
ThinkPHP-5.0.16-14.png

修复

官方修复https://github.com/top-think/framework/commit/363fd4d90312f2cfa427535b7ea01a097ca8db1b

ThinkPHP-5.0.16-15.png

在dec和inc操作之前对$val[1]的值做了检查

参考

1.ThinkPHP框架 5.0.x sql注入漏洞分析
2.ThinkPHP框架 < 5.0.16 sql注入漏洞分析
3.ThinkPHP5.0.x框架SQL注⼊