某cms的sql注入漏洞分析
字数 1731 2025-08-06 12:20:59
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参数校验
漏洞复现:
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方法
漏洞原理:
- 跟进where和save方法
- 在_parseOptions方法中:
- $val是数组,is_scalar判断为非标量
- 不会进入_parseType方法进行类型检测
- 在parseWhereItem函数中:
- $exp取数组第一个值bind
- 拼接$whereStr形成SQL语句但保留:0
- 在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类型会转换)
- 字符型参数会进行关键字符转义
特殊利用方式:
-
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等)
- 未授权访问的控制器方法