某cms的sql注入漏洞分析
字数 1731 2025-08-06 12:20:59

ThinkPHP 3.2.3框架下SQL注入漏洞分析与挖掘指南

一、ThinkPHP框架基础

1.1 MVC架构与请求流程

ThinkPHP采用MVC架构,运行流程如下:

  1. 用户请求发送到控制器(Controller)
  2. 控制器分析请求并调用相应模型(Model)
  3. 模型操作数据库并返回数据给控制器
  4. 控制器将数据传递给视图(View)
  5. 视图呈现数据给用户

1.2 控制器机制

  • 控制器是一个类,操作是控制器类的公共方法
  • 命名规范:
    • 控制器类名:驼峰命名法+Controller(如ApiuserController)
    • 控制器文件名:类名+.class.php(如ApiuserController.class.php)
  • 请求处理过程:
    1. 通过getController和getAction定义CONTROLLER_NAME和ACTION_NAME
    2. 获取当前操作名
    3. 创建控制器实例
    4. 通过ReflectionMethod获取对应方法
    5. 执行应用程序

二、典型SQL注入漏洞分析

2.1 直接拼接SQL注入(ApiuserController.class.php)

漏洞位置:group_info方法
漏洞原因

  • order_id参数通过GET请求直接传入
  • 未进行任何过滤直接拼接进SQL语句
  • 缺少token参数校验

漏洞复现

http://127.0.0.1/index.php?s=/Apiuser/group_info&order_id=1 and updatexml(1,concat(0x7e,database(),0x7e),1)

2.2 字符串条件注入(VipcardController.class.php)

漏洞位置:get_vipgoods_list方法
漏洞原因

  • order_id通过GET请求传入并直接拼接到WHERE语句
  • 使用字符串条件时,$this->options['where']的键是_string
  • 不会进入if判断语句
  • _parseType方法不会对字符串类型进行字段数据类型检查

特殊注意

  • 非array传入的参数会被添加括号
  • 无法闭合时可尝试添加括号

2.3 数组条件注入(ApiuserController.class.php)

漏洞位置:set_default_address方法
漏洞原理

  1. 跟进where和save方法
  2. 在_parseOptions方法中:
    • $val是数组,is_scalar判断为非标量
    • 不会进入_parseType方法进行类型检测
  3. 在parseWhereItem函数中:
    • $exp取数组第一个值bind
    • 拼接$whereStr形成SQL语句但保留:0
  4. 在execute中:
    • :0被替换为外部传入字符串
    • 通过strtr()函数替换

漏洞复现

http://127.0.0.1/index.php?s=Apiuser/set_default_address&id[0]=bind&id[1]=0 and (updatexml(1,concat(0x7e,user(),0x7e),1))

三、ThinkPHP 3.2.3 SQL注入挖掘思路

3.1 使用QUERY方法的原生SQL查询

特征代码

$gid = $_GPC['gid'];
$sql = "select xxx from xxx where gid='$id';"
$result = M()->query($sql);

挖掘方法

  • 正则搜索:M\query$.+?$
  • 检查传入参数是否可控且未过滤

3.2 使用字符串作为查询条件

特征代码

$gid = $_GPC['gid'];
$resultt = M('xxx')->where( "pid = {$gid}" )->select();

挖掘方法

  • 正则搜索:M\where$((?!array).)*$
  • 查找非数组传参的where条件
  • 检查参数是否可控

3.3 使用数组作为查询条件

特征代码

$gid = $_GPC['gid'];
$resultt = M('xxx')->where( array('gid' => $gid) )->save();

注意事项

  • 数组传参会进入if判断
  • 对传入值类型进行判断(int类型会转换)
  • 字符型参数会进行关键字符转义

特殊利用方式

  1. bind注入

    • 适用于update操作
    • 正则搜索:M\where\save$.+?$
  2. exp注入

    • 条件:必须通过全局数组传参(非I()函数)
    • I()函数会调用think_filter()过滤exp
    • 在此CMS中无法使用(所有参数通过I()函数传参)

四、防御建议

  1. 对所有用户输入进行严格过滤和转义
  2. 使用框架提供的参数绑定机制
  3. 避免直接拼接SQL语句
  4. 对关键操作添加权限验证
  5. 使用I()函数获取输入参数(但注意其局限性)
  6. 对数组条件中的键值进行严格检查

五、总结

ThinkPHP 3.2.3框架下SQL注入漏洞主要源于:

  1. 直接拼接用户输入到SQL语句
  2. 字符串条件未充分过滤
  3. 数组条件处理中的特殊逻辑缺陷
  4. 缺少必要的权限验证

审计时应重点关注:

  • 直接SQL拼接(query方法)
  • 字符串条件(where方法)
  • 数组条件中的特殊键值(bind、exp等)
  • 未授权访问的控制器方法
ThinkPHP 3.2.3框架下SQL注入漏洞分析与挖掘指南 一、ThinkPHP框架基础 1.1 MVC架构与请求流程 ThinkPHP采用MVC架构,运行流程如下: 用户请求发送到控制器(Controller) 控制器分析请求并调用相应模型(Model) 模型操作数据库并返回数据给控制器 控制器将数据传递给视图(View) 视图呈现数据给用户 1.2 控制器机制 控制器是一个类,操作是控制器类的公共方法 命名规范: 控制器类名:驼峰命名法+Controller(如ApiuserController) 控制器文件名:类名+.class.php(如ApiuserController.class.php) 请求处理过程: 通过getController和getAction定义CONTROLLER_ NAME和ACTION_ NAME 获取当前操作名 创建控制器实例 通过ReflectionMethod获取对应方法 执行应用程序 二、典型SQL注入漏洞分析 2.1 直接拼接SQL注入(ApiuserController.class.php) 漏洞位置 :group_ info方法 漏洞原因 : order_ id参数通过GET请求直接传入 未进行任何过滤直接拼接进SQL语句 缺少token参数校验 漏洞复现 : 2.2 字符串条件注入(VipcardController.class.php) 漏洞位置 :get_ vipgoods_ list方法 漏洞原因 : order_ id通过GET请求传入并直接拼接到WHERE语句 使用字符串条件时,$this->options[ 'where']的键是_ string 不会进入if判断语句 _ parseType方法不会对字符串类型进行字段数据类型检查 特殊注意 : 非array传入的参数会被添加括号 无法闭合时可尝试添加括号 2.3 数组条件注入(ApiuserController.class.php) 漏洞位置 :set_ default_ address方法 漏洞原理 : 跟进where和save方法 在_ parseOptions方法中: $val是数组,is_ scalar判断为非标量 不会进入_ parseType方法进行类型检测 在parseWhereItem函数中: $exp取数组第一个值bind 拼接$whereStr形成SQL语句但保留:0 在execute中: :0被替换为外部传入字符串 通过strtr()函数替换 漏洞复现 : 三、ThinkPHP 3.2.3 SQL注入挖掘思路 3.1 使用QUERY方法的原生SQL查询 特征代码 : 挖掘方法 : 正则搜索: M\query\(.+?\) 检查传入参数是否可控且未过滤 3.2 使用字符串作为查询条件 特征代码 : 挖掘方法 : 正则搜索: M\where\(((?!array).)*\) 查找非数组传参的where条件 检查参数是否可控 3.3 使用数组作为查询条件 特征代码 : 注意事项 : 数组传参会进入if判断 对传入值类型进行判断(int类型会转换) 字符型参数会进行关键字符转义 特殊利用方式 : bind注入 : 适用于update操作 正则搜索: M\where\save\(.+?\) exp注入 : 条件:必须通过全局数组传参(非I()函数) I()函数会调用think_ filter()过滤exp 在此CMS中无法使用(所有参数通过I()函数传参) 四、防御建议 对所有用户输入进行严格过滤和转义 使用框架提供的参数绑定机制 避免直接拼接SQL语句 对关键操作添加权限验证 使用I()函数获取输入参数(但注意其局限性) 对数组条件中的键值进行严格检查 五、总结 ThinkPHP 3.2.3框架下SQL注入漏洞主要源于: 直接拼接用户输入到SQL语句 字符串条件未充分过滤 数组条件处理中的特殊逻辑缺陷 缺少必要的权限验证 审计时应重点关注: 直接SQL拼接(query方法) 字符串条件(where方法) 数组条件中的特殊键值(bind、exp等) 未授权访问的控制器方法