教程
🛡️

网络安全

Web 安全、渗透测试、密码学与安全合规的系统化教程。

文件上传漏洞:往服务器塞个 Webshell

讲清文件上传漏洞原理与类型(一句话木马),覆盖图片木马、%00 截断、::$DATA、路径绕过等手法与靶场实战,并给出白名单、重命名、禁执行等防御。

· 更新于 2026-07-18 阅读量 --

文件上传漏洞 是拿服务器权限最直接的路之一:如果网站允许你传文件、又没管好”传的是什么、放哪、能不能被执行”,你就能传一个能执行命令的脚本(Webshell),再访问它,等于拥有了 RCE。

以下仅在授权靶场(如 upload-labs、DVWA)练习;对他人服务器上传 Webshell 属严重违法。

原理:上传 = 在服务器放文件

网站常有头像上传、附件上传、图片分享。流程是:用户选文件 → 服务器保存到某目录 → 之后可访问。如果:

  1. 没限制类型:你传了 .php 而不是 .jpg
  2. 保存目录可执行:该目录能被 Web 访问且 PHP 解析器会执行 .php
  3. 文件名可控:你能预测访问路径;

那访问 https://target.com/uploads/shell.php 时,服务器就执行了你的脚本。

一句话木马:最小化的 webshell

所谓”一句话木马”,是极短的能接收外部指令并执行的脚本:

<?php @eval($_POST['cmd']); ?>

它接收一个 POST 参数 cmd 当作 PHP 代码执行。攻击者用中国菜刀、蚁剑等工具连接,就能图形化操作服务器:文件管理、命令执行、数据库操作。一句话虽短,威力极大,所以任何上传点都要严防 PHP/ASP/JSP 这类脚本

绕过手法(靶场向)

防御常做”后缀白/黑名单”,攻击者就绕:

1. 黑名单不全

黑名单写了 php,攻击者换 php3php5phtmlpht(某些配置下这些也当 PHP 解析);换大写 PHP;换 phP。防御要覆盖所有可执行后缀。

2. 图片马(最常用)

把 PHP 藏进图片,绕过”只让传图片”的限制:

# 把一句话追加到真实图片末尾
copy normal.jpg /b + shell.txt /a webshell.jpg

webshell.jpg 表面是图片,实际末尾藏着 <?php eval(...)。但要执行它,还需配合文件包含漏洞(见下篇)把图片当 PHP 包含,或服务器配置错误把 .jpg 当 PHP 解析。

3. %00 截断(历史)

老版本 PHP 在路径拼接时遇到空字节 \x00 会截断。上传 shell.php\x00.jpg,程序校验后缀是 jpg,但保存到 shell.php 因截断只取到 .php。现代 PHP 已修,老系统仍可能遇。

4. ::$DATA(Windows)

Windows 下 shell.php::$DATA 会被当作 shell.php 的数据流,绕过后缀检查,保存成 shell.php。针对 IIS/Windows 服务器。

5. 双后缀 / 点点

shell.php.jpg 被某些逻辑错误处理成 shell.phpshell.php.shell.php.. 在 Windows 去尾点变成 shell.php

6. 竞争条件(Race Condition)

程序先保存再校验/删除,攻击者在”保存后、删除前”的极短时间窗里访问执行。需写脚本高速并发抢。

7. 前端校验绕过

有些只在前端 JS 校验后缀,把请求截下来用 Burp 改成 .php 即可,后端根本没拦。

8. .htaccess / .user.ini 改写解析

上传 .htaccess 让某目录把 .jpg 当 PHP 解析:AddType application/x-httpd-php .jpg。若上传点允许传这些配置文件,危害放大。

靶场实战思路

以 upload-labs 为例,每关换一种防御,你要对应换绕过:Pass-1 前端 JS → Burp 改包;Pass-2 校验 Content-Type → 改 image/png;Pass-3 黑名单 → 换 php3;Pass-4 全后缀 → 传 .htaccess;Pass-5 大小写 → PHP;Pass-11 %00 截断……理解每关”它拦了什么、漏了什么”,比记答案重要。

防御:管好”传什么、放哪、能不能跑”

1. 后缀白名单(最关键)

只允许业务真正需要的类型:jpg、png、gif、pdf、docx绝不放行 php/asp/jsp/phtml 等脚本后缀。白名单比黑名单可靠一万倍。

$allow = ['jpg','png','gif'];
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
if (!in_array($ext, $allow)) die('类型不允许');

2. 重命名文件

不要用用户给的文件名,服务器自己生成随机名(如 md5(时间).jpg),杜绝 ::$DATA、双后缀、预测路径等问题。

3. 存到不可执行目录

上传目录不解析脚本:用 Web 服务器配置禁止该目录执行动态语言(Nginx location /uploads { ... deny all 动态; }),或把文件存到对象存储(OSS/S3),根本不在 Web 应用服务器上。

4. 二次渲染/内容校验

用图像处理库重新生成图片(GD/imagecreatefromjpeg),破坏图片马里的 PHP 代码;校验文件头魔数(真实 JPEG 以 FFD8 开头),不只看后缀。

5. 限制大小与数量

防拒绝服务,限制单文件大小和总容量。

6. 云存储 + CDN

上传到 OSS 并设公开只读、无执行能力,从架构上消除”上传即执行”。

更多实战案例:一张图片如何变成木马

很多网站允许用户传头像,如果只在前端用 JS 检查后缀是 .jpg 就放行,攻击者把一句话木马 <?php @eval($_POST['x']);?> 保存成 evil.jpg 上传,后端若没校验真实类型就存到可访问目录,再配合文件包含或解析漏洞,就能用中国菜刀、蚁剑连上拿 shell。更直接的:后端用原始文件名保存,攻击者传 evil.php,如果上传目录又被配置成可执行脚本,文件一传上去就能被当 PHP 执行。

更多实战案例:绕过后缀与内容检查

防御方常做后缀白名单,攻击者就用变种绕过:传 evil.php5evil.phtmlevil.php.(末尾点)、evil.php (空格)、evil.PHP(大小写)、evil.php/.jpg(配合解析漏洞)。内容检查方面,若只查文件头前几个字节(如 jpg 的 FFD8),攻击者可把 PHP 代码接在合法图片后面做成”图片马”,文件头是图片、内容藏代码,骗过检查。还有用 .htaccess 上传(若目录允许)把某种后缀当 PHP 解析。

更多实战案例:拿下服务器后的危害链

一旦上传并执行成功,攻击者通常先执行 whoamiid 看权限,再读配置文件拿数据库密码,接着写计划任务或写公钥到 authorized_keys 维持权限,最后可能内网横向。所以文件上传不是”传个文件”的小事,它是很多大型入侵的入口。测试时要评估:上传目录是否可执行、能否被解析、是否可被包含、文件名是否可控、内容是否可藏代码。

常见坑

  1. 只在前端校验:前端 JS 校验一抓包就失效,必须在服务端校验。
  2. 只查后缀不查内容:图片马能绕过后缀白名单。
  3. 上传目录可执行脚本:应把上传目录配置成不可执行,与代码分离。
  4. 用原始文件名:攻击者控制文件名可构造路径穿越或特殊后缀,应重命名随机化。

进阶:修复

服务端做三层校验:一是类型校验,用文件真实 MIME 和内容特征(不仅是后缀);二是后缀白名单,只允许极少量安全后缀并统一转小写去空格;三是存储隔离,上传文件重命名为随机名、存到不可执行目录、用独立域名或对象存储返回。再配合内容安全扫描(杀毒、图片二次渲染破坏图片马)、限制文件大小、禁止执行权限,基本堵死绝大多数利用。

小测验

  • 问题1:前端 JS 校验后缀够安全吗?答案:不够,抓包改文件就能绕过,必须服务端校验。
  • 问题2:图片马怎么骗过检查?答案:文件头是合法图片、后面藏代码,只查文件头会中招。
  • 问题3:上传目录该怎么配?答案:不可执行、随机重命名、与代码分离或用对象存储。

更多实战案例:解析漏洞配合上传

即使后缀和类型都校验了,某些服务器/中间件的”解析漏洞”仍能让图片被当脚本执行。经典如 Apache 把 evil.php.xxx(xxx 是不常见后缀)按 .php 解析、IIS 的 *.asp;.jpg 分号截断、Nginx 的 evil.jpg/.php 空字节或路径解析问题。防御方做完上传校验,还要确保上传目录的解析规则不会”误把图片当代码”,即存储与解析解耦。

更多实战案例:二次渲染与内容检测

高级防御会对图片做”二次渲染”(重新生成图片),破坏图片马里藏的代码。攻击者应对:把代码藏到渲染后仍保留的 chunk(如 PNG 的某些元数据、GIF 的注释段),或用工具(如 exiftool)把代码写进图片特定字段且渲染不丢。这是攻防拉锯:检测越严,构造越巧。但绝大多数站点只要做到”后缀白名单 + 不可执行目录 + 随机重命名”就已足够挡住常见利用。

常见坑(再补充)

  1. 只在前端校验:抓包改文件即绕过,必须服务端校验。
  2. 只查后缀不查内容:图片马可骗过后缀白名单。
  3. 上传目录可执行脚本:应配置不可执行,与代码分离。
  4. 用原始文件名:攻击者可构造路径穿越或特殊后缀,应随机重命名。

进阶(再补充):完整修复清单

服务端三层校验:类型校验(真实 MIME + 内容特征,非仅后缀)、后缀白名单(极少量安全后缀、统一小写去空格)、存储隔离(随机重命名、不可执行目录、独立域名或对象存储)。再配合内容安全扫描(杀毒、图片二次渲染)、限制文件大小、禁止执行权限。高危场景还应对文件做沙箱检测。

小测验(再补充)

  • 问题1:解析漏洞怎么让图片变木马?答案:中间件把图片后缀按脚本解析执行。
  • 问题2:二次渲染为什么能破图片马?答案:重新生成图片会丢掉藏着的代码。
  • 问题3:上传目录该怎么配?答案:不可执行、随机重命名、与代码分离或用对象存储。

这一篇你该记住的

文件上传漏洞 = 传了可执行脚本 + 目录可解析 + 路径可预测,访问即 RCE。一句话木马 <?php @eval($_POST['cmd']);?> 是典型 webshell。绕过手法:黑名单不全换 php3/phtml、图片马配合包含、%00 截断、::$DATA、双后缀、竞争条件、前端校验绕过、传 .htaccess。防御铁三角:后缀白名单、服务器重命名、存不可执行目录(最好上云存储)。

文件上传常和文件包含配合——图片马要靠”包含”才能当 PHP 执行。下一篇就讲文件包含:让服务器把任意文件拉进来执行。