实战演练:用BurpSuite绕过upload-labs前10关的5种奇葩姿势(附避坑指南)
实战演练:用BurpSuite绕过upload-labs前10关的5种奇葩姿势(附避坑指南)
很多刚接触Web安全的朋友,一听到“文件上传漏洞”,第一反应可能就是“改个后缀名”或者“传个图片马”。但当你真正上手像upload-labs这样的经典靶场时,往往会发现事情没那么简单。服务器端的校验逻辑五花八门,从前端JS到后端MIME类型、黑名单过滤,再到各种字符串处理函数,稍不留神就会卡在某个关卡。今天,我们不按靶场原有的关卡顺序来,而是换个思路,从攻击者(或者说,安全测试者)的视角出发,将前10关遇到的防御手段归纳为几种典型的技术类型,并手把手教你如何用BurpSuite这把“瑞士军刀”,以五种意想不到的“姿势”优雅绕过。更重要的是,我会分享在实操中踩过的坑和对应的解决方案,让你不仅能“通关”,更能理解背后的原理,在真实环境中也能举一反三。
1. 环境准备与BurpSuite抓包基础
在开始我们的“绕过之旅”前,确保你的实验环境已经就绪。upload-labs靶场通常运行在PHP环境中,我推荐使用PHPStudy这类集成环境,它一键部署,省时省力。但这里有个新手常遇到的“拦路虎”:BurpSuite抓不到本地回环地址(127.0.0.1)的数据包。
这是因为Burp的代理默认监听本机网络接口,但对发往127.0.0.1的流量“视而不见”。解决这个问题有两个主流方法:
- 方法一:使用本机局域网IP访问靶场。打开命令提示符,输入
ipconfig,找到你当前活跃网卡(比如WLAN或以太网)的IPv4地址,例如192.168.1.100。然后在浏览器中用这个IP替换127.0.0.1来访问upload-labs。 - 方法二:修改系统主机名映射。编辑
C:\Windows\System32\drivers\etc\hosts文件(需要管理员权限),添加一行如127.0.0.1 test.local,之后在浏览器中用http://test.local访问靶场。Burp可以正常拦截这个域名解析到127.0.0.1的流量。
环境搞定后,我们快速过一下BurpSuite拦截和修改请求的基本操作流程:
- 浏览器配置代理为
127.0.0.1:8080,并安装Burp的CA证书(至关重要,否则HTTPS站点无法拦截)。 - 打开BurpSuite,在Proxy->Intercept标签页,确保Intercept is on是打开状态。
- 在浏览器中进行文件上传操作,请求会被Burp暂停。
- 在Burp的拦截界面,你可以直接修改HTTP请求的任何部分,如文件名、Content-Type等。
- 修改完成后,点击Forward发送请求,或者点击Drop丢弃。
注意:每次实战前,请务必清空靶场的
upload目录,避免之前上传的文件干扰判断。同时,准备好你的“武器”——一个内容为<?php phpinfo();?>的测试文件,用它来验证上传是否成功最直观。
2. 姿势一:前端校验的“障眼法”与MIME类型伪造
这是最常见也是最基础的防御层,通常对应靶场的前几关。它的核心特点是:校验发生在数据到达服务器之前。
2.1 绕过前端JavaScript校验
当你选择了一个.php文件点击上传,页面立刻弹窗警告“不允许上传”,但还没看到任何网络请求发出——这大概率是前端JavaScript在作祟。查看网页源码,你可能会发现类似下面的函数:
function checkFile() { var file = document.getElementById("upload_file").value; var ext = file.substring(file.lastIndexOf(".")).toLowerCase(); if (ext != '.jpg' && ext != '.png' && ext != '.gif') { alert("只允许上传jpg/png/gif格式文件!"); return false; } return true; }这种校验形同虚设,因为攻击者完全掌控发送给服务器的数据。绕过方法简单粗暴:
- BurpSuite拦截修改:先将你的
shell.php改名为shell.jpg上传。这时前端校验通过,请求被Burp拦截。你直接在Raw视图里找到filename="shell.jpg"这一部分,把它改回filename="shell.php",然后放行。服务器收到的是.php文件,而前端对此一无所知。 - 禁用浏览器JS:更直接的方法是,在浏览器开发者工具(F12)的设置里,或者通过插件,临时禁用JavaScript。这样,校验函数根本不会执行,你可以直接上传
.php文件。
2.2 伪造MIME类型
过了前端JS,下一关可能提示“文件类型不正确”。这时,查看Burp拦截到的请求,你会发现一个叫Content-Type的头部,它的值可能是application/octet-stream(二进制流)或根据你本地文件得出的类型。服务器端正是在检查这个值是否在白名单内(如image/jpeg,image/png)。
绕过方法就是“挂羊头卖狗肉”:
- 正常上传你的
.php文件,被Burp拦截。 - 在请求体中,找到
Content-Type: application/octet-stream这一行。 - 将其修改为任一种图片格式的MIME类型,例如
Content-Type: image/jpeg。 - 放行请求。
提示:常见的图片MIME类型包括
image/jpeg,image/png,image/gif。这种绕过方式成功的关键在于,服务器只检查了请求头中的Content-Type,而没有对文件内容进行真正的二进制识别(如图片头标识)。
3. 姿势二:黑名单过滤的“漏网之鱼”
当攻击数据抵达服务器端,开发者往往会采用黑名单机制,禁止一系列危险后缀,如.php,.asp,.jsp等。upload-labs的许多关卡都基于此设计。但黑名单总有遗漏,我们的任务就是找到这些“漏网之鱼”。
3.1 非常规PHP后缀
PHP引擎并非只认识.php这一个后缀。在历史版本或特定配置下,.php3,.php4,.php5,.phtml,.pht等后缀同样会被PHP解析器执行。如果服务器的黑名单只禁了.php,这就是一个绝佳的突破口。
操作步骤:
- 将你的木马文件命名为
shell.php5或shell.phtml。 - 直接上传,或用Burp在传输过程中修改后缀名。
但这里有一个至关重要的环境配置坑!默认情况下,PHPStudy可能并未将这些后缀与PHP解析器关联。你需要手动配置:
- 打开PHPStudy,进入其他选项菜单->打开配置文件->httpd-conf。
- 在配置文件中搜索
AddType application/x-httpd-php。 - 你会找到类似这样的一行(可能被注释掉):
#AddType application/x-httpd-php .php .phtml .php3 - 去掉行首的
#号,并确保你需要的后缀(如.php5,.pht)都在后面,例如:AddType application/x-httpd-php .php .phtml .php3 .php5 .pht - 保存文件,并重启PHPStudy的Apache服务。
3.2 大小写混淆绕过
在Windows服务器系统上,文件系统对大小写不敏感,shell.php和shell.PHP指向的是同一个文件。如果后端代码在过滤时,没有使用strtolower()或类似的函数将输入统一转为小写,那么黑名单里的.php就拦不住.PHP或.Php。
在Burp中,直接将filename="shell.php"修改为filename="shell.PHP"即可尝试绕过。这种漏洞在代码审计中表现为缺失了后缀名的规范化处理步骤。
4. 姿势三:利用配置文件“借壳上市”
当黑名单足够全面,堵死了所有已知的可执行后缀时,我们就需要更巧妙的思路:不直接上传可执行文件,而是上传一个配置文件,让服务器把普通的图片文件当作PHP代码来执行。这主要针对Apache服务器。
4.1 .htaccess文件攻击
.htaccess是Apache服务器的一个分布式配置文件,它可以覆盖其所在目录及其子目录的服务器配置。我们可以利用它实现“指鹿为马”。
创建.htaccess文件:新建一个文本文件,命名为
.htaccess(注意前面有个点)。内容如下:<FilesMatch "shell.jpg"> SetHandler application/x-httpd-php </FilesMatch>这段配置的意思是:强制将当前目录下名为
shell.jpg的文件,当作PHP脚本来解析执行。上传与利用:
- 首先,将你的PHP木马代码保存为
shell.jpg并上传。 - 然后,上传这个
.htaccess文件。 - 此时,访问
http://你的靶场地址/upload/shell.jpg,服务器就会执行其中的PHP代码。
- 首先,将你的PHP木马代码保存为
4.2 .user.ini文件攻击
如果.htaccess也被禁用了(常见于靶场后续关卡),我们可以转向.user.ini。这个文件是PHP的配置文件,影响范围也是其所在目录及子目录。它需要与一个已有的.php文件配合使用。
假设靶场的上传目录里已经有一个readme.php文件。
创建.user.ini文件:内容为:
auto_prepend_file=shell.jpgauto_prepend_file指令会在该目录下所有PHP文件执行之前,自动包含并执行指定的文件(shell.jpg)。上传与利用:
- 同样,先将木马保存为
shell.jpg并上传。 - 上传
.user.ini文件。 - 此时,访问
http://你的靶场地址/upload/readme.php。服务器在执行readme.php之前,会先执行shell.jpg里的代码,从而达到我们的目的。
- 同样,先将木马保存为
注意:
.user.ini的生效需要PHP运行在FastCGI模式下。在PHPStudy中,确保你的PHP版本选择的是NTS (Non-Thread Safe)版本,这通常对应FastCGI模式。
5. 姿势四:Windows系统特性“神助攻”
这类绕过姿势严重依赖于Windows操作系统在处理文件名时的特殊行为,在Linux环境下通常无效。它们利用了代码逻辑与系统实际行为之间的差异。
5.1 空格绕过
观察后端过滤代码,如果它在获取文件名后,没有使用trim()函数去除首尾空格,而是直接进行后缀截取和黑名单匹配,就可能存在漏洞。
- 攻击构造:将文件名改为
shell.php(注意php后面有一个空格)。 - Burp操作:上传时,Burp拦截请求,将
filename修改为shell.php。 - 原理:假设黑名单包含
.php。代码使用strrchr($file_name, '.')截取后缀,得到的是.php(包含空格)。这个字符串不在黑名单数组array(".php")中,因为数组里是.php。于是绕过检查。文件上传到Windows系统后,系统会自动去除文件名末尾的空格,保存为shell.php。
5.2 点号绕过
如果代码在截取后缀前,缺少了去除末尾点号的处理(例如没有调用deldot()或类似逻辑),而Windows系统会自动删除文件末尾的点。
- 攻击构造:
shell.php. - Burp操作:修改
filename为shell.php.。 - 原理:
strrchr('shell.php.', '.')截取到的是最后一个点及其后的内容,即单独的.。这个点号.显然不在黑名单里,绕过成功。Windows保存时去掉末尾点,文件变回shell.php。
5.3 ::$DATA 流绕过
这是Windows NTFS文件系统的一个特性。::$DATA是NTFS文件流的一种表示。在文件名后加上::$DATA,Windows在写入文件时会将其忽略,但某些字符串处理函数可能无法正确识别。
- 攻击构造:
shell.php::$DATA - Burp操作:修改
filename为shell.php::$DATA。 - 原理:如果后端代码没有使用
str_ireplace('::$DATA', '', $file_ext)这样的语句来清除::$DATA字符串,那么strrchr('shell.php::$DATA', '.')可能会得到.php::$DATA,这与黑名单不匹配。文件最终在磁盘上创建时,::$DATA被忽略,生成的就是shell.php。
6. 姿势五:组合拳与逻辑漏洞挖掘
到了后期关卡,开发者可能会补上前面提到的单个漏洞。这时,我们需要分析代码的整体处理流程,寻找组合利用的机会,或者发现更深层的逻辑顺序漏洞。
一个经典的组合是“点+空格+点”。观察下面这个典型的过滤链:
trim():去除首尾空白字符。deldot():从末尾开始删除点号,直到遇到非点号字符(注意:遇到空格也会停止)。strrchr():查找最后一个点号并截取后缀。
现在,我们传入一个精心构造的文件名:shell.php. .(点、空格、点)。
trim('shell.php. .')->shell.php. .(首尾无空格,不变)deldot('shell.php. .'):从末尾开始删点。删除最后一个点后,字符是空格,函数停止。结果变为shell.php.(末尾是一个点加一个空格)。strrchr('shell.php. ', '.'):查找最后一个点,位置在php后面,截取得到.(一个点加一个空格)。- 后续的
trim('. ')会去掉空格,得到.。一个单独的点号,成功绕过黑名单! - 最终保存的路径是原始文件名
shell.php. .,Windows系统会自动清理末尾的点和空格,得到shell.php。
这种绕过方式的关键在于,发现了deldot()函数遇到空格即停止的逻辑,与系统最终清理行为的差异。它要求我们对每一行代码的作用和顺序有清晰的理解。
避坑指南与实战心得
- 环境一致性:很多绕过(特别是Windows特性)严重依赖服务器环境。在本地测试成功的Payload,换到Linux生产环境可能完全失效。实战中,信息收集(判断服务器操作系统)是第一步。
- Burp的编码问题:在Burp中修改文件名时,空格、点号等特殊字符有时会被URL编码。确保在Proxy -> Intercept的Raw视图里修改,而不是在Params视图。如果看到
%20(空格)、%2e(点),需要理解这是编码后的表示,直接修改其原始字符即可。 - 多次编码绕过:在一些更复杂的过滤场景中,服务器可能会对文件名进行解码或多次检查。可以尝试对Payload进行双重URL编码(如空格
%20再编码为%2520),可能绕过一些简单的字符串匹配。 - 内容检测绕过:本文聚焦于“上传”动作本身的绕过。在实际靶场或真实场景中,后端还可能对文件内容进行检测(如图片头、PHP关键词)。这时就需要用到图片马(将PHP代码嵌入图片的EXIF信息或二进制末尾)并结合文件包含漏洞,或者使用短标签、动态函数调用等方式混淆PHP代码。这又是一个更大的话题了。
文件上传漏洞的攻防是一场关于“细节”的战争。每一处看似微不足道的字符串处理函数、每一个系统平台的特性差异,都可能成为突破口或防御点。通过BurpSuite这类工具,我们能够清晰地看到数据流动的每一个环节,并施加精确的影响。希望这五种“姿势”和其中穿插的避坑思路,能帮你不仅通关upload-labs,更能建立起一套分析文件上传功能安全性的方法论。记住,工具是手的延伸,思路才是真正的大脑。多读代码,多思考“如果我是开发者,我会怎么过滤?”,你就能发现更多意想不到的“奇葩姿势”。
