现代互联网的web应用程序中,文件上传是一种常见的要求,因为它有助于一高业务效率。在大型社交网络程序中都支持文件上传功能。在博客,论坛,电子银行网络,会给用户和企业员工有效的共享文件。允许上传图片,视频,头像和许多其他类型文件。
漏洞成因:
上传文件的时候,如果服务器端脚本语言,未对上传的文件进行严格的验证和过滤,就有可能上传恶意的脚本文件,从而控制整个网站,甚至是服务器。
漏洞具体分类:
未过滤或Web前段过滤被绕过
文件内容检测被绕过
中间件解析
不完善的黑名单扩展名
文件路径截断
HTTP不安全方法(PUT协议)
漏洞具体分析:
1.未过滤或Web前端过滤被绕过:
未过滤是指当前上传点未对文件格式做限制,随意上传恶意代码;前端绕过是指当前页在JS代码中对上传文件做尾缀的限制,通过firebug修改当前JS代码即可绕过。
2.文件内容检测被绕过:
检测方法:检测CONTENT-TYPE内容(判断是否为特定数据类型);检测和path相关内容;检测文件扩展功能相关内容;检测是否含有恶意代码
绕过:通过向代码文件头添加上传默认数据类型的头文件代码来绕过mime类型检测;通过向图片16进制空白区插入恶意代码,突破内容检测。
3.中间件解析:
利用当前服务器中间件版本的解析文件的顺序和方法等特点上传带特殊符号作为文件名的文件。
apache--<2.2.14------1.php.jpg jpg尾缀在上传过程中会被忽略掉----1.php
apache-->2.2.15-------1.php.1 1尾缀在上传过程中会被忽略掉--------1.php
iis6 -----------1.php;jpg ;号后的东西会在上传后被忽略掉 -------1.php
iis6 在asp为脚本语言的网站目录下如果存在一个叫asp的文件夹则,次文件夹下的所有文件都会在访问时被以asp代码执行。
4.不完善的黑名单的扩展:
许多网站虽然在后台代码中对文件的扩展名进行了过滤但是并不全面,有一些特别的文件脚本后缀依然可以执行
.php2 .php3 .php5 .phtml .aspx .ascx .ashx .cer .jspx
5.文件路径截断
00截断
网站上传函数处理xxx.php .jpg 时,首先.jpg是合法的可以上传值网站目录,但是系统在保存文件时,遇到" "字符则丢弃后面的jpg 最后在网站目录下以xxx.php保存
6.HTTP不安全方法:
当服务器配置不当时,在不需要的上传页面的情况下导致任意文件上传(PUT协议)
漏洞挖掘和利用:
查找上传点,图片,头像,附件;目录,文件扫描发现类似upload,php等文件,编译器目录如ewebeditor,fckeditor,kingeditor等
如果是编辑器上传功能则google查看编辑器版本并查找利用方法。
如果是自写的,先上传一个正常的jpg图片 查看功能是否正常;上传jpg图片,该数据包将尾缀改为php 能否正常上传(检测文件内容的验证是否存在,后缀检测是否存在);上上传jpg文件 00截断 1.php .jpg ;检测服务器所有配置信息利用解析漏洞。
实例:00截断突破上传
shell.asp内写的是webshell 用点分割尾缀利用了iis6的特性
抓包 将路径上传后的文件改为如下的尾缀
在hex下找到刚才添加的空格(20)
更改为00
文件成功上传并以.asp保存
执行webshell GID89A 是为了突破对内容头的检测,这是gif文件的头格式。
修复方案:
上传文件的存储目录禁用执行权限
文件的后缀白名单,注意0x00截断攻击
不能有本地文件包含漏洞
及时修复web上的代码
升级web server
修复代码:
<?php
function getExt ($filename) {
return substr ($filename,strripos($filename,'.')+1); //substr()函数返回字符串的一部分,strripos() 函数查找字符串从左到右在另一字符串中最后一次出现的位置
}
$disallowed_types = array('jpg','png','gif');
$FilenameExt = strtolower(getExt($_FILES["file"]["name"])); //获取文件扩展名strtolower()将扩展名字符转换小写
//判断是否在允许的扩展名里
if (!in_array($FilenameExt, $disallowed_types)) { //如果获取文件扩展名不在白名单数组里,则返回disallowed type。
die("disallowed type");
}
else {
//文件名用time()函数获得10进制时间戳命名,在1-10000之间随机一个常数,防止同一秒不同用户上传文件重复,并最终用md5函数生成哈希散列命名文件。
$filename = md5(time()+rand (1,10000)).".".$FilenameExt;
move_uploaded_file ($_FILES["upfile"]["tmp_name"], "upload/" . $filename);
echo '文件上传成功,保存于:upload/' . $filename . "\n";
}
?>