ThinkPHP 5.1.29 本身无 where 条件注入漏洞,该问题源于开发者未校验用户输入导致的 SQL 注入,属业务层缺陷;真实高危漏洞是远程代码执行(RCE),影响 5.0.22/5.1.29 等版本。

ThinkPHP 5.1.29 本身不直接存在 where 条件注入漏洞,你提到的“where 条件注入”实际是开发人员在使用框架时未安全处理用户输入导致的 SQL 注入问题,属于业务层编码缺陷,而非框架核心漏洞。官方从未将此类问题列为 CVE 或安全公告中的“ThinkPHP 漏洞”。真正被广泛确认、可复现、无需登录即可触发的是 远程代码执行(RCE)漏洞(如 /index.php?s=index/\think\app/invokefunction),影响 5.0.22 / 5.1.29 等版本。
明确 where 注入的成因
该问题通常出现在控制器中类似以下写法:
-
$ids = input('ids/a');直接接收数组型参数(如ids[]=1&ids[]=2) -
$model->where('id', 'in', $ids)->select();将未经校验的$ids传入in查询 - 若攻击者传入
ids[0]=1) AND (SELECT SLEEP(5))-- -,且框架未做类型强转或白名单过滤,可能绕过基础检测,拼接出恶意 SQL
修复 where in 类注入的关键措施
ThinkPHP 5.1.x 提供了安全机制,但需主动启用:
-
强制类型转换:对
in参数显式转为整型数组$ids = input('ids/a', [], 'intval');或array_map('intval', input('ids/a')); -
白名单校验:限制 ID 范围或长度,例如只允许 1~99999 的正整数
$ids = array_filter(input('ids/a'), function($v) { return is_numeric($v) && $v > 0 && $v -
改用闭包查询:避免直接传数组给
in,改由框架参数绑定保障安全$model->where(function ($query) use ($ids) { foreach ($ids as $id) $query->whereOr('id', $id); })->select(); -
禁用危险的动态表达式:避免在
where中拼接用户输入的字段名或操作符,如where(input('field'), input('op'), input('val'))—— 这类写法必须废弃
不要依赖“框架自动过滤”
ThinkPHP 的 input() 默认不做过滤,where(..., 'in', ...) 也不会自动对数组元素做 intval 或 escape。即使开启 default_filter 配置,它仅作用于字符串值,对数组无效。很多线上系统出问题,正是因为开发者误以为 “用了 ThinkPHP 就安全了”。
立即学习“PHP免费学习笔记(深入)”;
配套加固建议
- 升级到 5.1.30+ 或 5.1.40+(官方已修复 RCE,且增强参数解析逻辑)
- 在数据库配置中启用
PDO::ATTR_EMULATE_PREPARES => false,强制使用真实预处理 - 对所有涉及
in、not in、between、like的查询,统一加日志审计和长度/类型断言 - 测试时用
echo $model->getLastSql();查看最终 SQL,确认无非法字符或嵌套子查询



















