君衍.
一、环境搭建
注意:本靶场使用php版本为5.2.17才可正常使用。
首先这个靶场用来学习和测试文件上传漏洞的靶场(Web安全实验场)。它提供了一系列的漏洞场景和挑战,让安全研究人员和开发者能够实践和测试文件上传漏洞相关的技术和解决方案。
文件上传漏洞是指应用程序在接收用户上传的文件时,未能充分验证或限制文件类型、大小、执行权限等导致的安全漏洞。攻击者可能通过滥用这一漏洞,上传包含恶意代码或有害内容的文件,从而危害服务器和应用程序的安全。
这个我们使用小皮来提供中间件,源码可以去github上进行下载:
https://github.com/c0ny1/upload-labs
使用Nginx或者Apache中间件即可。同时放入小皮的web目录里面进行访问即可。
即为www目录下面,然后进行访问查看是否完成环境的搭建。
看到如上界面我们即可完成环境的搭建。
二、第一关 前端JS检测后缀
首先我们这里我们首先构造一个一句话木马来供我们来测试,这里我们使用phpinfo函数来进行判断:
创建一个文件为1.php:
<?php phpinfo(); ?>
我们直接上传尝试:
这个我们可以看到回显结果为:该文件不允许上传,请上传.jpgl.png|.gif类型的文件,当前文件类型为: .php
在文件上传时,用户选择文件时,或者提交时,有些网站会对前端文件名进行验证,一般检测后缀名,是否为上传的格式。如果上传的格式不对,则弹出提示文字。此时数据包并没有提交到服务器,只是在客户端通过 js 文件进行校验,验证不通过则不会提交到服务器进行处理。
1、源码分析
下面我们来观察其中的源码进行分析:
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name) == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
我们这里只查看关键代码可以看到这里使用前端JS进行了检测。详细查看下源码:
# 定义了一个JS函数
function checkFile() {
# 通过document.getElementsByName方法来获取名为upload_file元素
var file = document.getElementsByName('upload_file')[0].value;
# 判断用户是否进行了选择文件,如果没有选择,那么提示用户选择
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
//定义允许上传的文件类型
var allow_ext = ".jpg|.png|.gif";
//提取上传文件的类型
var ext_name = file.substring(file.lastIndexOf("."));
//判断上传文件类型是否允许上传
if (allow_ext.indexOf(ext_name) == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
var ext_name = file.substring(file.lastIndexOf("."));
:提取用户上传文件的后缀名。 使用lastIndexOf()方法找到文件名中最后一个.的位置,然后使用substring()方法获取该位置到字符串末尾的子字符串,即文件的后缀名。if (allow_ext.indexOf(ext_name) == -1) {
:检查用户上传的文件后缀名是否在允许的文件类型列表中。 如果用户上传的文件后缀名不在允许的文件类型列表中(即indexOf()返回值为-1),则弹出提示框告知用户不允许上传该类型的文件,并返回false,表示文件不符合条件,上传操作终止。
2、禁用浏览器JS上传
这里我们可以看到是使用的是前端JS进行过滤的,所以我们可以禁用浏览器的JS解析,我这里使用的火狐浏览器。
这里我们在URL中输入:
about:config
然后搜索:
JavaScript.enabled
我们可以看到这里是true,也就是启用的状态,然后点击:
即为false即为禁用,这下我们继续尝试上传:
即可完成本关的文件上传。
3、burp抓包修改
首先我们使用它规定上传的文件类型进行上传,这里我使用jpg文件来绕过JS的过滤:
然后去上传,绕过JS过滤同时使用burp进行抓包:
这里我们需要注意抓包使用我们真实的IP地址而不是使用127.0.0.1进行抓包
这里我们即可看到我们上传的文件类型为jpg,然后我们在这里将文件类型改为php:
点击放通,即可看到我们上传成功:
我们在upload目录下即可进行执行,可见前端的过滤即可轻松绕过。
三、第二关 MIME头验证
我们同样使用1.php尝试去上传,即可看到:
这里我们看到输出:文件类型不正确,请重新上传。 同时我们点击提示可以看到
本pass在服务端对数据包的MIME进行检查!其实是对我们上传的内容进行了MIME验证,判断上传文件的MIME类型是不是我们的预期类型。
1、源码分析
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'];
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
首先判断表单是否进行了提交
if (isset($_POST['submit']))
,然后判断服务器上是否存在指定的上传目录UPLOAD_PATHif (file_exists(UPLOAD_PATH))
,再次进行判断上传文件的MIME类型是否被允许的图像类型即为jpeg、png、gif类型if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif'))
,然后获取上传文件的临时文件路径,构建目标文件的路径,同时包含了上传目录以及上传文件的原始文件名,使用move_uploaded_file
函数完成上传文件的移动,如果文件成功移动,则为tr