ThinkPHP 5.1.x SQL注入漏洞分析
字数 1307 2025-08-18 11:37:37
ThinkPHP 5.1.x SQL注入漏洞分析与防护指南
漏洞概述
ThinkPHP 5.1.23之前的版本存在SQL注入漏洞(CVE-2018-16385),该漏洞源于程序在处理order by参数时,未正确过滤处理数组的key值。当攻击者能够控制该参数且传递的数据为数组时,可导致SQL注入攻击。
受影响版本
- ThinkPHP < 5.1.23
漏洞原理分析
漏洞位置
漏洞主要存在于/thinkphp/library/think/db/Builder.php文件的parseOrder()函数中。
漏洞触发流程
-
参数处理流程:
- 当传入的
$order参数为数组时,foreach函数将其分为key和value形式处理 - 当
$val为数组时,会进入parseOrderField()函数
- 当传入的
-
关键函数分析:
parseKey()函数对传入的$key进行多重判断:is_numeric判断是否为数字- 判断
$key是否属于Expression类 strpos($key,false ===strpos($key,key && ($strict ||!preg_match(s]/', $key))
- 攻击者的SQL注入语句会满足第4个条件,导致
$key被加上反引号后直接返回
-
拼接过程:
- 处理后的
$key与$val及field字符串拼接 - 最终与
order by形成完整的SQL查询语句 - 系统调用
query()函数执行查询,触发漏洞
- 处理后的
利用关键点
-
field()函数要求:
- 必须指定≥2个字段才能正常运行
- 当表中只有一个字段时,可随意指定数字或字符串参数
- 第一个参数必须是正确的表字段(会被反引号包裹)
- 第二个参数可以是任意数字或字符串
-
利用条件:
- 传入的
$order必须是数组 $val也必须是数组- 至少知道数据库表中的一个字段名称
- 能够闭合反引号
- 传入的
漏洞复现
环境搭建
-
使用Composer安装ThinkPHP 5.1.1:
composer create-project topthink/think=5.1.1 tp5.1 --prefer-dist -
创建Demo文件
Test.php,放置在/tp5.1/application/index/controller/目录下 -
创建匹配的数据库表(如
user表,至少包含id字段)
攻击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
漏洞修复方案
官方修复
升级到ThinkPHP 5.1.24或更高版本
手动修复
参考官方补丁进行代码修改:
https://github.com/top-think/framework/commit/f0f9fc71b8b3716bd2abdf9518bcdf1897bb776
防护建议
- 对所有用户输入进行严格的过滤和验证
- 使用参数化查询或预处理语句
- 遵循最小权限原则,限制数据库用户权限
- 在生产环境中关闭错误信息显示
- 定期更新框架和组件到最新版本
总结
该SQL注入漏洞源于ThinkPHP对order by参数中数组key值处理不当,攻击者通过精心构造的数组参数可绕过过滤机制,实现SQL注入攻击。开发人员应及时更新框架版本,并对所有用户输入保持高度警惕,实施严格的安全验证措施。