ext校验是ThinkPHP上传验证五层防线中不可跳过的起点,仅比对文件名后缀且不读取内容,必须全小写无点逗号分隔,漏配则整个validate链失效。

因为只验证扩展名本身不安全,但它是五层校验中不可跳过的起点——不设白名单,连基础过滤都没有,后续所有校验都失去意义。
ext规则只校验文件名后缀,完全不读文件内容
ThinkPHP 的 validate(['ext' => ['jpg', 'png']]) 仅提取 $_FILES['file']['name'] 中的点号后部分(如 shell.php.jpg 提取为 jpg),然后比对是否在白名单里。它不会打开文件、不读字节、不调用 finfo_open()。
- 攻击者把
webshell.php改名为avatar.jpg就能绕过这一层 - 规则里写
'JPG'或'.jpg'都会失败,必须全小写、无点、逗号分隔:'jpg,png,gif' - 空格也会破坏提取,
report .pdf的扩展名会被识别为'pdf'前带空格,校验失败
不配 ext 就等于没启动 validate() 校验链
ThinkPHP 6+ 默认不自动触发任何上传验证。如果你只写了 size 或 type,但漏掉 ext,整个 validate() 调用可能静默跳过——尤其当用错方法时:validate() 是模型方法,对文件无效;必须用 rule() 或 validateRule() 绑定到 thinkFile 实例。
- 表单缺
enctype="multipart/form-data",request()->file()返回 null,后续所有验证都不执行 - 没写
ext规则,哪怕写了type,TP 也可能因逻辑短路不进入 MIME 校验分支 -
ext是唯一能快速拦截明显非法后缀(如.exe、.php)的低成本手段,不该省
ext 和 type 必须分开配,不能混用
ThinkPHP 对 ext 和 type 的处理是互斥的:如果规则里同时存在 ext 和 type,框架优先走 ext 路径,直接忽略 type ——这不是 bug,是设计行为。
立即学习“PHP免费学习笔记(深入)”;
- 想用真实 MIME 校验,必须删掉
ext,只留type,并配合'mime' => false关闭对客户端$_FILES['file']['type']的信任 - 更稳妥的做法是两套都配,但分两次调用:
$file->validate(['ext' => [...]])过第一关,再手动用finfo_file()做第二关 -
jpeg和jpg在 TP 里被视为不同扩展名,白名单里得都写上
真正危险的不是「为什么必须验证扩展名」,而是以为验证了扩展名就安全了——它只是门禁卡,不是安检仪。后面四层(真实 MIME、重命名、非 Web 存储、服务器禁执行)缺一不可,而 ext 是你唯一能靠配置就立刻生效的防线。
文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/xinjizixun/124104.html