服务器端应用安全——文件上传漏洞

攻击者上传一个可执行脚本文件,并通过该脚本获得了执行服务器命令的能力。

按照上传文件类型分类:

  1. web脚本文件
  2. Flash策略文件
  3. 病毒、木马
  4. 钓鱼图片或包含脚本的图片

攻击者成功上传,并且被用户执行,才能称之为攻击成功。

一般服务器均对上传文件的格式有检查,以下总结常见绕过文件类型检查的方法:
校验方法:

  1. 客户端校验
    一般都是在网页上写一段javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>新建网页 1</title>
</head>
<body>
<form method="POST" enctype="multipart/form-data"  onsubmit ="return check()"  name ="frm" action="index2.htm" >
 <p><input type="file" name="F1" size="20"><input type="submit"  value="提交" name="B1"><input type="reset" value="重置" name="B2"></p>
</form>
<script type ="text/javascript">
//核心代码,检验上传文件格式
function check()
{
    var filename = frm.F1.value  ;
    filename = filename.substring(filename.lastIndexOf("\\")+1,filename.length);
    var patrn=/^.*.htm$/ig;
    alert(filename);
  
    if(!patrn.test(filename))
    {
        alert(patrn.test(filename));
        return false;
    }
         return true;
 }
</script>
</body>
</html>

当上传文件类型为html时,客户端通过文件类型验证
服务器端应用安全——文件上传漏洞_第1张图片服务器端应用安全——文件上传漏洞_第2张图片
否则,不通过验证:
服务器端应用安全——文件上传漏洞_第3张图片
2. 服务端校验
2.1content-type字段校验:
可以用一段php代码实现

if($_FILES['userfile']['type'] != "image/gif")

例子:
首先写一个上传文件的页面upload.php,并将用户选择的文件送到处理文件upload_server.php.
upload.php代码如下:

<!DOCTYPE html>
<html>
<head>
	<title>文件上传</title>
	<meta charset="utf-8">
</head>
<body>
	<center>
		<!-- enctype="mulipart/form-data"属性是指以二进制方式进行数据传输 
		传输文件需要设置-->
		<form action="upload_server.php" method="post" enctype="multipart/form-data">
		<input type="hidden" name="max_file_size" value="1048576">
		<input type="file" name="file">
		<input type="submit" name="上传">		
	</form>
	</center>
	
</body>
</html>

upload_server.php代码:

 
	header("content-type:text/html;charset=utf-8");
	//设置时区
	date_default_timezone_set('PRC');
	//获取文件名
	$filename = $_FILES['file']['name'];
	//获取文件临时路径
	$temp_name = $_FILES['file']['tmp_name'];
	//获取大小
	$size = $_FILES['file']['size'];
	//获取文件上传码,0代表文件上传成功
	$error = $_FILES['file']['error'];
//echo "$error";echo ("OK!!!");
	//判断文件大小是否超过设置的最大上传限制
	if ($size > 2*1024*1024){
		//
		echo "";
		exit();
	}
	//phpinfo函数会以数组的形式返回关于文件路径的信息 
	//[dirname]:目录路径[basename]:文件名[extension]:文件后缀名[filename]:不包含后缀的文件名
	$arr = pathinfo($filename);
	//获取文件的后缀名
	$ext_suffix = $arr['extension'];
	//设置允许上传文件的后缀
	$allow_suffix = array('jpg','gif','jpeg','png');
	//判断上传的文件是否在允许的范围内(后缀)==>白名单判断
	if(!in_array($ext_suffix, $allow_suffix)){
		//window.history.go(-1)表示返回上一页并刷新页面
		echo "";
		exit();
	}
	//检测存放上传文件的路径是否存在,如果不存在则新建目录
	if (!file_exists('uploads')){
		mkdir('uploads');
	}
	//为上传的文件新起一个名字,保证更加安全
	$new_filename = date('YmdHis',time()).rand(100,1000).'.'.$ext_suffix;
//	echo "$_FILES['file']['error']";
	//将文件从临时路径移动到磁盘
	if ($error==0 || move_uploaded_file($temp_name, 'uploads/'.$new_filename)){
		echo "";
	}else{
		echo "";
	}

 ?>

当选择的文件是jpg,gif,jpeg,png格式时,允许上传。

服务器端应用安全——文件上传漏洞_第4张图片
否则,上传失败:
服务器端应用安全——文件上传漏洞_第5张图片
2.2 文件头校验
通过正则匹配,判断文件头内容是否符合要求

Apache漏洞利用:

apache对文件后缀名的识别是从后向前进行匹配的,以单个.作为分隔符。当遇到未知的文件后缀名时,会继续向前匹配,直到遇到可以识别的后缀名为止。
apache的这个特性,可以被用来绕过一些上传文件的检测。如果一个文件上传的页面,通过黑名单的方式禁止上传php文件,那么我们就可以将文件名修改为test.php.abcd的方式进行上传。最后请求test.php.abcd时,和请求test.php的效果是一样的,这样就成功绕过了文件后缀名的检测上传了一个php文件。

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
常见设置:
服务器端应用安全——文件上传漏洞_第6张图片
IIS 6文件解析问题:

曾经出现过的漏洞,主要原因有两个:一是在识别文件类型时,将;作为截断符,从而导致的一系列安全问题;而是在处理文件夹拓展名时,将该文件夹下的文件类型认为同文件夹类型一致,比如:localhost/UpLfile.asp/test.php,会将test文件类型认为是asp!!

文件上传漏洞的主要原因为,攻击者上传了服务器禁止的可执行文件,并且绕过了服务器的文件类型检查,从而在服务器上执行恶意代码。

设计安全的文件上传功能:

  • 文件上传的目录设置为不可执行
    将存储用户上传文件的目录设置为不可知性,这样用户即使成功上传了可执行文件,仍然得不到执行的机会。
    另外,这样做的好处也可以用来缓存加速。
  • 判断文件类型
    mime type以及文件类型检查等方式,尽可能使用白名单而非黑名单。
  • 使用随机数改写文件名和文件路径
    即使攻击者成功上传,但由于修改了文件名,所以攻击者的攻击成本大大提升。如上面upload_server.php的做法。
  • 单独设置文件服务器域名
    利用同源策略,类似于第一种方法,将数据与代码分离开来。

你可能感兴趣的:(笔记)