ThinkPHP 5.1.x SQL注入漏洞分析

2018 年 10 月 1 日 FreeBuf

一、背景介绍

ThinkPHP 是一个快速、简单的基于 MVC 和面向对象的轻量级 PHP 开发框架,遵循 Apache2 开源协议发布。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重开发体验和易用性,为 WEB 应用和 API 开发提供了强有力的支持。

在近期,ThinkPHP 框架被曝出存在SQL注入漏洞。由于SQL注入漏洞的危害性以及该框架应用十分广泛。 对此,天融信阿尔法实验室以静态和动态两种方式对该漏洞进行了深入分析。

1.1 漏洞描述

在ThinkPHP5.1.23之前的版本中存在SQL注入漏洞,该漏洞是由于程序在处理order by 后的参数时,未正确过滤处理数组的key值所造成。如果该参数用户可控,且当传递的数据为数组时,会导致漏洞的产生。

1.2 受影响的系统版本

ThinkPHP < 5.1.23

1.3 漏洞编号

CVE-2018-16385

二、环境搭建

1.下载安装thinkphp5.1.x

对于thinkphp5.1.x完整版,目前官方没有直接下载的链接。Github上只是放出核心版。该版本需要以Composer或Git方式进行安装。

这里以Composer安装方式说明。

在 Linux 和 Mac OS X 中可以运行如下命令:

curl -sS https://getcomposer.org/installer | phpmv composer.phar/usr/local/bin/composer

在 Windows 中,你需要下载并运行 Composer-Setup.exe 。

安装好之后,切换路径到WEB目录下运行:

composercreate-project topthink/think=5.1.1 tp5.1 --prefer-dist

然后会生成一个名为tp5.1的文件夹。到此think5.1.1下载成功。

2.然后在浏览器中访问  

如果出现该页面,则证明安装成功。

3.Demo示例

编写Demo文件,并将文件命名为Test.php,然后放在/tp5.1/application/index/controller/目录下。

4.数据库

与Demo文件匹配,需要创建一个user表,然后设一个字段(id)。

三、漏洞细节

在/thinkphp/library/think/db/Builder.php parseOrder()的函数中:

通过Demo传入order参数内容,当传入的$order是一个数组时,foreach函数将$order数组分为key和value形式。

根据漏洞修复补丁,知道漏洞发生在parseOrderField()函数中。

当$val为数组时,会进入parseOrderField()函数。

跟踪parseOrderField()函数

getOptions()函数是获取了当前要查询的参数,getFieldsBind()函数是获取数据表绑定信息,foreach循环是对$val值进行了处理,这里其实不是重点,就提一下。$val值是什么不用管,因为注入点在$key上,而$val 拼接在$key后面,可以在构造$key加#注释掉$val。

重点是parseKey()函数,跟踪parseKey()函数。

这里对传入的$key进行多重判断以及处理。

1. is_numeric判断,如果是数字,则返回,不是的话继续向下执行。

2. 判断$key是否属于Expression类。

3. strpos($key, ‘->’) && false ===strpos($key, ‘(‘) 。

4. (‘*’ != $key && ($strict ||!preg_match(‘/[,\'\"\*\(\)`.\s]/’, $key)))。

因为$key是我们的sql注入语句,所以1.2.3肯定不满足,而4满足。

所以此时的$key会在左右两侧加个 ` 号。

$table不存在,不会对$key修改,所以加 ` 号后会返回$key,然后和$val以及field字符串进行拼接,再然后return赋值给array变量,紧接着,array与order by 字符串进行拼接形成order by查询语句,最终系统调用query()函数进行数据库查询,触发漏洞。

着重说明一下,这里由于field函数,漏洞利用有两个关键点:

首先解释下field()函数:MySQL中的field()函数作用是对SQL中查询结果集进行指定顺序排序。一般与order by 一起使用。

关键点1:

field()函数必须指定大于等于两个字段才可以正常运行,否则就会报错。

当表中只有一个字段时,我们可以随意指定一个数字或字符串的参数。

关键点2:

当field中的参数不是字符串或数字时,指定的参数必须是正确的表字段,否则程序就会报错。这里由于程序会在第一个字段中加 `` 限制 ,所以必须指定正确的字段名称。第二个字段没有限制,可以指定字符串或数字。

所以,我们要利用该漏洞,第一我们至少需要知道表中的一个字段名称,第二向field()函数中中传入两个字段。第二个字段不需要知道字段名,用数字或字符串绕过即可。

Payload构造

根据以上分析,构造payload需要满足以下条件:

1.传入的$order需要是一个数组。

2.$val 必须也是数组。

3.至少知道数据库表中的一个字段名称,并且传入两个参数。

4.闭合 ` 。

最终Payload构造如下:

http://127.0.0.1/tp5.1/public/index/test/index?order[id`,111)|updatexml(1,concat(0x3a,user()),1)%23][]=1

http://127.0.0.1/tp5.1/public/index/test/index?order[id`,'aaa')| updatexml(1,concat(0x3a,user()),1)%23][]=1

四、动态调试分析

有时候单单静态分析,很难知道某些函数做了些什么,而对于程序运行过程,也很难理解透彻。而利用动态分析,一步一步debug,就很容易理解清楚。

这里我们利用上面构造的payload进行debug。

首先下断点:

$val是个数组,进入parseOrderField()函数。F7下一步(我这里用的是phpstorm,F7是单步调试的意思)。

foreach循环后,可以看到只是处理了$val,并没有涉及$key(我们的关注点在$key)。$val 的值是在$key的基础上加了个:data__前缀,后面加了个0。

继续F7,进入了parseKey()函数。

到这里,看到$key满足if条件,然后两边加了个 ` 号。

最后返回的$key。其实就是两边加了个 ` 号 。

最后,返回给array变量的值为file字符串val的拼接。

继续F7,看看接下来程序怎么走。

进行了limit分析,union分析等多个分析处理,最终来到了removeoption()函数。

可以看到这里的$sql,已经可以触发注入漏洞。

然后经过了中间的几个过程,对比上图,并没有改变sql语句内容。最后sql语句,进入query()函数执行了SQL语句,成功触发注入漏洞。

五、修复建议

官方补丁

目前官方已经更新补丁,请受影响的用户尽快升级到ThinkPHP5.1.24版本。

手工修复

根据官方给出的方案进行代码修改。

https://github.com/top-think/framework/commit/f0f9fc71b8b3716bd2abdf9518bcdf1897bb776

*本文作者:alphalab,转载请注明来自FreeBuf.COM


登录查看更多
1

相关内容

中文 WEB 应用开发框架
【2020新书】实战R语言4,323页pdf
专知会员服务
100+阅读 · 2020年7月1日
还在修改博士论文?这份《博士论文写作技巧》为你指南
【经典书】Python数据数据分析第二版,541页pdf
专知会员服务
192+阅读 · 2020年3月12日
算法与数据结构Python,369页pdf
专知会员服务
161+阅读 · 2020年3月4日
缺失数据统计分析,第三版,462页pdf
专知会员服务
108+阅读 · 2020年2月28日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
漏洞预警丨Xstream远程代码执行漏洞
FreeBuf
4+阅读 · 2019年7月25日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
16+阅读 · 2019年5月13日
Pupy – 全平台远程控制工具
黑白之道
43+阅读 · 2019年4月26日
Linux挖矿病毒的清除与分析
FreeBuf
14+阅读 · 2019年4月15日
百度开源项目OpenRASP快速上手指南
黑客技术与网络安全
5+阅读 · 2019年2月12日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
Neo4j 和图数据库起步
Linux中国
8+阅读 · 2017年12月20日
Meta-Learning with Implicit Gradients
Arxiv
13+阅读 · 2019年9月10日
Arxiv
8+阅读 · 2019年5月20日
Learning Implicit Fields for Generative Shape Modeling
Arxiv
10+阅读 · 2018年12月6日
Bidirectional Attention for SQL Generation
Arxiv
4+阅读 · 2018年6月21日
Arxiv
5+阅读 · 2018年3月6日
Arxiv
9+阅读 · 2018年1月30日
VIP会员
相关VIP内容
相关资讯
漏洞预警丨Xstream远程代码执行漏洞
FreeBuf
4+阅读 · 2019年7月25日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
16+阅读 · 2019年5月13日
Pupy – 全平台远程控制工具
黑白之道
43+阅读 · 2019年4月26日
Linux挖矿病毒的清除与分析
FreeBuf
14+阅读 · 2019年4月15日
百度开源项目OpenRASP快速上手指南
黑客技术与网络安全
5+阅读 · 2019年2月12日
去哪儿网开源DNS管理系统OpenDnsdb
运维帮
21+阅读 · 2019年1月22日
Neo4j 和图数据库起步
Linux中国
8+阅读 · 2017年12月20日
相关论文
Meta-Learning with Implicit Gradients
Arxiv
13+阅读 · 2019年9月10日
Arxiv
8+阅读 · 2019年5月20日
Learning Implicit Fields for Generative Shape Modeling
Arxiv
10+阅读 · 2018年12月6日
Bidirectional Attention for SQL Generation
Arxiv
4+阅读 · 2018年6月21日
Arxiv
5+阅读 · 2018年3月6日
Arxiv
9+阅读 · 2018年1月30日
Top
微信扫码咨询专知VIP会员