文件上传漏洞
在现代的web网站中,文件上传功是一种常见的功能。比如一些博客网站,允许用户上传,图片,视频,头像,等许多其他类型的文件。但是向用户接受的文件越多,所面临的信息安全风险也就越大。如果web网站存在文件上传漏洞,那么恶意用户就可以利用文件上传漏洞将可执行上传到服务器中,最后获取到网站的权限。
一个漏洞百出的文件上传代码
<?php
$file=$_FILES['tx'];
if(is_uploaded_file($file["tmp_name"]))
{
if(move_uploaded_file($file["tmp_name"],"file/".$file['name']))
{echo "成功";}
else
{echo "失败";}
}
else
{
echo "上传失败";
}
这段代码提供了文件上传的功能,但是他很危险没有任何安全防护,被上传的文件也按原名保存在目录里。
用if函数判断是否有文件上传,有的话以原名复制到file的目录下。
js前端检测的文件上传代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="text/javascript">
function wenjscgl(sc){
var wenjian= sc.value;
var hz = wenjian.toLowerCase().substr(wenjian.lastIndexOf("."));
if(hz!=".jpg")
{
alert("请选择jpg格式的照片上传");
sc.outerHTML=sc.outerHTML;
}
}
</script>
<form action="dck.php" method="POST" enctype="multipart/form-data">
上传文件
<input type='file' name="tx" id="file" onchange="wenjscgl(this)">
<input type="submit" name="tj" value="提交">
</form>
<?php
$file=$_FILES['tx'];
if(isset($_POST['tj']))
if(is_uploaded_file($file["tmp_name"]))
{
if(move_uploaded_file($file["tmp_name"],"file/".$file['name']))
{echo "成功";}
else
{echo "失败";}
}
else
{
echo "请选择文件上传";
}?>
</body>
</html>
这是一段html+javascript+php的代码,javascript负责前端检测,拒绝不是.jpg的文件上传,javascript代码为获取文件上传的后缀并对后缀名进行判断如果不是jpg弹窗,是jpg就执行后面的php语句。php语句
判断是否有提交文件,有文件上传就用move_uploaded_file函数用本名上传至file目录下。
免费领取学习资料 2021年全套网络安全资料包及最新面试题(渗透工具,环境搭建、HTML,PHP,MySQL基础学习,信息收集,SQL注入,XSS,CSRF,暴力破解等等)
js检测绕过
由于上面的代码只做了前端的过滤,并没有在后端用php过滤,所以我们只要绕过前端就可以上传jpg格式的文件了。这里使用burpsuite来实施绕过。
把要上传的文件先改成jpg格式,通过前端验证以后用burp抓包再修改回可执行的格式。
可以看到上传成功。
文件后缀绕过
我们在网站上提交文件时,有些web网站会通过文件后缀过滤的方法来阻止恶意文件上传的事件。那么有过滤就有绕过
文件后缀源代码分析
header('Content-type:text/html;charset=utf-8');
$file=$_FILES['tx'];
if(isset($_POST['tj'])){
if(is_uploaded_file($file["tmp_name"]))
{
$qwe=pathinfo($_FILES["tx"]["name"]);
$kzm=$qwe['extension'];
if(strtolower($kzm)=='php'){
echo "<script>alert('不允许的文件上传')</script>";
}else{
move_uploaded_file($_FILES['tx']['tmp_name'],"file/".$_FILES['tx']['name']);
echo "<script>alert('文件上传成功')</script>";
}
}
else
{
echo "请选择文件上传";
}}?>
老规矩上来先分析一下源码,用file中,接着用if控制获取到提交才执行下面的语句,再用if判断提交中是否有文件。用pathinfo截取文件的后缀名,用strtolower函数将获取的后缀名转为小写。判断$kzm字段中也就是我们上传的文件后缀名是否是.php,如果是则弹出前端代码不“允许的文件上传”,反之 move_uploaded_file函数以原文件名上传至f同级目录file中。
需要注意的是虽然警告语句是用前端代码弹出的,但是我们对文件的判定是后端php执行的,所以上文提到的前端过滤代码在这里并不适用.
文件后缀绕过分析
文件后缀绕过的姿势也有非常多。
上面代码使用黑名单只过滤了.php文件的上传。
1,例如在httpd.conf中, 如果配置有如下代码,则能够解析php和phtm|文件。
AddType application/x-httpd php.php.phtml
所以,可以上传一个后缀为phtml的WebShell, 在Apache的解析顺序中,是从右到左开始解析文件后缀的,如果最右侧的扩展名不可识别,就继续往左判断,直到遇到可以解析的文件后缀为止,所以如果上传的文件名类似1.php.xxxx,因为后缀xxxx不可以解析,所以向左解析后缀php。
2,apache不仅会解析.php的后缀名还会解析如php1,php2,php3之类的后缀。我们可以上传这样的文件绕过。
文件类型绕过
通过文件类型过滤,如果服务端是通过content-type的值来判断文件类型而不是通过后缀名。
文件类型源代码分析
<?php
header('Content-type:text/html;charset=utf-8');
$file=$_FILES['tx'];
if(is_uploaded_file($file['tmp_name'])){
$qwe = $_FILES["tx"]["type"];
if ($qwe == 'application/octet-stream') {
echo "<script>alert('不允许的文件上传')</script>";
} else {
move_uploaded_file($_FILES['tx']['tmp_name'], "file/" . $_FILES['tx']['name']);
echo "<script>alert('文件上传成功')</script>";
}
}
?>
代码中判定是否有文件提交,有文件提交就用qwe变量获取文件的content-type然后判断content-type值是否为application/octet-stream,application/octet-stream是php文件的类型。接着把文件上传至服务器file目录下。
文件类型绕过
content-type值虽然看不见,但是我们使用burpsuite是可以修改的。使用burpsuite抓取文件上传数据包。
修改content-type值为jpeg的类型 image/jpeg
上传成功,其实可以修改成任意的字符串因为只过滤了php类型的,并没有对上传的类型做其他限制,只要不是php类型的就可以了。