文件上传漏洞 是拿服务器权限最直接的路之一:如果网站允许你传文件、又没管好”传的是什么、放哪、能不能被执行”,你就能传一个能执行命令的脚本(Webshell),再访问它,等于拥有了 RCE。
以下仅在授权靶场(如 upload-labs、DVWA)练习;对他人服务器上传 Webshell 属严重违法。
原理:上传 = 在服务器放文件
网站常有头像上传、附件上传、图片分享。流程是:用户选文件 → 服务器保存到某目录 → 之后可访问。如果:
- 没限制类型:你传了
.php而不是.jpg; - 保存目录可执行:该目录能被 Web 访问且 PHP 解析器会执行
.php; - 文件名可控:你能预测访问路径;
那访问 https://target.com/uploads/shell.php 时,服务器就执行了你的脚本。
一句话木马:最小化的 webshell
所谓”一句话木马”,是极短的能接收外部指令并执行的脚本:
<?php @eval($_POST['cmd']); ?>
它接收一个 POST 参数 cmd 当作 PHP 代码执行。攻击者用中国菜刀、蚁剑等工具连接,就能图形化操作服务器:文件管理、命令执行、数据库操作。一句话虽短,威力极大,所以任何上传点都要严防 PHP/ASP/JSP 这类脚本。
绕过手法(靶场向)
防御常做”后缀白/黑名单”,攻击者就绕:
1. 黑名单不全
黑名单写了 php,攻击者换 php3、php5、phtml、pht(某些配置下这些也当 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.php;shell.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.php5、evil.phtml、evil.php.(末尾点)、evil.php (空格)、evil.PHP(大小写)、evil.php/.jpg(配合解析漏洞)。内容检查方面,若只查文件头前几个字节(如 jpg 的 FFD8),攻击者可把 PHP 代码接在合法图片后面做成”图片马”,文件头是图片、内容藏代码,骗过检查。还有用 .htaccess 上传(若目录允许)把某种后缀当 PHP 解析。
更多实战案例:拿下服务器后的危害链
一旦上传并执行成功,攻击者通常先执行 whoami、id 看权限,再读配置文件拿数据库密码,接着写计划任务或写公钥到 authorized_keys 维持权限,最后可能内网横向。所以文件上传不是”传个文件”的小事,它是很多大型入侵的入口。测试时要评估:上传目录是否可执行、能否被解析、是否可被包含、文件名是否可控、内容是否可藏代码。
常见坑
- 只在前端校验:前端 JS 校验一抓包就失效,必须在服务端校验。
- 只查后缀不查内容:图片马能绕过后缀白名单。
- 上传目录可执行脚本:应把上传目录配置成不可执行,与代码分离。
- 用原始文件名:攻击者控制文件名可构造路径穿越或特殊后缀,应重命名随机化。
进阶:修复
服务端做三层校验:一是类型校验,用文件真实 MIME 和内容特征(不仅是后缀);二是后缀白名单,只允许极少量安全后缀并统一转小写去空格;三是存储隔离,上传文件重命名为随机名、存到不可执行目录、用独立域名或对象存储返回。再配合内容安全扫描(杀毒、图片二次渲染破坏图片马)、限制文件大小、禁止执行权限,基本堵死绝大多数利用。
小测验
- 问题1:前端 JS 校验后缀够安全吗?答案:不够,抓包改文件就能绕过,必须服务端校验。
- 问题2:图片马怎么骗过检查?答案:文件头是合法图片、后面藏代码,只查文件头会中招。
- 问题3:上传目录该怎么配?答案:不可执行、随机重命名、与代码分离或用对象存储。
更多实战案例:解析漏洞配合上传
即使后缀和类型都校验了,某些服务器/中间件的”解析漏洞”仍能让图片被当脚本执行。经典如 Apache 把 evil.php.xxx(xxx 是不常见后缀)按 .php 解析、IIS 的 *.asp;.jpg 分号截断、Nginx 的 evil.jpg/.php 空字节或路径解析问题。防御方做完上传校验,还要确保上传目录的解析规则不会”误把图片当代码”,即存储与解析解耦。
更多实战案例:二次渲染与内容检测
高级防御会对图片做”二次渲染”(重新生成图片),破坏图片马里藏的代码。攻击者应对:把代码藏到渲染后仍保留的 chunk(如 PNG 的某些元数据、GIF 的注释段),或用工具(如 exiftool)把代码写进图片特定字段且渲染不丢。这是攻防拉锯:检测越严,构造越巧。但绝大多数站点只要做到”后缀白名单 + 不可执行目录 + 随机重命名”就已足够挡住常见利用。
常见坑(再补充)
- 只在前端校验:抓包改文件即绕过,必须服务端校验。
- 只查后缀不查内容:图片马可骗过后缀白名单。
- 上传目录可执行脚本:应配置不可执行,与代码分离。
- 用原始文件名:攻击者可构造路径穿越或特殊后缀,应随机重命名。
进阶(再补充):完整修复清单
服务端三层校验:类型校验(真实 MIME + 内容特征,非仅后缀)、后缀白名单(极少量安全后缀、统一小写去空格)、存储隔离(随机重命名、不可执行目录、独立域名或对象存储)。再配合内容安全扫描(杀毒、图片二次渲染)、限制文件大小、禁止执行权限。高危场景还应对文件做沙箱检测。
小测验(再补充)
- 问题1:解析漏洞怎么让图片变木马?答案:中间件把图片后缀按脚本解析执行。
- 问题2:二次渲染为什么能破图片马?答案:重新生成图片会丢掉藏着的代码。
- 问题3:上传目录该怎么配?答案:不可执行、随机重命名、与代码分离或用对象存储。
这一篇你该记住的
文件上传漏洞 = 传了可执行脚本 + 目录可解析 + 路径可预测,访问即 RCE。一句话木马 <?php @eval($_POST['cmd']);?> 是典型 webshell。绕过手法:黑名单不全换 php3/phtml、图片马配合包含、%00 截断、::$DATA、双后缀、竞争条件、前端校验绕过、传 .htaccess。防御铁三角:后缀白名单、服务器重命名、存不可执行目录(最好上云存储)。
文件上传常和文件包含配合——图片马要靠”包含”才能当 PHP 执行。下一篇就讲文件包含:让服务器把任意文件拉进来执行。