ThinkPHP 5.0.27本身无官方认定的上传后缀绕过漏洞,该问题源于开发者业务代码中未校验后缀或MIME、未重命名、未服务端内容校验及上传目录未禁执行等不规范实现。

ThinkPHP 5.0.27 本身不包含官方认定的“文件上传后缀绕过漏洞”。该版本(发布于2019年)的主要高危问题是未授权远程代码执行(RCE),典型如:
-
?s=index/\think\app/invokefunction调用call_user_func_array -
_method=__construct配合filter[]=system的参数覆盖型 RCE
而所谓“上传后缀绕过”,在 ThinkPHP 5.0.x 系列中并非框架原生功能缺陷,而是开发者在业务代码中错误使用上传接口时引发的安全问题。常见场景如下:
上传逻辑未校验后缀或 MIME 类型
例如:
$file = request()->file('image');
$file->move(ROOT_PATH . 'public' . DS . 'uploads');这段代码完全信任客户端传来的 $_FILES['image']['name'],攻击者可上传 shell.php.jpg 并配合 Apache 解析漏洞(如 .jpg 被误解析为 PHP),或利用 Nginx 配置不当(如 fastcgi_split_path_info 匹配错误)触发执行。
立即学习“PHP免费学习笔记(深入)”;
使用 validate(['ext'=>'jpg,png']) 但未启用严格校验
ThinkPHP 5.0 的 validate() 默认只检查扩展名后缀,不解析文件内容,且若开发者手动拼接文件名(如 $name = input('name') . '.jpg'),就可能绕过验证。
修复方式必须落在业务层,而非升级 TP5.0.27
因为该漏洞本质是开发不规范,不是框架补丁能一键修复的。需逐项落实:
-
强制白名单校验扩展名
不用in_array(pathinfo($file->getInfo('name'), PATHINFO_EXTENSION), ['jpg','png'])这类松散判断。改用:$ext = strtolower($file->getOriginalExtension()); if (!in_array($ext, ['jpg', 'jpeg', 'png', 'gif'], true)) { $this->error('不支持的文件类型'); } -
禁用危险扩展名写入可执行目录
上传目录(如public/uploads/)应配置 Web 服务器禁止执行 PHP:- Apache:
.htaccess中添加php_flag engine off或Deny from all - Nginx:在 location 块中加
deny all;或fastcgi_intercept_errors on;
- Apache:
-
重命名文件,剥离原始后缀
绝不保留用户可控的文件名:$newName = md5(uniqid() . mt_rand()) . '.' . $ext; $file->move(ROOT_PATH . 'public' . DS . 'uploads', $newName);
-
服务端二次校验文件头(Magic Number)
对图片类上传,读取前几个字节比对:$bin = file_get_contents($file->getRealPath(), false, null, 0, 4); $finfo = finfo_open(FILEINFO_BYTES); $type = finfo_buffer($finfo, $bin); finfo_close($finfo); if (stripos($type, 'jpeg') === false && stripos($type, 'png') === false) { $this->error('文件内容与扩展名不符'); }
ThinkPHP 官方从未为 5.0.27 单独发布“上传后缀绕过补丁”,因其不属于框架安全边界内的问题。真正有效的修复,是把上传逻辑从“信任输入”改为“白名单+重命名+服务端内容校验+Web 服务器防护”四层防御。



















