文件上传漏洞绕过与防护

一、前言

文件上传是 Web 渗透中非常常见的高危入口。如果后端对上传文件校验不严格,攻击者可能上传 WebShell、HTML 钓鱼页面、恶意脚本或可被解析执行的文件。

在红队和渗透测试中,文件上传漏洞的价值在于:它可能从一个普通 Web 功能变成服务器命令执行入口。

本文总结文件上传漏洞的判断、绕过思路和防护建议,仅用于靶场和授权环境。

二、常见上传场景

常见功能点:

  • 头像上传
  • 附件上传
  • 富文本图片上传
  • 简历上传
  • Excel/Word 导入
  • 插件上传
  • 压缩包上传
  • 后台模板上传

常见接口参数:

1
2
3
4
5
6
7
file
upload
image
avatar
attachment
document
plugin

看到这些功能时,可以重点关注文件类型限制、保存路径、访问路径和是否能被解析执行。

三、漏洞判断流程

1. 上传普通文件

先上传正常图片:

1
test.jpg

观察:

  • 是否上传成功。
  • 返回文件路径。
  • 文件是否可访问。
  • 文件名是否被重命名。
  • 保存目录是否可执行脚本。

2. 测试后缀限制

尝试上传:

1
2
3
4
5
test.php
test.phtml
test.php5
test.jsp
test.asp

如果直接上传成功,并且能访问执行,说明风险非常高。

3. 测试内容校验

有些系统只检查文件后缀,不检查内容;有些系统检查 MIME 或文件头。

可以构造图片马:

1
2
GIF89a
<?php phpinfo(); ?>

如果服务器将该文件作为 PHP 解析,就可能执行其中的 PHP 代码。

四、常见绕过方式

1. 前端校验绕过

如果只在前端 JavaScript 校验文件类型,可以直接用 Burp Suite 修改请求包。

例如前端只允许:

1
2
3
jpg
png
gif

可以先选择 1.jpg,拦截请求后改成:

1
1.php

如果后端没有再次校验,就能绕过。

2. MIME 类型绕过

后端可能只判断:

1
Content-Type: image/jpeg

上传 PHP 文件时修改请求头:

1
Content-Type: image/jpeg

但真实防护不能只依赖 MIME,因为该字段可被客户端控制。

3. 黑名单后缀绕过

如果只禁止 .php,可以尝试:

1
2
3
4
5
.phtml
.php3
.php5
.phar
.shtml

具体是否解析取决于服务器配置。

4. 双后缀绕过

1
2
shell.jpg.php
shell.php.jpg

有些系统只检查最后一个后缀,有些解析器可能按中间后缀处理,需要结合实际环境判断。

5. 大小写绕过

1
2
shell.PHP
shell.PhP

如果后端判断时没有统一转小写,可能被绕过。

6. 文件头绕过

部分系统检查图片文件头,可以在文件开头添加图片标识:

1
GIF89a

然后追加脚本内容。

7. 压缩包上传风险

如果系统支持 zip 上传并自动解压,要关注:

  • 解压路径是否可控。
  • 是否存在 Zip Slip。
  • 是否能解压出脚本文件。
  • 是否会覆盖已有文件。

Zip Slip 风险示例路径:

1
../../../../var/www/html/shell.php

五、解析漏洞与配置问题

有时上传本身没有问题,真正的问题在 Web 服务器解析配置。

1. 上传目录可执行

上传目录应只存静态资源,不能执行脚本。

高风险配置:

1
/uploads/shell.php 可以被 PHP 解析

2. Nginx 解析配置不当

如果 Nginx 与 PHP-FPM 配置不当,可能出现路径解析问题。

防护重点:

  • 严格设置 SCRIPT_FILENAME
  • 禁止上传目录执行 PHP。
  • 不将任意路径交给 PHP-FPM。

3. Apache 解析风险

Apache 中如果启用了特殊解析规则,某些多后缀文件可能被当作脚本解析。

例如:

1
shell.php.jpg

具体行为取决于配置。

六、上传后利用验证

上传成功后需要确认:

1
2
3
4
5
6
文件保存路径
文件访问 URL
是否能执行
当前执行用户
是否能写入其他目录
是否能执行系统命令

常见验证内容:

1
<?php phpinfo(); ?>

或:

1
<?php echo "ok"; ?>

授权测试中不要随意上传破坏性 WebShell,验证风险即可。

七、真实风险

文件上传漏洞可能导致:

  • WebShell 写入
  • 服务器命令执行
  • 网站被篡改
  • 钓鱼页面托管
  • 内网入口建立
  • 敏感文件读取
  • 横向移动

在渗透测试报告中,不应只写“上传成功”,而要说明上传后能造成什么影响。

八、防护建议

1. 后端白名单校验

只允许业务需要的类型:

1
2
3
4
5
jpg
png
gif
pdf
docx

不要使用黑名单作为主要防护。

2. 校验文件内容

结合文件头、图片解析库、MIME、扩展名多重判断。

图片上传可以重新编码:

1
用户上传图片 -> 服务端重新生成图片 -> 保存新文件

这样可以破坏图片马中的脚本内容。

3. 重命名文件

上传后使用随机文件名:

1
uuid.jpg

不要保留用户原始文件名。

4. 上传目录禁止执行

Nginx 示例:

1
2
3
4
5
location ^~ /uploads/ {
location ~ \.php$ {
return 403;
}
}

Apache 可以通过 .htaccess 或主配置禁止脚本执行。

5. 文件存储隔离

  • 上传文件放到静态文件服务器。
  • 上传目录与代码目录分离。
  • 不让上传文件被脚本引擎解析。

6. 权限控制

  • 上传目录不给执行权限。
  • Web 用户使用低权限账号。
  • 限制文件大小。
  • 限制上传频率。

九、测试清单

文件上传测试时可以按这个清单走:

1
2
3
4
5
6
7
8
9
10
11
是否只前端校验
是否校验后缀
是否校验 MIME
是否校验文件头
是否可上传脚本后缀
是否可双后缀绕过
是否可大小写绕过
是否返回访问路径
上传目录是否可执行
压缩包是否自动解压
文件名是否可控

十、总结

文件上传漏洞的核心不只是“能不能传 PHP”,而是完整判断:

1
上传入口 -> 校验逻辑 -> 存储路径 -> 访问路径 -> 解析环境 -> 可造成的影响

红队面试中,如果能把上传漏洞从发现、绕过、验证、风险到修复建议说完整,会比单纯背几个后缀更有说服力。