1、什么是文件上传漏洞?
文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器并执行。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。这种攻击方式是最为直接和有效的,部分文件上传漏洞的利用技术门槛非常的低,对于攻击者来说很容易实施。

2、webshell介绍
大多数的文件上传漏洞被利用后,攻击者都会留下webshell以方便后续进入系统。攻击者在受影响系统放置或者插入webshell后,可通过该webshell更轻松,更隐蔽的在服务器中为所欲为。
这里需要特别说明的是上传漏洞的利用经常会使用webshell,而webshell的植入远不止文件上传这一种方式。(例如还可以通过其他命令执行,数据库插入等方式植入webshell)

3、实战案例分享
去年在某企业红队评估项目中,我仅用 30 分钟就通过一个文件上传功能拿下了核心服务器权限 —— 当时我上传了一个伪装成 “产品图片” 的 PHP 木马,后台不仅没拦截,还直接执行了脚本。事后复盘时发现,这个看似简单的漏洞,竟藏着网站开发者最容易犯的 5 个错误。
文件上传漏洞是网络安全领域最 “致命” 的漏洞之一,它不像 SQL 注入需要复杂的语句拼接,也不像 XSS 依赖用户交互,一旦存在未修复的文件上传漏洞,攻击者往往能直接获取服务器控制权(getshell),甚至横向渗透整个内网。这篇文章,我会结合6个实战案例,从漏洞定义、利用技巧、防御方案三个维度,带大家彻底搞懂文件上传漏洞 —— 无论你是刚入门的安全新人,还是负责开发的程序员,都能找到可落地的知识点。
先搞懂:什么是文件上传漏洞?为什么它能直接 getshell?
在讲利用方法前,必须先明确一个核心问题:文件上传漏洞到底是怎么产生的?很多人以为 “允许用户上传文件 = 有漏洞”,其实不然 —— 漏洞的根源在于 “文件上传后被服务器当作脚本执行”。
3.1 漏洞本质:开发者的 “双重疏忽”
文件上传功能本身是合法需求(比如用户头像、商品图片、文档附件),但当开发者同时犯了两个错误时,漏洞就会产生:
- 疏忽 1:未过滤恶意文件
没有对上传文件的类型、后缀名、内容进行严格校验,导致攻击者能上传 PHP、ASP、JSP 等可执行脚本(俗称 “木马文件”)。 - 疏忽 2:上传目录可执行脚本
把上传文件存放在 Web 可访问目录(比如/upload、/images),且该目录允许服务器执行脚本(比如 Apache 配置了AllowOverride All,Nginx 开启了fastcgi_pass解析)。
举个我遇到的真实案例:某电商网站的 “商品图片上传” 功能,仅在前端用 JS 判断了文件后缀是否为.jpg/.png,后端完全没校验。我禁用浏览器 JS 后,直接上传了名为shell.php的木马文件,然后访问http://目标域名/upload/shell.php,服务器直接执行了脚本 —— 此时我已经能通过蚁剑连接这个 “webshell”,像操作自己电脑一样控制服务器。

3.2 漏洞危害:从 “单个文件” 到 “整个内网”
文件上传漏洞的危害程度,取决于服务器的权限和内网架构,我总结了从低到高的 4 级危害:
| 危害级别 | 具体影响 | 实战案例 |
|---|---|---|
| 1 级 | 读取服务器敏感文件 | 上传readfile.php,读取/etc/passwd(Linux)或C:\Windows\system32\config\SAM(Windows) |
| 2 级 | 获取服务器权限 | 上传cmd.php,执行系统命令(如whoami、ipconfig),添加管理员账号 |
| 3 级 | 横向渗透内网 | 通过已控制的服务器,扫描内网其他机器(如用 Nmap 扫 192.168.1.0/24 段),利用永恒之蓝等漏洞扩散 |
| 4 级 | 数据泄露 / 勒索 | 找到数据库配置文件(如config.php),导出用户数据;或植入勒索病毒,加密服务器文件 |
印象最深的一次是 2023 年测试某政务系统,通过文件上传漏洞 getshell 后,发现服务器在内网中具有 “域管理员” 权限 —— 最终我不仅拿到了整个政务网的用户数据,还能远程登录所有办公电脑。这也印证了:文件上传漏洞往往是攻击者突破内网的 “第一扇门”。
4、实战拆解:6 种常见过滤机制与对应的绕过技巧(附案例)
开发者为了防御文件上传漏洞,会设置各种过滤手段,但多数过滤都存在 “可乘之机”。我梳理了实战中最常见的 6 种过滤机制,每种都附上我亲身测试过的绕过方法和案例,新手也能跟着复现。
4.1 前端 JS 过滤:最容易绕过的 “纸老虎”
原理:在前端页面用 JavaScript 判断文件后缀名,比如只允许.jpg/.png/.gif,如果选择其他后缀(如.php),会弹出 “文件类型不允许” 的提示。
特点:只在客户端校验,未在服务器端二次校验,是最基础的防御手段。
我的绕过案例:某企业官网的 “联系我们” 模块,允许上传 “附件”,前端 JS 过滤了非图片后缀。我用两种方法轻松绕过:
- 方法 1:禁用浏览器 JS
在 Chrome 中按F12打开开发者工具,按Ctrl+Shift+P输入 “Disable JavaScript”,禁用后直接上传shell.php,后端毫无拦截;

如果 JavaScript 禁用成功,则会在浏览器地址栏最右侧出现如下图红框中的标识,将鼠标放置在此标识上则会显示 “已拦截此网页上的 JavaScript” 。

- 方法 2:先改后缀再抓包改回
把shell.php改名为test.jpg,

通过前端校验后,用 BurpSuite 抓包,BP成功抓取数据包

在请求包中将filename="test.jpg"改为filename="test.php",后端接收的是.php文件。

脚本文件成功上传

防御漏洞点:开发者误以为 “前端过滤 = 安全”,忽视了后端二次校验。
4.2 后端后缀名黑名单过滤:找 “漏网之鱼”
原理:在服务器端维护一个 “黑名单”(比如禁止.php/.asp/.jsp),如果上传文件的后缀在黑名单中,就拒绝上传。
特点:比前端过滤更有效,但黑名单无法覆盖所有 “危险后缀”,存在绕过空间。
我的绕过案例:某 CMS 系统的文件上传功能,后端黑名单禁止了.php,但我通过 “特殊后缀” 绕过:
- 利用服务器解析特性:Apache 服务器默认支持
.php5/.phtml/.php3等后缀,这些后缀不在黑名单中,我上传shell.php5,访问时服务器会当作 PHP 脚本执行; - 利用 Windows 文件特性:Windows 系统会忽略文件名末尾的
.和空格,比如上传shell.php.(末尾加.),Windows 会自动去掉.,变成shell.php,而黑名单没过滤.php.; - 利用大小写绕过:如果后端黑名单只过滤小写
.php,上传shell.PHP(大写),部分不区分大小写的服务器会解析为 PHP 脚本。
关键知识点:不同服务器的解析规则不同,这是绕过黑名单的核心 —— 比如 Nginx 默认不解析.php5,但 Apache 会;IIS 服务器会把shell.asp;.jpg解析为 ASP 脚本(分号后的内容被忽略)。
4.3 MIME 类型过滤:抓包改 “文件身份”
原理:MIME 类型是文件的 “身份标识”(比如图片文件是image/jpeg,PHP 文件是application/octet-stream),后端通过判断Content-Type字段的值来过滤文件类型。
特点:依赖 HTTP 请求头中的 MIME 类型,而非文件本身内容,容易被篡改。
我的绕过案例:某教育平台的 “作业提交” 功能,后端只允许Content-Type: image/jpeg的文件。我上传shell.php时,用 Burp 抓包修改 MIME 类型:
- 正常上传
shell.php,请求包中Content-Type: application/octet-stream,后端拒绝; - 将
Content-Type改为image/jpeg,其他内容不变,后端认为是图片文件,允许上传; - 上传后访问
http://目标/upload/shell.php,服务器解析为 PHP 脚本,成功 getshell。
防御漏洞点:开发者只校验 MIME 类型,不校验文件实际内容,导致 “文件身份” 和 “实际内容” 不匹配。
4.4 文件内容检测:用 “图片马” 突破
原理:后端不仅校验后缀和 MIME 类型,还会检测文件内容(比如判断是否包含图片的文件头FF D8 FF(JPG)、89 50 4E 47(PNG)),如果是脚本文件,会拒绝上传。
特点:比前三种过滤更严格,但可通过 “图片马”(图片 + 脚本的混合文件)绕过。
我的绕过案例:某金融 APP 的 “头像上传” 功能,后端会检测文件头。我用 “图片马” 成功绕过:
-
制作图片马:在 Windows 命令行中执行
copy /b 1.jpg+shell.php 2.jpg,将 PHP 脚本shell.php(内容<?php @eval($_POST['cmd']);?>)附加到图片1.jpg后,生成shell.jpg—— 此时文件前半部分是正常图片,后半部分是 PHP 脚本;


-
上传
2.jpg:后端检测到文件头是FF D8 FF,判定为图片,允许上传; -
触发解析:找到服务器的 “解析漏洞”—— 比如该服务器配置了 “如果文件包含.php 后缀就解析”,我通过访问
http://目标/upload/2.jpg.php(不存在该文件),服务器会尝试解析shell.jpg中的 PHP 脚本;或者利用 Apache 的AddHandler application/x-httpd-php .jpg配置,让服务器将.jpg文件当作 PHP 解析。
关键注意点:图片马需要配合 “服务器解析漏洞” 才能执行,否则上传后只是一张普通图片,无法作为脚本运行。
4.5 白名单过滤:看似无解,实则有 “配置漏洞”
原理:后端维护 “白名单”(只允许.jpg/.png/.gif),只有后缀在白名单中的文件才能上传,这是比黑名单更安全的防御手段。
特点:正常情况下无法绕过,但如果服务器存在 “路径穿越漏洞” 或 “解析漏洞”,仍有机会。
我的绕过案例:某企业 OA 系统的文件上传功能,白名单只允许.png。我利用 “路径穿越 + 解析漏洞” 绕过:
- 路径穿越:上传时用 Burp 抓包,将
filename="shell.png"改为filename="../upload/shell.php.png"—— 如果后端未过滤../,会将文件存到上级目录的upload文件夹,文件名变为shell.php.png; - 解析漏洞:该服务器使用 IIS 6.0,存在 “分号解析漏洞”——IIS 会忽略分号后的内容,
shell.php.png会被解析为shell.php; - 访问执行:访问
http://目标/upload/shell.php.png,IIS 解析为 PHP 脚本,成功 getshell。
防御漏洞点:白名单本身没问题,但开发者未过滤../等特殊字符,导致路径穿越;同时服务器版本过旧,存在解析漏洞。
4.6 文件名随机化:绕过后缀,但绕不开 “路径泄露”
原理:后端会将上传文件的文件名改为随机字符串(比如a3f2d1.png),即使上传的是.php文件,也会被改为.png,从根本上避免脚本执行。
特点:较难绕过,但如果能泄露 “随机文件名的存储路径”,配合解析漏洞仍有机会。
我的绕过案例:某电商平台的 “商品图片上传” 功能,文件名会随机生成。我通过 “路径泄露” 实现利用:
- 泄露路径:在商品详情页,右键查看图片地址,发现路径是
http://目标/upload/202405/a3f2d1.png—— 能看到上传目录/upload/202405/和随机文件名a3f2d1.png; - 上传图片马:制作包含 PHP 脚本的
2.png(图片马),上传后得到随机文件名b4e5f6.png; - 利用解析漏洞:该服务器的
/upload目录下有个index.php,其中包含include $_GET['file'];—— 我访问http://目标/upload/index.php?file=202405/b4e5f6.png,index.php会包含b4e5f6.png中的 PHP 脚本,从而执行恶意代码。
核心逻辑:文件名随机化解决了 “后缀问题”,但没解决 “文件内容被包含执行” 的问题 —— 只要有其他脚本包含该图片马,就能触发漏洞。
5、防御方案:开发者必看的 6 个 “防漏” 要点
作为安全从业者,我不仅要懂利用,更要懂防御。结合实战中遇到的漏洞,我给开发者总结了 6 个可落地的防御方案,能覆盖 90% 以上的文件上传漏洞。
5.1 后端白名单校验:拒绝 “黑名单思维”
-
做法:只允许业务必需的文件类型(如头像上传只允许
.jpg/.png/.gif),用白名单判断后缀名,且校验时要 " 取最后一个.后的后缀 "(避免shell.php.png被当作.png); -
代码示例(PHP):
$allowExt = ['jpg', 'png', 'gif']; // 白名单 $ext = strtolower(end(explode('.', $_FILES['file']['name']))); // 取最后一个后缀 if (!in_array($ext, $allowExt)) { die("不允许的文件类型"); }
5.2 文件内容深度校验:不止校验文件头
-
做法:用专业库校验文件内容(如 PHP 的
getimagesize()判断是否为图片,或用fileinfo扩展获取真实文件类型),避免图片马绕过; -
代码示例(PHP):
$finfo = new Finfo(FILEINFO_MIME_TYPE); $mime = $finfo->file($_FILES['file']['tmp_name']); // 获取真实MIME类型 $allowMime = ['image/jpeg', 'image/png', 'image/gif']; if (!in_array($mime, $allowMime)) { die("文件内容不合法"); }
5.3 文件名随机化 + 存储目录分离
- 做法:将上传文件的文件名改为随机字符串(如
uniqid().'.'.$ext),避免攻击者猜测路径;同时将上传目录设置为 “不可执行脚本”(如 Apache 配置php_flag engine off,禁止解析 PHP); - 关键:即使攻击者上传了恶意文件,也无法执行,只能作为静态文件下载。
5.4 过滤特殊字符:防止路径穿越
-
做法:对上传文件名中的
../、\、;等特殊字符进行过滤或转义,避免路径穿越漏洞; -
代码示例(PHP):
$filename = str_replace(['../', '\\', ';'], '', $_FILES['file']['name']); // 过滤特殊字符
5.5 升级服务器与框架:修复解析漏洞
- 做法:及时升级 Apache、Nginx、IIS 等服务器到最新版本,关闭不必要的解析配置(如 Apache 的
AddHandler application/x-httpd-php .jpg);使用成熟的 Web 框架(如 Spring Boot、Laravel),避免自定义上传逻辑。
5.6 日志审计与监控:及时发现攻击
- 做法:记录所有文件上传操作(包括上传者 IP、文件名、时间、路径),定期审计日志;对异常上传行为(如短时间内多次上传相同类型文件)进行告警,及时发现攻击者的测试行为。
6、总结:文件上传漏洞的 “攻防本质”
回顾我测试过的 100 + 包含文件上传漏洞的网站,发现一个规律:80% 的漏洞不是因为防御技术不够,而是因为开发者的 “侥幸心理”—— 比如觉得 “前端过滤够了”、“黑名单能覆盖所有危险后缀”、“没人会注意这个小功能”。
对于安全从业者来说,文件上传漏洞的利用核心是 “寻找防御链的薄弱环节”—— 前端过滤不行就抓包改,后缀过滤不行就用特殊后缀,内容过滤不行就做图片马,白名单过滤不行就找解析漏洞。但请务必记住:所有测试都要在合法授权的前提下进行,SRC 平台、企业授权项目、合法靶场(如 DVWA、Upload-Lab)是实战的正确场景,切勿触碰法律红线。
对于开发者来说,防御文件上传漏洞的核心是 “放弃侥幸,构建多重防御链”—— 白名单校验、内容检测、文件名随机化、目录不可执行,这四重防御组合起来,能抵御几乎所有已知的利用手段。毕竟,在网络安全领域," 多一层防御,就少一分风险 "。
最后送大家一句话:文件上传漏洞是 “攻防双方思维的较量”—— 攻击者在找 “开发者的疏忽”,而开发者要做的,就是让 “疏忽” 无处可藏。
网络安全学习资源分享:
给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
因篇幅有限,仅展示部分资料,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,请看下方扫描即可前往获取




被折叠的 条评论
为什么被折叠?



