upload-labs靶场 1-21通关

发布于:2025-03-07 ⋅ 阅读:(10) ⋅ 点赞:(0)

目录

1.Pass-01 前端绕过

分析

解题

2.Pass-02 服务器端检测--修改IMME

分析

解题

3.Pass-03 黑名单绕过

分析

解题

4.Pass-04 .htaccess绕过

分析

 解题

5.Pass-05 . .绕过和.user.ini绕过

分析

解题

6.Pass-06 大小写绕过

分析

解题

7.Pass-07 空格绕过

分析

解题

8.Pass-08 .绕过

分析

解题

9.Pass-09 ::$DATA绕过

分析

解题

10.Pass-10 . . 绕过

分析

解题

11.Pass-11 双写绕过

分析

解题

12.Pass-12 %00截断(GET)

分析

解题

13.Pass-13 %00截断(POST)

分析

解题

14.Pass-14 图片马1

分析

解题 

15.Pass-15 图片马2

分析 

解题

16.Pass-16 图片马3

分析

解题

17.Pass-17 二次渲染绕过

分析

解题

18.Pass-18 条件竞争

分析

解题

19.Pass-19  条件竞争2

分析

 解题

20.Pass-20 move_uploaded_file绕过

分析

解题

21.Pass-21 数组绕过

分析

解题


1.Pass-01 前端绕过

分析

选择一个php文件上传,页面立即弹出错误提示,且‌没有向服务器发送请求‌(通过浏览器开发者工具查看网络请求可确认)。

这种即时反馈表明验证逻辑是在客户端完成的,而非服务端

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;
    }
}

分析源码也可以发现,这里的关键是验证罗德由JS函数(checkFile())实现,且验证失败时会直接组织扁担提交到服务器

解题

  • 方法1

直接禁用js就可以上传了,以Google Chrome为例,设置-->隐私与安全-->网站设置-->javaScript-->不允许网站使用JS

上传成功。

  • 方法2

使用Burpsuit抓包修改后缀绕过

上传jpg文件-->点击上传Burpsuit抓包-->修改jpg后缀为php

上传成功

2.Pass-02 服务器端检测--修改IMME

分析

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        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.'文件夹不存在,请手工创建!';
    }
}

它是用file_exists()函数检查文件存在,并判断文件的类型是否为image/jpeg,image/gif,image/png,如果是,就会拼接文件路径

解题

上传php文件-->点击上传Burpsuit抓包-->修改Content-Type为代码允许的三个类型

上传成功

3.Pass-03 黑名单绕过

分析

​$deny_ext = array('.asp','.aspx','.php','.jsp');

其设置的后缀为黑名单,我们选择这四种后缀之外的文件就可以成功上传,比如php5

解题

上传成功

4.Pass-04 .htaccess绕过

分析

 $deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".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",".ini");

 该题代码与第三关几乎相同,仅仅在黑名单中多添加了一些后缀,但是它却少了.htaccess。如果Web应用允许上传.htaccess文件,并且.htaccess文件可以启用,那就意味着攻击者可以更改Apache的配置,对于受害者来说这种情况是十分危险的。
.htaccess文件攻击有三种方式:

1. 如果黑名单过滤了所有的能执行的后缀名,如果允许上传.htaccess。当.htaccess文件的内容如下,会将内容符合php语法规则的文件当作php文件解析

SetHandler application/x-httpd-php

2.  该文件还会匹配文件名中的关键字,如:[1.php.jpg]中包含.php,并且.htaccess文件的内容如下,[1.php.jpg]中的代码就会被执行

AddHandler php5-script .php

3.  匹配文件名,当.htaccess文件内容如下,它可以将匹配到的文件名的文件中的代码执行

<FilesMatch "sxc">
    SetHandler application/x-httpd-php
</FilesMatch>

 解题

直接编写htaccess文件

<FilesMatch "web.jpg">
  SetHandler application/x-httpd-php
</FilesMatch>

然后上传一个web.jpg文件,然后上传这个.htaccess,再访问web.jpg,即可通关。

5.Pass-05 . .绕过和.user.ini绕过

分析

$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");

源码里把所有可以解析的后缀名都给写死了,包括大小写,转换,空格,还有点号,正常的php类文件上传不了了,并且拒绝上传 .htaccess 文件。但是没有被限制的后缀名还有.php7和.ini

php.ini 是 php的配置文件,.user.ini 中的字段也会被 php 视为配置文件来处理,从而导致 php 的文件解析漏洞。

但是想要引发 .user.ini 解析漏洞需要三个前提条件

服务器脚本语言为PHP  

服务器使用CGI/FastCGI模式  

上传目录下要有可执行的php文件

  什么是 CGI
       CGI 的全称为“通用网关接口”(Common Gateway Interface),为 HTTP 服务器与其他机器上的程序服务通信交流的一种工具, CGI 程序须运行在网络服务器上。
   
       传统 CGI 接口方式的主要缺点是性能较差,因为每次 HTTP 服务器遇到动态程序时都需要重新启动解析器来执行解析,之后结果才会被返回给 HTTP
       服务器。这在处理高并发访问时几乎是不可用的,因此就诞生了 FastCGI。另外,传统的 CGI 接口方式安全性也很差,故而现在已经很少被使用了。
   
       什么是 FastCGI
       FastCGI 是一个可伸缩地、高速地在 HTTP 服务器和动态服务脚本语言间通信的接口(在 Linux 下, FastCGI 接口即为 socket,这个socket 可以是文件 socket,也可以是IP socket),主要优点是把动态语言和 HTTP
   服务器分离开来。多数流行的 HTTP 服务器都支持 FastCGI,包括 Apache 、 Nginx 和 Lighttpd 等。

解题

  • 方法1 .user.ini绕过

创建一个文件名为 .user.ini  内容为

auto_prepend_file=web.jpg

 上传web.jpg文件和.user.ini文件到upload目录下之后访问readme.php就可以执行web.jpg中的php代码

  • 方法2 . .绕过
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $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;

如果我们上传web.php. .,可以看见$file_name处理后值为web.php. (这里有一个空格),而$file_ext值为.

最终的文件路径拼接的时候应该是web.php. 最后的空格和.会因为windows系统的特性自动过滤掉,成为web.php

绕过成功

6.Pass-06 大小写绕过

分析

$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",".ini");
$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); //首尾去空

可以发现,这里黑名单过滤了极多的部分,包括.htaccess .ini以及之前用到的php5等。仔细查看源码发现,其没有进行大小写的过滤。所以可以通过大小写进行绕过。

解题

直接上传web.PHP即可

上传成功

7.Pass-07 空格绕过

分析

        $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",".ini");
        $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

 仔细观察代码中部可以发现,其忽略了空格存在的情况,所以我们可以使用空格绕过的方式

解题

上传web.php进行抓包,然后在其后缀处加上一个空格

上传成功

8.Pass-08 .绕过

分析

        $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",".ini");
        $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); //首尾去空

 观察源代码,发现其没有删除文件名中小数点的函数

解题

上传web.php进行抓包,然后在其后缀处加上一个.

上传成功

9.Pass-09 ::$DATA绕过

分析

        $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",".ini");
        $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); //首尾去空

  观察源代码,发现其没有过滤::$DATA

解题

上传web.php进行抓包,然后在其后缀处加上一个::$DATA

上传成功

10.Pass-10 . . 绕过

分析

这关跟第五关是一样的,通过代码分析可以推断,我们可以使用. .绕过的方法达到上传php文件的目的。

解题

上传成功

11.Pass-11 双写绕过

分析

 $file_name = trim($_FILES['upload_file']['name']);
        $file_name = str_ireplace($deny_ext,"", $file_name);
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = UPLOAD_PATH.'/'.$file_name;        

先使用trim函数去除其两边的空白字符以及转义字符,再使用str_ireplace,将$file_name的字符串与$deny_ext中的黑名单对比,如果有相同的,则从$file_name中删除对应部分,通常这种情况的过滤,可以使用双写对应的字符,使其删除一次后恢复为正确的文件后缀进行绕过。

解题

上传web.pphphp文件

上传成功

12.Pass-12 %00截断(GET)

分析

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;

通过观察函数可以发现,我们的上传路径是可控的(通过GET方式传参),所以我们想到可以使用%00截断的方法  

%00是字符串的结束标识符,攻击者可以利用手动添加字符串标识符的方式来将后面的内容进行截断

只有数据包中必须含有上传路径的情况下才可以用,那么攻击者可以通过修改path的值来构造paylod,并且php<5.3.29并且magic_quotes_gpc是关闭的

解题

上传info.jpg,然后抓包截断。路径处加上info.php%00

上传成功

13.Pass-13 %00截断(POST)

分析

这里和上一关区别只是一个为POST一个为GET方法,在GET请求中会对输入的内容进行URL解码。但POST请求有不同, 需要我们将POST中的%00解码后传入。

解题

上传info.jpg,然后抓包截断。路径处加上web (这里有个空格),选中空格,改变他的16进制为00

上传成功

14.Pass-14 图片马1

分析

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 = '';    

 getReailFileType这个函数是用于检测文件头部两个字节的信息(前两个字节是文件格式的标识),并且通过二进制码判断其文件的类型,然后控制文件的上传。

由于其要检测前两个字节的信息,所以不能简单的通过直接修改后缀进行上传。需要制作图片马,采用图片与木马合并的方法

windows下通过cmd命令进行制作

copy 1.jpg /b + 2.php /a 3.php

解题 

首先制作一张图片马web.php,我们将其上传。但是由于图片不能解析为php代码来执行。若有文件包含漏洞,则可以通过文件包含漏洞进行解析。好由于题目说了存在文件包含漏洞,我们通过文件包含漏洞进行。 我们复制图片地址,链接到文件包含界面,然后访问。

    上传成功

    15.Pass-15 图片马2

    分析 

    本关与上一关类似,只是判断文件的函数方法略有区别,也可以通过图片马进行访问。

    解题

    上传成功

    16.Pass-16 图片马3

    分析

    根据要求首先开启php_exif模块, 这关和之前两个也类似,仅仅是使用函数变化,原理相同

    解题

    上传成功

    17.Pass-17 二次渲染绕过

    分析

    if(($fileext == "jpg") && ($filetype=="image/jpeg")){
            if(move_uploaded_file($tmpname,$target_path)){
                //使用上传的图片生成新的图片
                $im = imagecreatefromjpeg($target_path);
    
                if($im == false){
                    $msg = "该文件不是jpg格式的图片!";
                    @unlink($target_path);
                }else{
                    //给新图片指定文件名
                    srand(time());
                    $newfilename = strval(rand()).".jpg";
                    //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                    $img_path = UPLOAD_PATH.'/'.$newfilename;
                    imagejpeg($im,$img_path);
                    @unlink($target_path);
                    $is_upload = true;
                }
            } else {
                $msg = "上传出错!";
            }

    以jpg的函数为例,代码先通过检查上传文件的后缀,然后用$im = imagecreatefromjpeg语句将上传的图片传给$im作为一个图片标志符,再经过srand函数重新命名后,利用imagejpeg函数将$im的图像保存到指定路径处。相当于对文件的图像部分进行了重新生成,并且使用unlink函数将原图片删除。

    所以说如果我们上传一个图片马的话,经过这个函数的重新生成得到的图片会是一堆乱码,不在包含我们的php语句。

    但是jpg、png、gif文件在重新生成后与原图片相比是否存在不变的部分呢?下面以gif图片为例解题,这里使用gif文件比jpg和png文件更加简单。

    解题

    先生成一个gif的图片马

    将web.gif上传,把重新生成的图片保存下来,利用010editor将渲染前后的图片对比,将web.gif未改变的部分加入php语句

    上传成功

    18.Pass-18 条件竞争

    分析

    $is_upload = false;
    $msg = null;
    
    if(isset($_POST['submit'])){
        $ext_arr = array('jpg','png','gif');
        $file_name = $_FILES['upload_file']['name']; 
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $file_ext = substr($file_name,strrpos($file_name,".")+1);
        $upload_file = UPLOAD_PATH . '/' . $file_name;
    
        if(move_uploaded_file($temp_file, $upload_file)){
            if(in_array($file_ext,$ext_arr)){
                 $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
                 rename($upload_file, $img_path);
                 $is_upload = true;
            }else{
                $msg = "只允许上传.jpg|.png|.gif类型文件!";
                unlink($upload_file);
            }
        }else{
            $msg = '上传出错!';
        }
    }

     这个代码的文件处理流程是:移动文件到指定路径-->判断后缀名是否符合-->符合则重命名-->不符合则删除文件。

    这里存在逻辑的问题那就是先上传后删除,服务器处理代码时总会存在一定的时间差,当我们在上传文件后就多次快速尝试访问目标文件,那么是不是有机会在删除前成功访问文件。 而如果文件的代码是重新创建一个木马文件,新木马文件则永远不会被删除了!

    解题

    创建一个木马文件demo.php

    <?php fputs(fopen('web.php','w'),'<?php phpinfo(); ?>');?> 

    上传这个demo.php并抓包,然后发送到intruder模块,设置pyload和不间断发包

    设置好后开始attack 并访问127.0.0.1/upload/demo.php 我等待上几秒就成功了

    19.Pass-19  条件竞争2

    分析

    这关我们通过对源码断点调试来分析源码,在index.php中,首先new了一个MyUpload类,传入了上传的文件名,临时名,文件大小,随机time名(这个随机time和文件最终名字有关)。然后传入UPLOAD_PATH给upload函数(也就是把../upload传入)。

    然后我们看看MyUpload函数,对类初始化的时候调用Myupload函数,传入对应参数赋值,进入里面看看,在upload函数中,是先进行文件路径、后缀、大小判断,然后文件移动、重命名。

    这就出现了逻辑问题,先移动后重命名

        $ret = $this->move();
        if( $ret != 1 ){
          return $this->resultUpload( $ret );    
        }
    
        // check if we need to rename the file
    
        if( $this->cls_rename_file == 1 ){
          $ret = $this->renameFile();
          if( $ret != 1 ){
            return $this->resultUpload( $ret );    
          }
        }
        

     解题

    还是一样,先做图片马web.jpg

    copy 1.jpg /b + demo.php /a web.jpg
    
    
    <?php fputs(fopen('web.php','w'),'<?php phpinfo(); ?>');?> 

    上传,复制图片地址并访问

    然后访问 

    http://127.0.0.1/upload/web.php

     上传成功

    20.Pass-20 move_uploaded_file绕过

    分析

            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 = '禁止保存为该类型文件!';
            }
    

    move_uploaded_file()还有这么一个特性,会忽略掉文件末尾的 /.

    解题

    方法一

    上传一个jpg图片,里面内容为php语句,然后抓包修改,在save_name处的内容上加上/.

    方法二

     同样可以使用大小写绕过,修改位置跟方法一的位置相同

    上传成功

    21.Pass-21 数组绕过

    分析

    $is_upload = false;
    $msg = null;
    if(!empty($_FILES['upload_file'])){
        //检查MIME
        $allow_type = array('image/jpeg','image/png','image/gif');
        if(!in_array($_FILES['upload_file']['type'],$allow_type)){
            $msg = "禁止上传该类型文件!";
        }else{
            //检查文件名
            $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
            if (!is_array($file)) {
                $file = explode('.', strtolower($file));
            }
    
            $ext = end($file);   //文件后缀
            $allow_suffix = array('jpg','png','gif');
            if (!in_array($ext, $allow_suffix)) {
                $msg = "禁止上传该后缀文件!";
            }else{
                $file_name = reset($file) . '.' . $file[count($file) - 1];
                $temp_file = $_FILES['upload_file']['tmp_name'];
                $img_path = UPLOAD_PATH . '/' .$file_name;
                if (move_uploaded_file($temp_file, $img_path)) {
                    $msg = "文件上传成功!";
                    $is_upload = true;
                } else {
                    $msg = "文件上传失败!";
                }
            }
        }
    }else{
        $msg = "请选择要上传的文件!";
    }

    首先检查upload_file如果不为空,则继续检查MIME类型是否是白名单里的

    然后如果save_name为空,则把$_FILES['upload_file']['name']的值给$file,不为空则把$_POST['save_name']的值给$file

    接下来如果$file不是数组,explode函数则将其处理为数组,用.分割

    然后继续通过end函数获得$file中的最后一个元素,赋值给$ext,并进行后缀校验。如果后缀符合,则拼接文件名为首元素.尾元素。reset函数来获取首元素

    解题

    上传web.php,抓包

    要修改三个部分 

    1. MIME类型
    2. save_name后加上数组,保存名称改为php后缀
    3. 再加入一个save_name[2]绕过尾元素

    上传成功