zoukankan      html  css  js  c++  java
  • 【Web安全】之文件上传漏洞

    一、文件上传漏洞介绍

    Web应用程序通常带有文件上传的功能,比如在博客园发表文章需要上传图片等行为,这其中就可能存在文件上传漏洞。

    如果Web应用程序存在上传漏洞,攻击者可以直接上传WebShell(以asp、php或者jsp等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页后门)到服务器上。

    二、解析漏洞

    攻击者在利用上传漏洞时,通常会与Web容器的解析漏洞配合在一起。

    常见的Web容器有IIS、Nginx、Apache、Tomcat。

    1. IIS解析漏洞(基于IIS6.0环境)

    (1)当建立*.asa*.asp格式的文件夹时,其目录下的任意文件都将被IIS当做asp文件来解析。

    测试案例:建立文件夹parsing.asp,在文件夹内新建内容为<%=NOW()%>的文本文件test.txt,然后在浏览器里访问。

    测试结论:NOW()是ASP获取当前时间的函数。正常而言,IIS是不会去解析文本文档格式而是直接显示内容。而在parsing.asp文件夹内,却被当做ASP脚本来解析。

    (2)当文件为*.asp;1.jpg时,IIS同样会以ASP脚本执行。

    测试案例:创建文件名为test.asp;1.jpg,其内容为<%=NOW()%>

    (3)WebDav漏洞

    WebDav是一种基于HTTP1.1协议的通信协议。在GET、POST、HEAD等HTTP标准方法之外扩展了新方法。

    攻击者可以通过PUT方法向服务器上传危险脚本。

    2. Apache解析漏洞(基于Apache 1.xApache 2.x环境)

    (1)Apache漏洞介绍:

    我们在Apache环境中设置文件内容为<?php phpinfo(); ?>1.php.aa文件,在正常情况下,应该会提示下载该文件,但是在此情况下却显示了phpinfo()的内容。

    (2)Apache在解析文件名的原理:

    当遇到不认识的扩展名,将会从后向前解析,直到碰到认识的扩展名。例如文件名为1.php.aa,首先解析aa扩展名,发现不认识继续向前面遍历。

    (3)Apache可识别扩展名(在/conf/mime.types文件中有详细列表)

    (4)对于Apache解析漏洞的防范:

    在开发设计上传文件程序时,应设置判断是否为PHP、ASP、ASPX以及在(3)中提到的扩展名的函数,如果函数返回Fasle则禁止上传。

    3. PHP CGI(Nginx)解析漏洞

    (1)漏洞介绍

    我们在Nginx环境下布置一个1.jpg文件,并用文本编辑器写入<?php echo "hello world"; ?>。通常情况而言,我们打开URL:http://127.0.0.1:80/1.jpg 显示为一张无法识别的图片,但是利用Nginx解析漏洞,我们打开URL:http://127.0.0.1:80/1.jpg/1.php (1.php是虚构、不存在的文件)时,却将文件1.jpg识别为一个php文件。


    (2)漏洞解析

    在PHP的配置文件中有一个选项:cgi.fix_pathinfo=True,在访问URL时,当Nginx服务器遇到1.php是不存在的文件时,便会向前遍历解析。

    如下图在php7.3.4版本中,cgi.fix_pathinfo默认是开启的。

    三、绕过上传漏洞

    使用Web应用中,很多场景都要使用文件上传。文件上传的流程为客户端使用JavaScript验证与服务器端采用随机数命名文件。因此在客户端利用JavaScript在文件未上传的时候就对文件进行验证,服务器端检测上传文件的MIME类型、检测文件扩展名是否合法、是否嵌入恶意代码。

    任何客户端验证都是不安全的。客户端验证是防止用户错误输入,减少服务器开销而已。

    1. 客户端检测

    下面通过对Upload.html中JavaScript源代码分析来突破客户端验证。

    <html>
    <head>
      <title>Pic Upload</title>
      <script type="text.javascript">
      		funtion checkFile(){
      			var flag=false;
      			var str=document.getElementById("file").value;
      			str=str.substring(str.lastIndexOf('.')+1);
      			var arr=new Array('png','bmp','gif','jpg'); 
      			for(var i=0;i<arr.length;i++){
      				if(str=arr[i]){
      					flag=true;
      				}
      			}
      			if(!flag)
      				alert('file invalid');
      			}
      			return flag;
      		}
      </script>
      </head>
      <body>
        <form action="upload.php" method="post" onsubmit=“ checkFile ”
              enctype="multpart/form-data">
          		<input type="file" name="file" id="file" /><br/>
         			<input type="submit" value="Submit" name="submit" />     
        </form>
      </body>
    </html>
    

    由源代码得知客户端JavaScript仅针对png,bmp,gif,jpg四种进行文件上传,那么攻击者就可以将文件名伪装成这些类型上传。

    (1)使用Firebug

    Firebug介绍:

    1. 是网页浏览器 Mozilla Firefox 下的一款开发类扩展,它集HTML查看和编辑、Javascript控制台、网络状况监视器于一体,是开发JavaScript、CSS、HTML和Ajax的得力助手。

    2. Firebug从各个不同的角度剖析Web页面内部的细节层面,给Web开发者带来很大的便利。

    3. Firebug也是一个除错工具。用户可以利用它除错、编辑、甚至删改任何网站的 CSS、HTMLDOM 以及JavaScript 代码。

    Firebug安装

    在Upload.html中单击Submit按钮,Form表单将会触发onsubmit时间从而调用checkFile()函数,通过检验扩展名是否合法从而允许文件是否可以上传至服务器。Firebug将onsubmit事件删除,因此所有类型的文件扩展名都可以绕过JavaScript函数checkfile()验证。

    (2)中间人攻击

    机制与(1)中的Firebug完全不同,中间人攻击在传输中的HTTP层做手脚。可以简单地理解为上传1.jpg文件通过JavaScript函数的验证,再使用抓包工具(Burp Suite)将文件名修改后缀为php。

    注意:HTTP请求头部Content-Length参数(实体正文长度),需要根据文件名长度的改动进行相应的修改。

    2. 服务器端检测

    服务器端验证主要包含白名单与黑名单扩展名过滤、文件类型检测、文件重命名等操作。如果将上传漏洞配合解析漏洞就可以绕过大多数上传验证。

    (1)白名单与黑名单验证

    黑名单过滤:定义一系列不安全的扩展名,在服务器端收到文件后匹对扩展名。

    <?php
    	$Blacklist = array('asp','php','jsp','php5','asa','aspx');#危险函数黑名单
    	if(isset($_POST["submit"])){
    		$name = $_FILES['file']['name'];
    		$extension = substr(strrchr($name, "."), 1);
    		$boo = false;
    		foreach($Blacklist as $key => $value) {
    			if ($value==$extension){
    				$boo = true;
    				break;
    			}
    		}
    		if($boo){
    			echo "file invalid";
    		}
    	}
    ?>
    

    黑名单过滤的缺点:

    1. 攻击者可以从黑名单中找到Web开发者忽略的扩展名
    2. 没有进行大小写转换,诸如.PHP扩展名不在黑名单里,依旧会被服务器接收
    3. windows系统下,如果文件名以"."或空格结尾会自动取出。asp.转化为asp

    白名单过滤:

    与黑名单过滤相反,白名单只允许已定义过的扩展名,比黑名单有更好的防御机制。

    <?php
    	$Whitelist = array('jpg','jpge','bmp','gif','png');#白名单允许函数
    	if(isset($_POST["submit"])){
    		$name = $_FILES['file']['name'];
    		$extension = substr(strrchr($name, "."), 1);
    		$boo = true;
    		foreach($Blacklist as $key => $value) {
    			if ($value==$extension){
    				$boo = false;
    				break;
    			}
    		}
    		if(!$boo){
    			echo "file invalid";
    		}
    	}
    ?>
    

    白名单过滤的缺点:

    白名单并不能完全防御上传漏洞。在IIS解析漏洞章节中,我们介绍过当文件名为*.asp;1.jpg时,白名单过滤机制识别文件扩展名为.jpg,即验证通过可以上传。但是在IIS解析漏洞中,此文件会被当做asp脚本程序来执行。

    (2)MIME验证

    MIMIE类型用来设定某种扩展名文件的打开方式。

    if($_FILES['file']['type']==" image/jpeg"){
    	$imageTempName=$_FILES['file']['tmp_name'];
    	$imageName=$_FILES['file']['name'];
    	$last=substr($imageName, strrpos($imageName,"."));
    	if(!is_dir("uploadFile")){
    		mkdir("uploadFile");
    	}
    	$imageName=md5($imageName).$last;
    	move_uploaded_file($imageName, "./uploadFile/".$imageName;
    	echo("Success");
    }else{
    	echo("Fail");
    	exit();
    }
    

    上传php文件时,我们使用抓包工具(Burp Suite)查看其MIME类型,可以发现php文件的MIME类型为application/php,无法通过验证。因此可以将Content-Type修改成image/jpeg类型,即可通过验证。

    (3)目录验证

    简介:在文件上传时,允许用户将文件放到指定的目录中,如果不存在指定目录,就会先创建目录再将文件放入。

    攻击手段:HTML代码中有一个隐藏标签<input type="hidden" name="Extension" value="up"/>,这是文件上传默认的文件夹,我们可以将参数value的值就可以达到目的。结合IIS解析漏洞(当建立*.asa*.asp格式的文件夹时,其目录下的任意文件都将被IIS当做asp文件来解析),就可以将恶意代码写入。

    (4)截断上传攻击

    此方法通常适用于ASP程序。

    //ASP代码
    <%
    username = request("username")
    Response.write username
    %>
    //将请求输入的username输出
    

    截断上传攻击指的是%00将后面的字符都截断,当我们上传文件名为1.asp x.jpg时,然后将空格的十六进制数20改成00,因此文件名为1.asp%00x.jpg,即符合截断上传攻击原型,最终将上传1.asp文件。

    四、文件编辑器上传漏洞

    (1)敏感信息暴露

    部分文本编辑器的文件目录存在一些敏感文件,将敏感信息直接暴露在攻击者前。

    (2)黑名单策略错误

    部分文本编辑器采用的是黑名单机制,基于上述黑名单策略的缺点,攻击者仍可以找到另外的危险脚本。

    (3)任意文件上传漏洞

    五、修复上传漏洞的策略

    文件上传漏洞产生的原因主要是:

    1. 目录过滤不严,攻击者可能建立畸形目录
    2. 文件未重命名,攻击者可能利用Web容器解析漏洞

    经过学习,设计如下代码可预防上述攻击。

    <?php
      if(!isset($_POST['submit'])){
        exit();
      }
      $arr = Array('jpg','gif','jpeg','png','rar','zip','doc'); //设置白名单
      $imageTempName=$_FILES['file']['temp_name'] //将文件放在临时路径,防止解析漏洞发生
      $imageName=$_FILES['file']['name'];
      $last=strtolower(substr($imageName, strrpos($imageName,'.')+1)); //获取文件扩展名并全部转换成小写
      if(!in_array($last,$arr)){
        exit('extension name invalid .$last ...'); //当扩展名不在白名单内,立即退出程序。
      }
    	$Extension=$_POST['Extension']; //确认扩展名安全方可获取文件上传目录
      $imageName = md5($imageName).".".$last; //对文件重命名,防止利用解析漏洞
      move_uploaded_file($imageTempName, "./$Extension/".$imageName);
      echo("Success!");
    }
    
    1. 接收文件将其存放在文件临时路径,即便存在解析漏洞也不能获取有效信息。
    2. 将扩展名与白名单对照,不符合的情况下直接退出程序。
    3. 对文件重命名方式诸如test.asp;1.jpg文件名绕过白名单却利用解析漏洞实施攻击。
  • 相关阅读:
    第五周总结
    第四周总结
    关于“模仿"和”创新“
    第三周总结
    第九周总结
    第八周总结
    第六周总结
    中国历史上成功的两人合作
    第五周总结
    第四周总结
  • 原文地址:https://www.cnblogs.com/implanck/p/12392074.html
Copyright © 2011-2022 走看看