upload-labs 0.1 靶机详解

下载地址
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更改为数组形式,更改文件类型

可以看到成功上传

成功访问

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Hack The Box-Monitored

目录 信息收集 rustscan dirsearch WEB web信息收集 snmpwalk curl POST身份验证 漏洞探索 漏洞挖掘 sqlmap 登录后台 提权 get user get root 信息收集 rustscan ┌──(root㉿ru)-[~/kali/hackthebox] └─# rustscan -b 2250 10.10.11.248 --range0-65535 --…

Hadoop大数据应用:Yarn 节点实现扩容与缩容

目录 一、实验 1.环境 2.Yarn 节点扩容 3.Yarn 节点缩容 二、问题 1.yarn启动服务报错 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 主机架构软件版本IP备注hadoop NameNode &#xff08;已部署&#xff09; SecondaryNameNode &#xff08;已部署&…

宋仕强论道之华强北背包客(三十九)

华强北汹涌的人流&#xff0c;主要是在华强北经营的商户和来华强北的客户&#xff0c;还包括华强北的背包客&#xff0c;背包客是华强北的特殊群体&#xff0c;来自于全国各地甚至于世界各地&#xff0c;国外的背包客也是华强北国际化的主要渠道。一个是国内的背包客的渠道&…

分类预测 | Matlab实现GSWOA-KELM混合策略改进的鲸鱼优化算法优化核极限学习机的数据分类预测

分类预测 | Matlab实现GSWOA-KELM混合策略改进的鲸鱼优化算法优化核极限学习机的数据分类预测 目录 分类预测 | Matlab实现GSWOA-KELM混合策略改进的鲸鱼优化算法优化核极限学习机的数据分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GSWOA-KELM分类&#xff0…

Java项目实战记录:雷达数据解析

Java项目实战记录&#xff1a;雷达数据解析 背景介绍 最近公司接了一个雷达相关的系统开发项目&#xff0c;雷达数据会由C程序进行二次处理存放到指定文件夹中&#xff0c;我这边使用Java程序去文件夹下读取这些雷达产品&#xff0c;进行解析并将数据传递到前台&#xff0c;由…

【吊打面试官系列】Java虚拟机JVM篇 - 关于JVM 新生代、老年代、永久代的区别

大家好&#xff0c;我是锋哥。今天分享关于JVM新生代、老年代、永久代的区别的JVM面试题&#xff0c;希望对大家有帮助&#xff1b; JVM 新生代、老年代、永久代的区别? 在 Java 中&#xff0c;堆被划分成两个不同的区域&#xff1a;新生代 ( Young ) 、老年代 ( Old ) 。而新…

【学习记录】调试千寻服务+DTU+导远RTK过程的记录

最近调试车载定位的时候&#xff0c;遇到了一些问题&#xff0c;千寻服务已经正确配置到RTK里面了&#xff0c;但是导远的定位设备一直显示RTK浮动解&#xff0c;通过千寻服务后台查看状态&#xff0c;长时间显示不合法的GGA值。 首先&#xff0c;通过四处查资料&#xff0c;千…

ThingsBoard 开源物联网平台

文章目录 1.ThingsBoard 介绍2.ThingsBoard 架构2.1.单体架构2.2.微服务架构 3.物联网网关4.边缘计算 ThingsBoard # ThingsBoardhttps://iothub.org.cn/docs/iot/ https://iothub.org.cn/docs/iot/thingsboard-ce/1.ThingsBoard 介绍 ThingsBoard 是一个开源物联网平台&…

【Claude 3】关于注册Claude 3模型的操作演示

文章目录 1. 登录Claude URL2. 海外手机号码验证3. 获取手机验证码4. 输入Claude用户名称5. 同意确认使用协议6. 点击去开始体验7. 注册登录成功8. 重新登录进入Claude9. 参考链接PS&#xff1a;所遇问题&#xff1a;⚠️注册即封号&#xff01;&#xff01;&#xff01; 1. 登…

代码随想录刷题笔记 Day 51 | 单词拆分 No.139 | 多重背包理论基础

文章目录 Day 5101. 单词拆分&#xff08;No. 139&#xff09;<1> 题目<2> 笔记<3> 代码 02. 多重背包理论基础2.1 解题思路2.2 携带矿石资源&#xff08;卡码网No.56&#xff09;<1> 题目<2> 笔记<3> 代码 Day 51 01. 单词拆分&#xff…

Python·算法·每日一题(3月15日)合并两个有序链表

题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&am…

如何正确地设置Outlook SMTP发送电子邮件?

Outlook SMTP发送邮件配置方法&#xff1f;Outlook怎么开启SMTP&#xff1f; 在使用Outlook发送邮件时&#xff0c;正确设置SMTP服务器是确保邮件能够顺利发送的关键步骤。接下来&#xff0c;就让AokSend一起探讨如何正确地设置Outlook SMTP发送电子邮件吧&#xff01; Outlo…

【Redis】Redis常用命令之Hash

1.hset&#xff1a;设置hash中指定的字段&#xff08;field&#xff09;的值&#xff08;value&#xff09;。 HSET key field value [field value ...]时间复杂度&#xff1a;插⼊⼀组field为O(1),插⼊N组field为O(N)。 返回值&#xff1a;添加的字段的个数。 2.hget&#xf…

vscode 导入前端项目

vscode 导入前端项目 导入安装依赖 运行 参考vscode 下载 导入 安装依赖 运行 在前端项目的终端中输入npm run serve

【洛谷 P8637】[蓝桥杯 2016 省 B] 交换瓶子 题解(贪心算法)

[蓝桥杯 2016 省 B] 交换瓶子 题目描述 有 N N N 个瓶子&#xff0c;编号 1 ∼ N 1 \sim N 1∼N&#xff0c;放在架子上。 比如有 5 5 5 个瓶子&#xff1a; 2 , 1 , 3 , 5 , 4 2,1,3,5,4 2,1,3,5,4 要求每次拿起 2 2 2 个瓶子&#xff0c;交换它们的位置。 经过若干次…

Springboot的配置文件及其优先级

配置文件 内置配置文件 配置文件的作用&#xff1a;修改SpringBoot自动配置的默认值&#xff1b;SpringBoot在底层都给我们自动配置好&#xff1b;SpringBoot使用一个全局的配置文件&#xff0c;配置文件名是固定的&#xff1a; application.propertiesapplication.yml 以上…

【无标题】vmprotect net 混淆效果挺不错

vmprotect net 混淆效果挺不错,测试了一个&#xff0c;以前的写程序。用dnspy测试一下&#xff0c;效果非常好。 sunnf0451qq.com

string接口[小白理解篇]

作文目的 本文是为了加深对string底层函数的一点理解(请勿与底层源码混为一谈)&#xff0c;下面从模拟与注意项出发。 一.string 功能化模拟 1.迭代器模拟 迭代器&#xff0c;为实现简单便理解故使用指针的方式(非说明迭代器使用该方法实现)。其中的begin、end都是为了给迭代…

【论文笔记合集】ARIMA 非平稳过程通过差分转化为平稳过程

本文作者&#xff1a; slience_me 文章目录 ARIMA 非平稳过程通过差分转化为平稳过程文章原文具体解释详解参照 ARIMA 非平稳过程通过差分转化为平稳过程 文章原文 Many time series forecasting methods start from the classic tools [38, 10]. ARIMA [7, 6] tackles the fo…

爬虫入门到精通_框架篇16(Scrapy框架基本使用)_名人名言的抓取

1 目标站点分析 抓取网站&#xff1a;http://quotes.toscrape.com/ 主要显示了一些名人名言&#xff0c;以及作者、标签等等信息&#xff1a; 点击next&#xff0c;page变为2&#xff1a; 2 流程框架 抓取第一页&#xff1a;请求第一页的URL并得到源代码&#xff0c;进行下…