ThinkPHP 5.0.16未修复input过滤失效问题,反而因参数解析逻辑缺陷导致数组型输入(如username[0]=exp)绕过/s等类型修饰符校验,引发SQL注入;官方在5.0.24+和5.1.40+中通过递归过滤修复,推荐升级至5.0.25或6.x LTS。

ThinkPHP 5.0.16 并不修复 input 过滤失效问题,反而因引入新的参数解析逻辑,导致部分场景下 input() 的类型过滤被绕过——尤其是当用户传入数组型参数(如 username[0]=exp&username[1]=UPPER(1))时,input('username/s') 仍可能放行恶意表达式,最终在 parseData() 中拼入 SQL,触发注入。
这个现象不是配置错误,而是 5.0.16 版本中 input() 方法对嵌套数组的类型校验未递归执行,仅作用于顶层键值,底层数组元素逃逸了 /s /d 等修饰符约束。
核心修复方向只有两个:升级或加固
立即升级到安全版本
5.0.16 本身存在缺陷,官方后续在 5.0.24+ 和 5.1.40+ 中修复了 `input()` 对数组值的递归过滤逻辑: - 升级至 5.0.25 或更高(推荐 5.0.24 起已稳定修复多处注入链) - 或直接迁移到 ThinkPHP 6.x LTS(长期支持,`input()` 默认启用深度白名单校验)
使用 Composer 升级命令:
composer update topthink/framework:^5.0.25
升级后需验证:手动构造 `?username[0]=exp&username[1]=UPPER(1)` 请求,确认 `input('username/s')` 返回空或抛出异常,而非原样透传。
无法升级时的手动加固方法
若受限于兼容性必须停留在 5.0.16,需在业务层补全过滤逻辑:
- 所有调用
input()获取数据后,立即做二次校验:- 对疑似字段(如 username、email、order、sort)检查是否为数组且含 `exp` 结构:
is_array($val) && isset($val[0]) && $val[0] === 'exp' - 对字符串值执行关键词拦截:
preg_match('/\b(select|union|update|delete|drop|load_file|into\s+outfile)\b/i', $val) - 批量插入前,用
array_filter($data, function($k) { return in_array($k, ['name','email','status']); }, ARRAY_FILTER_USE_KEY)强制白名单
- 对疑似字段(如 username、email、order、sort)检查是否为数组且含 `exp` 结构:
禁用高危参数接收模式
在 config/app.php 中关闭不安全特性:
- 设
'var_array' => false(禁用a修饰符,阻止自动解析name[]=xxx) - 清空
'var_method' => ''(防止_method=__construct变量覆盖) - 关闭调试:
'app_debug' => false(避免报错泄露 SQL 回显)
关键位置加白名单校验
在控制器入口或公共中间件中,对所有 POST/GET 数据做统一预检:
foreach (input() as $key => $val) {
if (is_array($val)) {
foreach ($val as $subval) {
if (is_string($subval) && preg_match('/^[\x20-\x7E]*$/', $subval) === 0) {
throw new Exception('Invalid input character');
}
}
}
}
重点拦截 `\x00-\x08\x0b\x0c\x0e-\x1f\x7f` 等控制字符及 SQL 关键字。
不复杂但容易忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











