第一次接触upload-labs靶场时,我就像发现了一个宝藏训练场。这个专门针对文件上传漏洞设计的靶场,包含了从基础到进阶的19个关卡,每关都模拟了真实网站中可能存在的安全缺陷。对于刚入门Web安全的新手来说,这里就像是个精心设计的闯关游戏,只不过我们破解的不是游戏关卡,而是各种文件上传限制。
文件上传漏洞在OWASP Top 10中长期占据重要位置,原因很简单——它危害大、利用简单。攻击者通过上传恶意文件(比如PHP webshell)就能直接获取服务器控制权。我在实际渗透测试中遇到过太多因为文件上传功能没做好而导致整个系统沦陷的案例。upload-labs把这些漏洞场景浓缩成了一个个关卡,让我们可以安全地练习各种绕过技巧。
搭建这个靶场非常简单,你可以选择Docker一键部署,也可以直接下载源码在本地运行。我建议初学者先在本地环境练习,这样可以用Burp Suite等工具随意抓包调试。靶场界面很简洁,左侧是关卡列表,右侧是文件上传区域和源码查看按钮。每关都会给出明确的任务:上传一个webshell到服务器。
第一关就像是在告诉我们:"别被表面现象骗了"。当我尝试上传.php文件时,页面立即弹出警告阻止上传。这看起来像是服务器在拒绝,但打开开发者工具查看网络请求后发现,请求根本没发出去——验证完全是在前端用JavaScript完成的。
这种前端验证有多脆弱呢?我教你们三种破解方法:
html复制<!-- 原始校验代码示例 -->
<script>
function checkFile() {
var filename = document.getElementById("upload").value;
if(!/\.(jpg|png|gif)$/.test(filename)){
alert("只允许上传图片文件!");
return false;
}
return true;
}
</script>
很多新手开发者会犯这个错误——只在客户端做验证。我在代码审计时经常看到类似实现,开发者以为这样能减轻服务器压力。但实际上,攻击者可以轻易绕过所有前端验证。正确的做法是:前端验证只为提升用户体验,后端验证才是安全保障的关键。
第二关开始触及服务端验证,这次检测的是Content-Type头。当我上传php文件时,服务端会检查这个头是否是image/jpeg之类的图片类型。绕过方法很简单:先用Burp拦截上传请求,然后把Content-Type改成image/jpeg就能骗过检测。
http复制POST /upload.php HTTP/1.1
Content-Type: multipart/form-data
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: image/jpeg <!-- 修改这一行 -->
<?php @eval($_POST['cmd']); ?>
第三关采用了黑名单机制,禁止上传.php文件。但开发者往往考虑不周全,不知道PHP还有其他可执行后缀如.php3、.php5、.phtml等。我上传shell.php5文件就成功绕过了检测。
更深入的做法是修改服务器配置。在Apache中,找到httpd.conf里的AddType application/x-httpd-php配置,把其他PHP后缀都加上。这样即使上传非标准后缀也能被解析:
apache复制AddType application/x-httpd-php .php .php3 .php5 .phtml
当所有PHP后缀都被封杀时,.htaccess文件就成了突破口。这个Apache配置文件可以改变目录行为。我上传了一个包含以下内容的.htaccess文件:
apache复制<FilesMatch "shell.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
然后上传一个包含PHP代码的shell.jpg文件。这样配置后,服务器会把jpg文件当作PHP执行。这种手法在实际渗透中非常有效,特别是当网站允许上传.htaccess文件时。
接下来的几关展示了如何利用系统特性绕过检测:
这些绕过方式都利用了Windows系统的文件处理特性。我在内网渗透测试中经常使用这些技巧,特别是当Web应用没有规范化文件名时。
第九关的源码几乎过滤了所有已知绕过手法,但仔细审计代码发现它只是简单地将非法字符替换为空。于是我上传"shell.php. .",经过替换后变成了"shell.php",成功绕过检测。这提醒我们:安全过滤必须考虑替换后的结果。
第十关采用了更严格的过滤——直接删除黑名单中的字符串。这时可以使用双写技术:上传"shell.pphphp",当中间的"php"被删除后,剩下的字符又组合成了新的"php"。
php复制// 漏洞代码示例
$filename = str_replace(['php', 'asp'], '', $filename);
第十一关和十二关展示了经典的截断攻击:
这些攻击在PHP版本低于5.3.4时特别有效。我在老旧系统渗透中仍经常遇到这种漏洞。
图片马是文件上传漏洞中最隐蔽的攻击方式之一。我常用的制作方法有:
bash复制copy /b normal.jpg + shell.php webshell.jpg
图片马要配合文件包含漏洞才能执行。在靶场中,我们需要开启allow_url_include配置:
php复制<?php include($_GET['file']); ?>
最后几关展示了条件竞争漏洞的威力。当系统先上传文件再进行安全检查时,攻击者可以在文件被删除前快速访问它。我使用Burp的Intruder模块连续发送100次请求,同时浏览器不断刷新页面,最终成功执行了webshell。
http复制POST /upload.php HTTP/1.1
Host: target.com
Content-Length: 1000
Content-Type: multipart/form-data
(上传请求内容)
在实际渗透中,这种攻击需要编写自动化脚本。我通常会准备两个线程:一个不断上传文件,另一个不断尝试访问。
文件上传漏洞的防御需要多层次方案:既要严格校验文件内容和后缀,又要妥善配置服务器环境,还要注意代码逻辑的严谨性。在靶场练习后,我建议读者尝试在DVWA等综合靶场中实践这些技巧,逐步建立完整的安全攻防思维。