ThinkPHP 5.1.27 不存在官方确认的数组查询注入漏洞,它是修复了聚合函数字段名注入的稳定版本;常见问题多源于业务层误用或实际运行版本低于5.1.27。

ThinkPHP 5.1.27 并不存在官方确认的“数组查询注入漏洞”。当前(2026年10月)已知的 ThinkPHP 5.1 系列高危漏洞集中在两个方向:一是 5.1.25 及之前版本的聚合函数字段名注入(如 max()、count() 参数被用户控制),二是 5.1.x 全系存在的路由型 RCE 漏洞(CVE-2018-1002015,通过 s= 参数触发 \think\app::invokefunction)。5.1.27 实际是修复了聚合函数问题的稳定版本——它已包含对 parseKey 在聚合场景下的校验补丁。
先确认你是否真在用 5.1.27
很多项目显示为 5.1.27,实则因手动覆盖文件或 Composer 锁定不严,底层仍运行旧版核心。请执行以下验证:
- 查看
thinkphp/library/think/db/Builder.php中aggregate()方法,确认是否调用$this->parseKey($key, true)且该方法内部有白名单或正则过滤逻辑 - 运行
php think version或在代码中输出\think\App::VERSION,比对实际加载版本 - 检查
composer.lock中topthink/framework的 exact commit hash 是否匹配 5.1.27 发布记录
如果你确实在用 5.1.27,但仍有类似注入现象
大概率不是框架原生漏洞,而是业务层误用导致。重点关注以下三类常见误操作:
-
数组参数未过滤直接进 where:例如
$model->where(input('where', []))->select(),若用户传入where[username]=admin&where[password][exp]=1=1,可能绕过基础校验。应改用显式键名白名单:where(['username' => input('username')]) -
闭包查询中拼接用户输入:如
$model->where(function ($query) { $query->where('status', input('s')); }),若input('s')是"1=1 OR id IN (SELECT ...)"就会出问题。必须对每个字段值做类型强转或in_array()校验 -
自定义查询构造器滥用:自行扩展的
Builder子类若重写了parseWhereItem等方法,且未继承父类安全逻辑,也可能引入风险
通用加固建议(无论版本)
不依赖框架补丁,从编码习惯上切断风险链:
立即学习“PHP免费学习笔记(深入)”;
- 所有
where()、order()、field()等接受字段名的参数,只允许固定字符串或白名单枚举,禁止任何用户输入直接进入 - 禁用调试模式:
'app_debug' => false,防止 SQL 报错泄露结构 - 数据库账户最小权限原则:应用账号仅授予
SELECT, INSERT, UPDATE, DELETE,禁用FILE、LOAD DATA等高危权限 - 关键接口增加 WAF 规则,拦截含
UNION SELECT、EXTRACTVALUE、updatexml、反引号+括号组合(如`id`))等特征的请求



















