攻击者上传一个可执行脚本文件,并通过该脚本获得了执行服务器命令的能力。
按照上传文件类型分类:
攻击者成功上传,并且被用户执行,才能称之为攻击成功。
一般服务器均对上传文件的格式有检查,以下总结常见绕过文件类型检查的方法:
校验方法:
<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时,客户端通过文件类型验证
否则,不通过验证:
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格式时,允许上传。
否则,上传失败:
2.2 文件头校验
通过正则匹配,判断文件头内容是否符合要求
Apache漏洞利用:
apache对文件后缀名的识别是从后向前进行匹配的,以单个.作为分隔符。当遇到未知的文件后缀名时,会继续向前匹配,直到遇到可以识别的后缀名为止。
apache的这个特性,可以被用来绕过一些上传文件的检测。如果一个文件上传的页面,通过黑名单的方式禁止上传php文件,那么我们就可以将文件名修改为test.php.abcd的方式进行上传。最后请求test.php.abcd时,和请求test.php的效果是一样的,这样就成功绕过了文件后缀名的检测上传了一个php文件。
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
常见设置:
IIS 6文件解析问题:
曾经出现过的漏洞,主要原因有两个:一是在识别文件类型时,将;作为截断符,从而导致的一系列安全问题;而是在处理文件夹拓展名时,将该文件夹下的文件类型认为同文件夹类型一致,比如:localhost/UpLfile.asp/test.php,会将test文件类型认为是asp!!