thinkphp本身无上传漏洞,而是开发者校验逻辑松散导致绕过;不可信的$_files['type']易被伪造,须用finfo_file()校验mime;取后缀、路径拼接、session id命名等均需严格过滤与标准化,并禁用上传目录脚本执行。

ThinkPHP本身没有“上传漏洞”,但大量基于它的项目因校验逻辑松散、路径拼接随意、MIME信任前端,实际跑起来就是个可上传WebShell的入口。
为什么$_FILES['type']不能当文件类型用
这个字段完全由浏览器控制,攻击者只要改个Content-Type: text/plain就能绕过所有仅依赖它的白名单检查。真正该用的是finfo_file()读取文件头——比如finfo_file(finfo_open(FILEINFO_MIME_TYPE), $tmp_file)返回image/jpeg才可信。
- 常见错误:用
pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)取后缀,结果shell.PHP、a.php::$DATA、1.jpg.全过 - 更糟的是:只调用
getimagesize()就认为是图片,但图片马(在JPEG末尾追加<?php phpinfo();?>)照样能过 - 正确做法:先
finfo校验MIME,再用imagecreatefromxxx()重绘并保存,剥离所有元数据和嵌入代码
input('save_path')拼接路径时怎么防目录穿越
ThinkAdmin里曾出现strpos($filename, '..') !== false这种弱过滤,结果/../、%2e%2e%2f、甚至....//都能绕过。关键不是“拦住几个字符串”,而是“让路径绝对化且限定根目录”。
- 必须用
realpath()或dirname(__DIR__) . DS . $user_path做标准化,再用str_starts_with()确认最终路径没跳出预设根目录(如UPLOAD_PATH) - 避免直接拼接
$_GET或input()来的路径参数,尤其别用DS . input('dir')这种写法 - Apache环境下还要额外注意:
.htaccess可能被上传覆盖,导致AddHandler application/x-httpd-php .jpg生效,让图片变PHP
ThinkPHP 6.0的PHPSESSID任意文件操作怎么触发
这不是上传功能本身的漏洞,而是Session ID被当作文件名一部分使用,且未过滤非法字符。当session_id()可控(比如通过Set-Cookie头注入),攻击者就能把PHPSESSID=../../../../public/shell.php带进来,导致session_write_close()把恶意内容写进Web目录。
- 影响版本:ThinkPHP 6.0.0–6.0.1,修复方式是强制
ctype_alnum($id)校验Session ID - 复现关键点:中间件需开启
session,且业务代码里有Session::set()或session('key', $val)写入行为 - 防御重点:永远不要把任何用户可控输入(包括Cookie、Header、Session ID)直接用于文件路径或
file_put_contents()的文件名参数
最常被忽略的一点:即使你做了所有校验,如果上传目录本身在Web根下、且服务器配置允许执行PHP,那一个漏掉的.user.ini或.htaccess就能让所有防护失效。上传目录必须禁用脚本执行,这是最后一道物理防线。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











