小伙伴们大家好!本期为大家带来的是文件上传漏洞之文件头绕过getimagesize()。
目录
getimagesize()
getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。
getimagesize() 函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。
GIF89a
“GIF89a”经常作为“Graphics Interchange Format number 89A”的缩写来使用,中文表示:“图形交换格式编号89A”
一个GIF89a图形文件就是一个根据图形交换格式(GIF)89a版(1989年7 月发行)进行格式化之后的图形。
绕过原理
绕过getimagesize()其实很简单,我们只需要在文件内容的起始位置加上一个GIF89a即可,这样我们的文件就会被认为是一个图片,php的getimagesize()函数也检测不出来我们构造的这个“虚假”的图片是无效的。
实战演示
我这里是自己写了两段代码,用phpstudy2018集成环境搭建的一个小靶场。phpstudy集成环境的搭建在我之前的文章PhpStudy环境搭建+MySQL基础+PHP操作数据库有讲解,供大家参考。
源码:
4.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件后缀绕过</title>
</head>
<body>
<script type="text/javascript">
function selectFile(file) {
var filename = file.value;
var mime = filename.toLowerCase().substr(filename.lastIndexOf("."));
if (mime != ".png") {
alert("请选择png格式的照片上传");
file.outerHTML = file.outerHTML
}
}
</script>
<center>
<form action="file04.php" method="post" enctype="multipart/form-data">
<label for="file">请上传png格式图片:</label>
<input type="file" name="file" id="file" onchange="selectFile(this)"/><br/>
<input type="submit" name="submit" value="上传" />
</form>
</center>
</body>
</html>
file04.php
<?php
header('Content-type:text/html;charset=utf-8');
if ($_FILES["file"]["error"] > 0) {
echo "Return Code:".$_FILES["file"]["error"]."<br/>";
} else {
if ($_FILES['file']['type'] != "image/png" || !getimagesize($_FILES['file']['tmp_name'])){
echo "<center><br/>";
exit("请上传png格式的文件");
echo "</center>";
}
echo "<center><br/>";
echo "upload: ".$_FILES["file"]["name"]."<br/>";
echo "type: ".$_FILES["file"]["type"]."<br/>";
echo "size: ".($_FILES["file"]["size"] / 1024)."KB<br/>";
echo "Temp file: ".$_FILES["file"]["tmp_name"]."<br/>";
if (file_exists("upload/".$_FILES["file"]["name"])) {
echo $_FILES["file"]["name"]." already exists. ";
} else {
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/".$_FILES["file"]["name"]);
echo "Stored in: "."upload/".$_FILES["file"]["name"];
}
echo "</center>";
}
1、尝试上传webshell
我们直接尝试上传带有一句话木马的webshell后门。
发现有前端验证,我们直接鼠标点击右键检查,将前端验证的代码删除掉。
点击上传!
上传失败,提示我们请上传png格式的文件,可能后端存在对文件类型的检验。
那我们就抓包改一下Content-Type试一下。
点击forward发送,回到浏览器查看页面响应情况。
发现依旧提示我们上传png格式的图片,猜测后端可能使用了getimagesize()函数来检查文件图片大小的信息。
这样我们再抓包将文件内容的开头加上GIF89a试一下。
之后点击Forward发送,再次回到浏览器查看响应。
OK,webshell上传成功。
2、使用连接工具连接webshell
webshell上传成功之后,接下来我们就使用webshell连接工具来连接我们成功上传的后门shell。
我这里使用的是中国蚁剑,大家使用其他的连接工具如菜刀、冰蝎等工具效果都是一样的。
测试成功之后,我们添加数据。
成功拿下站点!
总结
其实绕过getimagesize()函数的主要就是GIF89a的功能,由于GIF89a的加入,让getimageszie()函数也以为我们上传的webshell文件是图片,这样就轻松绕过了getimagesize()函数。