文件上传漏洞
一、原理
文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
二、搭建靶场环境
PS:通过自己搭建靶场的方式利用漏洞,可以更加熟练PHP、JS的使用,同时可以更好的理解漏洞产生的原因及如何防御
前端校验
1.创建表单,用于上传文件
<div id="upload">
<form action="upload_file.php" method="post" enctype="multipart/form-data" onsubmit="return CheckFile()">
<label for="file">头像:</label>
<input type="file" name="file" id="file">
<input type="submit" name="submit" value="提交">
</form>
</div>
2.js代码校验
// 以下JS代码功能为检查文件后缀名合法性
function CheckFile(){
var file = document.getElementById('file').value;
if(file == "" || file == null) {
alert('请选择您要上传的文件!');
return false;
}
// 定义文件上传的扩展名
var allow_ext = ".jpg|.png|.gif|.jpeg|.jiff";
// 提取上传文件的扩展名
var ext_name = file.substring(file.lastIndexOf("."));
// 判断上传文件是否符合要求
if (allow_ext.indexOf(ext_name) == -1){
var msg = "请输入" + allow_ext + "类型的文件!";
alert(msg);
return false;
}
}
// 需要在要提交的表单写入属性 onsubmit = return CheckFile();
Extension:
substring(start, end):截取字符串,参数为下标;只填一个参数代表从该下标开始到结束
indexOf():返回参数所在的下标位置,若目标不存在则返回-1
lastIndexOf():返回该参数最后一个下标位置
3.后端页面upload_file.php
<?php
if($_FILES['file']['error'] > 0){
echo $_FILES['file']['error'];
}
/*
echo "上传文件名: " . $_FILES["file"]["name"] . "<br>";
echo "文件类型: " . $_FILES["file"]["type"] . "<br>";
echo "文件大小: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "文件临时存储的位置: " . $_FILES["file"]["tmp_name"];
*/
// 保存上传的文件
// 判断文件是否存在
if (file_exists("upload/" . $_FILES['file']['name'])){
echo "文件已存在";
}
else{
// 将文件保存到指定目录
$filename = "upload/" . date("Ymd_His.") . end(explode('.', $_FILES['file']['name']));
// move_uploaded_file(file,newloc) file:要移动的文件 newloc:文件的新位置。
move_uploaded_file($_FILES['file']['tmp_name'], $filename) or die('上传失败');
}
echo "<script>alert('上传成功!')</script>";
echo "<script>location.href='./list.php'</script>";
?>
后端校验
// 判断后缀名
$allowExts = array("jpg", "jpeg", "png", "gif");
$ext_name = end(explode('.', $_FILES['file']['name']));
if (!in_array($ext_name, $allowExts)){
echo "<script>alert('请上传 .jpg | .png | .jpeg | .png | .gif 类型的文件!')</script>";
echo "<script>location.href='list.php'</script>";
}
// 判断文件类型
$allowFileTypes = array("image/jpeg", "image/jpg", "image/gif", "image/png");
if (!in_array($_FILES['file']['type'], $allowFileTypes)){
echo "<script>alert('请上传 .jpg | .png | .jpeg | .png | .gif 类型的文件!')</script>";
echo "<script>location.href='list.php'</script>";
}
三、绕过方式
1.前端绕过
前端绕过的方式很简单,主要有两种方法
-
可以通过F12禁用或修改JS代码(此方法可能会导致无法执行其他正常的js功能)
-
将要上传的文件名更改为合法的,上传之后Burp拦截请求包修改回正常的再发送
2.黑白名单绕过
可以修改扩展名为phtml, php3, phpphp, php php, phphpp, PhP, php.xxx 等等绕过
测试是否被成功解析
3.文件类型绕过
上传文件后,burp修改Content-Type参数值
4.图片马包含
存在文件包含漏洞的情况下,制作图片马上传进行包含。
5.条件竞争
文件上传时会对文件进行验证,对传入的文件进行了临时保存,上传php文件,利用bp抓包,设置多线程,不断发包。
同时浏览器访问上传的php文件,不断刷新。
本人学习记录,欢迎各位大佬指正
注:
以上仅供学习交流,未用于非法用途。