Pikachu中不安全的文件下载和上传
Unsafe Filedownload(不安全的文件下载)
文件下载功能在很多web系统上都会出现,一般我们当点击下载链接,便会向后台发送一个下载请求,一般这个请求会包含一个需要下载的文件名称,后台在收到请求后 会开始执行下载代码,将该文件名对应的文件response给浏览器,从而完成下载。 如果后台在收到请求的文件名后,将其直接拼进下载文件的路径中而不对其进行安全判断的话,则可能会引发不安全的文件下载漏洞。
此时如果 攻击者提交的不是一个程序预期的的文件名,而是一个精心构造的路径(比如../../../etc/passwd),则很有可能会直接将该指定的文件下载下来。
从而导致后台敏感信息(密码文件、源代码等)被下载。
所以,在设计文件下载功能时,如果下载的目标文件是由前端传进来的,则一定要对传进来的文件进行安全考虑。
切记:所有与前端交互的数据都是不安全的,不能掉以轻心!
源码:
<?php /** * Created by runner.han * There is nothing new under the sun */ $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); if ($SELF_PAGE = "unsafedownload.php"){ $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); } $PIKA_ROOT_DIR = "../../"; include_once $PIKA_ROOT_DIR . 'header.php'; ?> <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="unsafedownload.php">unsafe filedownload</a> </li> <li class="active">不安全的文件下载</li> </ul><!-- /.breadcrumb --> <a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)" data-content="我就说一句,1996年的状元是艾弗森,但是下面这个列表里面kobe排在第一位,你说奇怪不奇怪吧。"> 点一下提示~ </a> </div> <div class="page-content"> <div id="usd_main" style="width: 600px;"> <h2 class="title" >NBA 1996年 黄金一代</h2> <p class="mes" style="color: #1d6fa6;">Notice:点击球员名字即可下载头像图片!</p> <div class="png" style="float: left"> <img src="download/kb.png" /><br /> <a href="execdownload.php?filename=kb.png" >科比.布莱恩特</a> </div> <div class="png" style="float: left"> <img src="download/ai.png" /><br /> <a href="execdownload.php?filename=ai.png" >阿伦.艾弗森</a> </div> <div class="png" style="float: left"> <img src="download/ns.png" /><br /> <a href="execdownload.php?filename=ns.png" >史蒂夫.纳什</a> </div> <div class="png" style="float: left"> <img src="download/rayal.png" /><br /> <a href="execdownload.php?filename=rayal.png" >雷.阿伦</a> </div> <div class="png" style="float: left"> <img src="download/mbl.png" /><br /> <a href="execdownload.php?filename=mbl.png" >斯蒂芬.马布里</a> </div> <div class="png" style="float: left"> <img src="download/camby.png" /><br /> <a href="execdownload.php?filename=camby.png" >马库斯.坎比</a> </div> <div class="png" style="float: left"> <img src="download/pj.png" /><br /> <a href="execdownload.php?filename=pj.png" >斯托贾科维奇</a> </div> <div class="png" style="float: left"> <img src="download/bigben.png" /><br /> <a href="execdownload.php?filename=bigben.png" >本.华莱士</a> </div> <div class="png" style="float: left"> <img src="download/sks.png" /><br /> <a href="execdownload.php?filename=sks.png" >伊尔戈斯卡斯</a> </div> <div class="png" style="float: left"> <img src="download/oldfish.png" /><br /> <a href="execdownload.php?filename=oldfish.png" >德里克.费舍尔</a> </div> <div class="png" style="float: left"> <img src="download/smallane.png" /><br /> <a href="execdownload.php?filename=smallane.png" >杰梅因.奥尼尔</a> </div> <div class="png" style="float: left"> <img src="download/lmx.png" /><br /> <a href="execdownload.php?filename=lmx.png" >阿卜杜.拉希姆</a> </div> </div> </div><!-- /.page-content --> </div> </div><!-- /.main-content --> <?php include_once $PIKA_ROOT_DIR . 'footer.php'; ?>
源码分析:
<a href="execdownload.php?filename=kb.png" >科比.布莱恩特</a>
filename=kb.png中文件名未进行安全判断,直接进行了下载
漏洞验证:
利用文件下载漏洞,获取down_nba.php文件,该文件位于下载图片的上级目录,构造payload:../down_nba.php
浏览器中点击图片名称,右击在新窗口打开:http://192.168.10.7:85/pikachu-master/vul/unsafedownload/execdownload.php?filename=../down_nba.php
下载down_nba.php成功
Unsafe upfileupload(不安全的文件上传)
文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像、上传附件等等。
当用户点击上传按钮后,后台会对上传的文件进行判断 比如是否是指定的类型、后缀名、大小等等,然后将其按照设计的格式进行重命名后存储在指定的目录。
如果说后台对上传的文件没有进行任何的安全判断或者判断条件不够严谨,则攻击着可能会上传一些恶意的文件,比如一句话木马,从而导致后台服务器被webshell。所以,在设计文件上传功能时,一定要对传进来的文件进行严格的安全考虑。
例如:
- 验证文件类型、后缀名、大小;
- 验证文件的上传方式;
- 对文件进行一定复杂的重命名;
- 不要暴露文件上传后的路径;
client check(客户端验证)
源码:
<?php /** * Created by runner.han * There is nothing new under the sun */ $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); if ($SELF_PAGE = "clientcheck.php"){ $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); } $PIKA_ROOT_DIR = "../../"; include_once $PIKA_ROOT_DIR . 'header.php'; include_once $PIKA_ROOT_DIR.'inc/uploadfunction.php'; $html=''; if(isset($_POST['submit'])){ // var_dump($_FILES); $save_path='uploads';//指定在当前目录建立一个目录 $upload=upload_client('uploadfile',$save_path);//调用函数 if($upload['return']){ $html.="<p class='notice'>文件上传成功</p><p class='notice'>文件保存的路径为:{$upload['new_path']}</p>"; }else{ $html.="<p class=notice>{$upload['error']}</p>"; } } ?> <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> <?php echo $html;//输出了路径,暴露了 ?> </div> </div><!-- /.page-content --> </div> </div><!-- /.main-content --> <script> 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); } } </script> <?php include_once $PIKA_ROOT_DIR . 'footer.php'; ?>
源码分析:
前端做了验证,完全可以绕过
漏洞验证:
火狐浏览器开发者工具中直接删除onchange="checkFileExt(this.valus)事件,即可绕过
MIME type
http头中的content-type来验证上传文件是否是图片。
源码:
<?php /** * Created by runner.han * There is nothing new under the sun */ $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); if ($SELF_PAGE = "clientcheck.php"){ $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); } $PIKA_ROOT_DIR = "../../"; include_once $PIKA_ROOT_DIR . 'header.php'; include_once $PIKA_ROOT_DIR.'inc/uploadfunction.php'; $html=''; if(isset($_POST['submit'])){ // var_dump($_FILES); $mime=array('image/jpg','image/jpeg','image/png');//指定MIME类型,这里只是对MIME类型做了判断。 $save_path='uploads';//指定在当前目录建立一个目录 $upload=upload_sick('uploadfile',$mime,$save_path);//调用函数 if($upload['return']){ $html.="<p class='notice'>文件上传成功</p><p class='notice'>文件保存的路径为:{$upload['new_path']}</p>"; }else{ $html.="<p class=notice>{$upload['error']}</p>"; } } ?> <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="MIME type了解一下"> 点一下提示~ </a> </div> <div class="page-content"> <div id="usu_main"> <p class="title">这里只允许上传图片,不要乱搞!</p> <form class="upload" method="post" enctype="multipart/form-data" action=""> <input class="uploadfile" type="file" name="uploadfile" /><br /> <input class="sub" type="submit" name="submit" value="开始上传" /> </form> <?php echo $html;//输出了路径,暴露了 ?> </div> </div><!-- /.page-content --> </div> </div><!-- /.main-content --> <?php include_once $PIKA_ROOT_DIR . 'footer.php'; ?>
源码分析:
$mime=array('image/jpg','image/jpeg','image/png');//指定MIME类型,这里只是对MIME类型做了判断。
漏洞验证:
Burp拦截,上传.php文件,Burp中修改content-type为image/png,即可上传成功。
上传成功:
getimagesize
将一句话木马插入到图片中,通过本地文件包含漏洞来连接中国菜刀
源码:
<?php /** * Created by runner.han * There is nothing new under the sun */ $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); if ($SELF_PAGE = "clientcheck.php"){ $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); } $PIKA_ROOT_DIR = "../../"; include_once $PIKA_ROOT_DIR . 'header.php'; include_once $PIKA_ROOT_DIR.'inc/uploadfunction.php'; $html=''; if(isset($_POST['submit'])){ $type=array('jpg','jpeg','png');//指定类型 $mime=array('image/jpg','image/jpeg','image/png'); $save_path='uploads'.date('/Y/m/d/');//根据当天日期生成一个文件夹 $upload=upload('uploadfile','512000',$type,$mime,$save_path);//调用函数 if($upload['return']){ $html.="<p class='notice'>文件上传成功</p><p class='notice'>文件保存的路径为:{$upload['save_path']}</p>"; }else{ $html.="<p class=notice>{$upload['error']}</p>"; } } ?> <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">getimagesize()</li> </ul><!-- /.breadcrumb --> <a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)" data-content="getimagesize了解一下"> 点一下提示~ </a> </div> <div class="page-content"> <div id="usu_main"> <p class="title">这里只允许上传图片,不要乱搞!</p> <form class="upload" method="post" enctype="multipart/form-data" action=""> <input class="uploadfile" type="file" name="uploadfile" /><br /> <input class="sub" type="submit" name="submit" value="开始上传" /> </form> <?php echo $html;//输出了路径,暴露了 ?> </div> </div><!-- /.page-content --> </div> </div><!-- /.main-content --> <?php include_once $PIKA_ROOT_DIR . 'footer.php'; ?>
源码分析:
getimagesize()这个函数返回结果中有文件大小和文件类型,如果用这个函数来获取类型,从而判断是否是图片的话,会存在问题
我们可以伪造图片头。
漏洞验证:
将一句话木马插入到图片中:
cmd中创建图片马命令:copy close.png /b+muma.php mu.png
上传mu.png
文件路径:uploads/2020/08/07/2558635f2d21e74aaac732359910.png
利用本地文件包含漏洞:http://192.168.10.7:85/pikachu-master/vul/fileinclude/fi_local.php?filename=../../unsafeupload/uploads/2020/08/07/2558635f2d21e74aaac732359910.png&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2
中国蚁剑连接成功: