文件上传漏洞防御,后端校验文件头、后缀、MIME绕过防护

文件上传漏洞的核心风险

很多网站在处理用户上传时,只靠前端限制扩展名,攻击者抓包改一下文件名和 Content-Type 就能绕过,把 PHP、JSP 等可执行脚本传上服务器。
一旦上传目录能执行脚本,网站基本就沦陷了。
所以服务端必须做多层校验,文件头、后缀、MIME 三者缺一不可
本文用 PHP 示例演示后端如何实现,并给出验证和避坑方法。

准备条件

在动手前,准备好下面的环境:

  • 一台可测试的服务器或本机环境,PHP 5.3 以上即可
  • 一个简单的上传表单和一个上传处理接口
  • Burp Suite 或浏览器开发者工具,用来模拟恶意请求

后端校验文件头、后缀和 MIME 的代码实现

下面以 PHP 为例,给上传接口加入三层校验。
注意代码顺序:先查后缀,再识别文件头,最后比对 MIME。

第一层:校验文件后缀

只允许白名单内的后缀,例如图片的 jpg、jpeg、png、gif。

$allowed = ['jpg', 'jpeg', 'png', 'gif'];
$ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $allowed)) {
    die('文件后缀不允许');
}

第二层:校验文件头

文件头是文件开头的几个字节,能反映真实格式。
JPEG 以 FF D8 FF 开头,PNG 以 89 50 4E 47 开头。
攻击者把 PHP 文件改成 .jpg 时,文件头通常不会变。
用 PHP 读取临时文件的前几个字节并判断:

$handle = fopen($_FILES['file']['tmp_name'], 'rb');
$header = fread($handle, 4);
fclose($handle);
if (!preg_match('/^(FF D8 FF|89 50 4E 47|47 49 46 38)/', bin2hex($header))) {
    die('文件头不正确');
}

第三层:校验服务端识别的 MIME

不要使用 $_FILES['file']['type'],这个值来自客户端请求头,攻击者可以随意改成 image/jpeg
要用 finfo_file 读取真实 MIME 并和扩展名比对:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['file']['tmp_name']);
finfo_close($finfo);

$map = [
    'jpg' => 'image/jpeg',
    'jpeg' => 'image/jpeg',
    'png' => 'image/png',
    'gif' => 'image/gif'
];
if ($map[$ext] !== $mime) {
    die('MIME 类型不匹配');
}

绕过方式与避坑清单

攻击者常见的绕过方法包括:

  • .php.jpg.phtml 等复合后缀,绕过只检查末尾扩展名的逻辑
  • 在图片末尾追加脚本代码,配合文件包含漏洞执行
  • 修改请求里的 Content-Type 字段,绕过只校验 MIME 的代码
  • 老版本系统里使用 shell.php%00.jpg 空字节截断

避坑时记住这几条:

  • 文件后缀和真实 MIME 必须一一对应,防止“图片后缀 + 脚本内容”的组合
  • 上传目录关闭脚本执行权限,例如 Nginx 配置 location ~* \.(php)$ { deny all; }
  • 上传后文件名随机重命名,不用用户原始文件名,避免包含恶意字符串
  • 安全修复完成后,还要定期扫描历史上传文件,防止旧文件已被植入后门

验证防御是否有效

用 Burp Suite 抓包,把一段 PHP 代码保存为 test.jpg,同时将请求里的 Content-Type 改成 image/jpeg,然后上传。
如果接口返回「文件头不正确」或「MIME 类型不匹配」,说明校验生效。

也可以直接上传一个内容为 php phpinfo(); ?
>
的文件,改名为 .jpg,再访问上传路径,确认文件没有被当作 PHP 执行。
这样能同时验证后缀、文件头、MIME 和目录执行权限是否都起了作用。

常见疑问

为什么只校验后缀不够?
因为攻击者可以完全伪造后缀和请求头,文件内容才是真实身份。

检测文件头能完全防住图片马吗?
不能。图片马的文件头是正常的,需要配合上传目录禁止脚本执行、随机文件名和内容检测。

如果业务允许上传 PDF 或压缩包怎么办?
同样用 finfo_file 获取真实 MIME,维护一份更宽的白名单,并把文件放在独立存储目录,禁止执行脚本。

文件上传漏洞防御必须落在后端。只要把后缀白名单、
服务端文件头识别、
真实 MIME 比对三层校验都做到位,
再关闭上传目录的执行权限,
就能挡住绝大多数绕过攻击。
建议部署后按本文的验证方法多测几次,
确保上传接口是安全的。

分享到:
上一篇
系统账号暴力破解日志分析,auth.log定位爆破源IP
下一篇
代理转发真实IP处理错误,业务拿不到真实攻击IP无法封禁
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意