php文件类型校验漏洞本质是信任客户端伪造的扩展名或$_files['type'],安全校验必须基于服务端对文件原始内容的解析,需用fileinfo扩展获取真实mime、exif_imagetype等函数验证图片结构,并强制重命名、白名单匹配、执行隔离缺一不可。

PHP文件类型校验漏洞本质是“信了不该信的信息”——只靠客户端传来的扩展名或$_FILES['type']判断文件类型,而这两者都可被轻易伪造。真正安全的校验必须基于服务端对文件**原始内容**的解析,且需多层交叉验证。
用fileinfo扩展做MIME类型检测
PHP内置的fileinfo扩展能读取文件二进制头信息,识别真实类型,比$_FILES['type']可靠得多。务必启用该扩展(虚拟主机中多数已开启),并用finfo_open()检测:
- 先检查扩展是否可用:
if (!extension_loaded('fileinfo')) { die('fileinfo extension required'); } - 用
FILEINFO_MIME_TYPE获取真实MIME:$finfo = finfo_open(FILEINFO_MIME_TYPE); $realType = finfo_file($finfo, $_FILES['file']['tmp_name']); - 白名单严格匹配,如只允许
image/jpeg、image/png,不接受text/plain或空值
图片类文件加一层内容校验
仅靠MIME仍不够——攻击者可构造“图片马”,即在JPEG文件末尾追加PHP代码。此时需调用图像处理函数确认其可被正常解析:
- 对JPEG/PNG/GIF,使用
exif_imagetype():返回IMAGETYPE_JPEG等常量才视为有效 - 对PNG还可进一步用
getimagesize(),它会尝试解析结构,失败即说明非真图 - 若校验失败,直接
unlink($_FILES['file']['tmp_name'])清理临时文件,避免残留
拒绝一切依赖扩展名或前端输入的判断
以下做法必须全部弃用:
- 不信任
pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)——用户可上传shell.php.jpg - 不信任
$_FILES['file']['type']——浏览器发送的MIME由前端控制,可任意修改 - 不在JavaScript里做“仅允许.jpg/.png”限制——纯属掩耳盗铃,绕过毫无难度
- 不拼接用户原始文件名保存,如
'uploads/' . $_FILES['file']['name']
配合存储路径与权限做最终隔离
即使校验通过,也要防止文件被当作脚本执行:
- 上传目录绝不放在Web根目录下,例如存到
/home/user/uploads/而非/public_html/uploads/ - 若必须放Web可访问路径,则用
.htaccess(Apache)禁止执行:php_flag engine off或deny from all - Linux服务器上设置目录权限为
755,文件为644,确保无x位 - 上传后立即重命名,用
uniqid() . bin2hex(random_bytes(8))生成不可预测名称
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











