文件上传之绕过
一般防止上传漏洞手法:
1、客户端检测:客户端使用JavaScript检测,在文件未上传时,就对文件进行验证
//任何客户端的验证都是不安全的,客户端验证目的是防止用户输入错误、减少
//服务器开销,而服务端验证才可以真正防御攻击者。
2、服务器端检测:服务端脚本一般会检测文件的MIME类型,检测文件扩展名是否合法
客户端检测
客户端验证代码形如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<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>
<form action="upload.php" method="post" onsubmit="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(date('Y-m-d h:m:s')).strrchr($name,".");
$size = $_FILES['file']['size'];
$tmp = $_FILES['file']['tem_name'];
move_uploaded_file($tmp,$name);
echo "文件上传成功!path:".$name;
}
?>
绕过:
服务端检测
- 黑名单与白名单验证
- MIME验证
- 目录验证
- 截断上传攻击
- .htaccess文件攻击
- 检测文件内容
黑名单与白名单验证
黑名单过滤方式
<?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($Blaklist as $key => $value)
{
if($value==$extension)
{
//迭代判断是否命中
$boo = true;
break; //命中后直接退出循环
}
}
if(!$boo)
{
//若没有被命中,则进行上传操作
$size = $_FILES['file']['size']; //接收文件大小
$tmp = $FILES['file']['temp_name']; //临时路径
move_uploaded_file($tmp, $name); //移动临时文件到当前文件目录
}
else
{
echo "文件不合法!!";
}
}
?>
- 从黑名单中找到web开发者忽略的扩展名,如:cer
- 没有对扩展名进行大小写转换,在window平台依然可以大小写绕过
- 在window下,若文件名以"."或者空格作为结尾,系统会自动去除"."与空格,
所以可以上传以“asp.”和“asp_”为扩展名的文件 - 0x00截断绕过
- 解析漏洞
白名单过滤方式
<?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_uploaded_file($tmp,$name);
echo "文件上传成功!<br/>path:".$name;
}
else
{
echo "文件不合法!";
}
}
?>
- 0x00截断绕过
- 此时若在iis6.0,则可以将木马名改为test.asp;1.jpg来上传,从而通过验证
- 配合解析漏洞
MIME验证
对文件MIME类型做验证的PHP代码如下:
<?php
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_upload_file($imageTempName,"./uploadFile/".$imageName);
echo("文件上传成功! path = /uploadFile/$imageName");
}
else
{
echo("文件上传类型错误,请重新上传...");
exit();
}
?>
修改MIME类型,上传成功:
目录验证
<html>
<head>
<meta charset="UTF-8">
<title>up</title>
</head>
<body>
<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>
</body>
</html>
<?php
if($_FILES['file']['type']=="image/jpeg")
{
$imageTempName=$_FILES['file']['tmp_name'];
$imageName=$_FILES['file']['name'];
$last=substr($imageName,strrpos($imageName,"."));
if($last!=".jpg")
{
echo("mime error!<br/>");
}
$Extension=$_POST['Extension'];
if(!is_dir($Extension))
{
mkdir("./$Extension");
echo "mkidr $Extension succesfully"."<br/>";
}
$imageName=md5($imageName).$last;
move_uploaded_file($imageTempName,"./$Extension/".$imageName);
echo("upload ok! path = /$Extension/$imageName");
}
else
{
echo("type error...");
exit();
}
?>
将文件改名:
截断上传攻击
截断上传攻击在ASP程序中比较常见(在PHP、JSP中也有)
更改图片名字:
.htaccess文件攻击
通过.htaccess文件调用php解析器去解析一个文件名中只要包含"haha"这个字符串的任意文件,论扩展名是什么(没有也行),都以php的方式来解析,.haccess文件代码如下
<FilesMatch "haha">
SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch "evil.gif">
SetHandler application/x-httpd-php
</FilesMatch>
检测文件内容
文件幻数检测在文件首部加上如下幻数,后面跟一句话木马即可
JFIF FF D8 FF E0 00 10 4A 46 49 46
GIF89a 47 49 46 38 39 61
PNG 89 50 4E 47
GIF89a
(...some binary data for image...)
<?php phpinfo(); ?>
(... skipping the rest of binary data ...)
文件加载检测
对渲染/加载测试的攻击方式是代码注入绕过
对二次渲染的攻击方式是攻击文件加载器本身
补充
绕过技巧
1 使用大小写绕过(针对对大小写不敏感的系统如windows),如:PhP
2 使用黑名单外的脚本类型,如:php5
3 借助文件解析漏洞突破扩展名验证,如:test.jpg.xxx(apache解析漏洞)
4 借助系统特性突破扩展名验证,如:test.php_(在windows下下划线是空格,保存文件时下划线被吃掉剩下test.php)
5 双扩展名之间使用00截断,绕过验证上传恶意代码如:test.php%00.jpg
6 借助.htaccess文件上传恶意代码并解析。如:上传一个.htaccess文件,内容为AddTypeapplication/x-httpd-php .jpg,上传的jpg文件就可以当作php来解析
7 使用00截断,绕过后缀验证获取webshell(php<5.3.4+关闭GPC)
8 超长文件名截断上传(windows 258byte | linux 4096byte)
安全建议
1 使用白名单限制可以上传的文件扩展
2 验证文件内容,使用正则匹配恶意代码限制上传
3 对上传后的文件统一随机命名,不允许用户控制扩展名
4 修复服务器可能存在的解析漏洞
5 严格限制可以修改服务器配置的文件上传如:.htaccess