← 返回题目列表

文件上传漏洞是什么?如何防范?

高频 中等 第 13 / 27 题 更新于 2026/07/28
文件上传漏洞WebShell网络安全白名单

简化版

文件上传漏洞是指服务器没有严格校验上传的文件,导致攻击者上传恶意可执行文件(如 WebShell 脚本),再通过 URL 访问它、让服务器执行,从而拿到服务器控制权。危害极大(等于攻击者在你服务器上能执行代码)。防范核心:白名单校验文件类型(扩展名 + MIME + 文件头)+ 重命名 + 存到不可执行目录/独立域名

详细版

攻击原理

  1. 网站有上传功能(头像、附件等);
  2. 攻击者上传一个服务端脚本文件(如 shell.phpshell.jsp),里面是一句能执行命令的代码(WebShell);
  3. 如果服务器把它存在了 Web 可访问且能执行脚本的目录,攻击者就能通过 http://site.com/upload/shell.php?cmd=... 访问它;
  4. 服务器执行了这个脚本 → 攻击者获得了在服务器上执行任意命令的能力(读文件、连数据库、进一步渗透)。

常见绕过手法(针对不严的校验):

  • 改扩展名/大小写shell.PHPshell.php5shell.phtml
  • 双扩展名shell.jpg.php
  • 截断shell.php%00.jpg(老漏洞);
  • 改 MIME 类型:抓包把 Content-Type 改成 image/jpeg 骗过只检查 MIME 的校验;
  • 图片马:把脚本藏在图片文件里(文件头是图片,尾部是脚本),配合文件包含漏洞触发。

防范手段

  • 白名单校验扩展名:只允许明确的安全类型(jpg/png/pdf),拒绝一切脚本类型;
  • 多重校验:扩展名 + MIME 类型 + 文件头魔数(真正判断文件类型)一起验,别只信扩展名或 MIME;
  • 重命名文件:用随机名 + 强制安全扩展名保存,别用用户原始文件名;
  • 存储隔离:把上传文件存到不能执行脚本的目录,或独立的文件服务器/对象存储/独立域名——即使传了脚本也执行不了;
  • 限制大小、加杀毒扫描

完整版教学

一、为什么文件上传漏洞危害「封顶」

在各种 Web 漏洞里,文件上传漏洞(成功传上 WebShell 时)危害往往是最高级别的——因为它直接给了攻击者在你服务器上执行任意代码的能力。

  • SQL 注入拿到的是数据库数据;XSS 影响的是用户浏览器;
  • 而 WebShell 意味着攻击者在你的服务器上「有了一个终端」——能读任意文件、连内网、装后门、横向渗透,几乎等于服务器被完全控制。

所以文件上传是攻防双方都极其重视的点。它的可怕之处在于:上传本身很常见(头像、附件谁都有),但一个校验疏漏就可能被打穿到服务器沦陷。

二、核心防线:白名单 + 多重校验

防御文件上传,最关键的是判断「这到底是什么文件」,且用白名单

为什么用白名单:黑名单(禁止 .php/.jsp)总有漏网之鱼——.php5.phtml.pht、大小写、解析配置差异等绕过太多。白名单只允许明确安全的类型(图片就只允许 jpg/png/gif),其余全拒,绕过空间小得多。

为什么要多重校验:单一校验都能被绕过:

  • 只查扩展名 → 改扩展名绕过;
  • 只查 MIME 类型Content-Type)→ 抓包改 MIME 绕过(这个是客户端传的,可伪造);
  • 所以要扩展名 + MIME + 文件头魔数一起验。文件头魔数(如 PNG 开头是 89 50 4E 47、JPG 是 FF D8)是文件内容的真实特征,最难伪造,是判断真实类型的可靠依据。

三、核心防线:存储隔离(让脚本无法执行)

即使校验被绕过、脚本传上来了,只要它无法被执行,危害就大大降低。所以存储隔离是极其有效的一道防线:

  • 存到不解析脚本的目录:配置 Web 服务器让上传目录不执行任何脚本(如 Nginx 里该目录只作静态文件下载,不 pass 给 PHP-FPM);
  • 存到独立域名/独立服务器:把用户上传的文件放到专门的静态资源域名或对象存储(OSS/S3),那里根本没有脚本执行环境,传上去的 .php 只是个静态文件,访问它只会被下载、不会执行;
  • 重命名:保存时用随机文件名 + 服务端强制的安全扩展名,攻击者也就无法通过已知路径访问自己传的马。

「静态资源和动态脚本分离」不仅是性能优化(详见「CDN 原理」那道题),也是重要的安全实践。

四、其他加固与「图片马」

  • 图片马 + 文件包含:攻击者把脚本藏进图片(FF D8 ... <?php ...?>),单靠文件头校验(是图片)过了,但如果站点有文件包含漏洞include 这张图,脚本就被执行了。所以文件上传要和文件包含漏洞一起防(别用用户可控的路径去 include 文件)。
  • 限制文件大小:防止大文件耗尽磁盘/带宽(也是一种 DoS);
  • 杀毒/内容扫描:对上传内容做恶意特征扫描;
  • 去除文件的可执行权限:存储时不给执行权限。

五、纵深防御思路

文件上传防御是「多道防线叠加」,任何一道都不能单独指望:

  1. 前端限制(体验,非安全)→ 后端才是真防护;
  2. 白名单 + 多重校验(扩展名 + MIME + 魔数)→ 拦住大部分恶意文件;
  3. 重命名 + 存储隔离(不可执行目录/独立域名)→ 即使传上来也执行不了;
  4. 配合防文件包含、限大小、扫描 → 兜底。

核心心法:既要「尽量不让恶意文件传上来」(校验),又要「就算传上来也让它跑不起来」(隔离)。

六、常见误区

  • ❌ 只校验扩展名或 MIME——都能绕过,要加文件头魔数多重校验,且用白名单。
  • ❌ 把上传文件存在能执行脚本的 Web 目录——应存到不可执行目录/独立域名,让脚本跑不起来。
  • ❌ 用用户原始文件名保存——要重命名(随机名 + 安全扩展名),防路径可预测和覆盖。
  • ❌ 只防上传不防文件包含——图片马配合文件包含仍能执行,两者要一起防。

六、常见误区与追问

考点正确口径
风险点上传 WebShell、恶意脚本、超大文件、伪装类型
校验扩展名、MIME、文件头、内容扫描、大小限制
隔离对象存储、随机文件名、非执行目录、权限最小化
allowlist: .jpg .png .pdf
check magic bytes, not only Content-Type
store outside web root
serve as attachment or static object
disable script execution

文件上传防护的关键是白名单、内容校验和存储隔离,不能只信文件名后缀。

  • 误区:校验后缀名就够了。 攻击者可用双后缀、大小写、解析差异或伪造 MIME 绕过。
  • 误区:图片上传一定安全。 图片可能包含恶意载荷、解析漏洞或超大压缩炸弹。
  • 误区:上传目录只要不公开链接就安全。 一旦路径可猜或被泄露,若目录可执行脚本就可能变成远程代码执行。
  • 追问:为什么要重命名文件? 随机文件名能避免路径猜测、覆盖已有文件和利用特殊文件名触发解析问题。
  • 追问:为什么推荐对象存储? 对象存储天然与应用执行环境隔离,降低上传文件被当代码执行的风险。
  • 追问:下载时如何降低风险? 设置正确 Content-Type、Content-Disposition,并避免浏览器把未知文件当 HTML 执行。

七、加强记忆

文件上传漏洞是服务器没严格校验上传文件,导致攻击者传上 WebShell(可执行脚本)并访问执行,拿到服务器控制权(危害封顶)。防御两条主线:一是校验(白名单扩展名 + MIME + 文件头魔数多重验,防传上来),二是隔离(重命名 + 存到不可执行目录/独立域名,让传上来的脚本也执行不了)。再配合防文件包含、限大小、扫描。核心:既拦上传,又让恶意文件跑不起来。