upload-labs代码审计 1-12

uploadfile代码审计1-5

Pass-01

本关审计要点

主要了解前端JS函数功能是如何对上传文件进行检测的

源码

源码

function checkFile() {
    //var 为js定义变量的关键字 
    //document 用来调用功能点函数实现具体功能的
    //getElementsByName 方法返回带有指定名称的对象的集合,查询的是name属性的值
    //定义一个file变量去获取上传的文件名,比如:9z1nc.jpg 第1个元素:9z1nc
    var file = document.getElementsByName('upload_file')[0].value;
    //如果file 文件为null或者空,弹出提示,返回false。
    if (file == null || file == "") {
        alert("请选择要上传的文件!");
        return false;
    }
    //定义允许上传的文件类型
    var allow_ext = ".jpg|.png|.gif";
    //提取上传文件的类型
    //lastIndexOf 从.开始向后匹配
    //substring 提取.后的字符串
    //将提取到的后缀名赋值给ext_name
    var ext_name = file.substring(file.lastIndexOf("."));
    //判断上传文件类型是否允许上传
    //ext_name + "|"与.jpg|进行对比  不相同则返回-1 弹出errMsg
    if (allow_ext.indexOf(ext_name + "|") == -1) {
        var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
        alert(errMsg);
        return false;
    }
}

allow_ext.indexOf(ext_name + "|") == -1

只要有.jpg|.png|.gif 就可以被匹配上

在这里插入图片描述

漏洞利用

利用思路

js前端校验,在代码中是获取上传数据包 Content-Disposition: form-data; name="upload_file"; filename="9z1nc.jpg" Content-Disposition字段中的filename元素内容取它的后缀.jpg与allow_ext中的内容对比,正确即可上传,抓包后只需要修改filename=“9z1nc.jpg” 为"9z1nc.php"就可以利用了。

使用蚁剑生产php webshell,先将文件改成.jpg格式上传并使用burp抓包

在这里插入图片描述

在burp中修改后缀为php

在这里插入图片描述

找到当前上传的路径

在这里插入图片描述

成功访问

在这里插入图片描述

Pass-02

本关审计要点

主要关注代码中对文件类型的判断

源码

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

漏洞利用

利用思路

代码中判断了content-type类型是否为image/jpeg,image/png,image/gif 中的一个,如果是则上传成功,不是则弹出提示。我们只需要抓包后修改content-type类型为这3个白名单中的任意一个即可上传成功。

原来content-type类型为Content-Type: application/ocatet-stream

在这里插入图片描述

修改为image/png

在这里插入图片描述

成功上传

在这里插入图片描述

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

漏洞利用

利用思路

在代码中可以看到,采用了黑名单的方式定义了一些不可以上传的后缀名(‘.asp’,‘.aspx’,‘.php’,‘.jsp’)和处理掉了一些绕过方式(apache解析漏洞,windows文件流,大小写,双文件名)。但我们还可以利用其他的后缀名绕过代码的检测(php3、 php4、php5、pht、phtml、phps)

这里我们上传一个php5的文件,成功上传。

解析还需要改配置文件,这里就演示一下上传成功的效果

在这里插入图片描述

Pass-04

本关审计要点

本关主要关注move_uploaded_file()函数在上传文件时的移动操作

源码

$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",".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 = 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;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

漏洞利用

利用思路

代码中deny_ext 黑名单后缀比较齐全,file_ext也过滤掉了一些绕过方式,但问题出现在$img_path = UPLOAD_PATH.'/'.$file_name; 文件上传后并没有进行重命名的操作,直接将文件保存到相应的路径。我们则可以先上传.htaccess文件(apache中才有),将白名单中的文件当做Php来解析。

.htaccess(看网上说要上传到网站根目录下才能执行,这里直接上传到当前路径下也可以被解析)

将png文件当做php来解析

AddHandler application/x-httpd-php .png

在这里插入图片描述

Pass-05

本关审计要点

了解.user.ini在文件上传中的作用

源码

$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",".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;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件类型不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

漏洞利用

利用思路

.user.ini文件是由用户自定义的php.ini文件,而我们可以利用auto_prepend_file与auto_append_file 可以在不改动任何页面的情况下,当需要修改顶部或底部require文件时,只需要修改auto_prepend_file与auto_append_file的值即可。

auto_prepend_file 在页面顶部加载文件

auto_append_file 在页面底部加载文件

可以看到黑名单也禁止了上传htacess文件,我们可以尝试上传.user.ini文件指定去包含xxx.png文件,而.user.ini文件它可以在php文件被执行的时候,去包含一个指定的文件当做代码执行,相当于require。

.user.ini

auto_prepend_file=9z1nc_5.png

这里需要注意 php要修改为非线程安全nts版本,还有测试的时候发现 是在执行上传路径中的php 会被包含成功

在这里插入图片描述

在这里插入图片描述

uploadfile代码审计6-11

Pass-06

本关审计要点

仔细查看过滤逻辑,以及过滤中用到的函数。

源码

源码

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

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

漏洞利用

利用思路

代码中未使用strtolower()函数对上传的文件名后缀进行小写转换,所以我们可以通过大小写后缀绕过黑名单。

上传文件为9z1nc.pHP

在这里插入图片描述

Pass-07

本关审计要点

仔细查看过滤逻辑,以及过滤中用到的函数。

源码

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

漏洞利用

利用思路

代码中未使用trim()函数对上传文件的后缀名进行收尾去空,我们可以上传文件名为 9z1nc_7.php 的文件

在这里插入图片描述

访问成功

在这里插入图片描述

本地测试的时候发现 php版本7.1.9以上开始就会出现上传出错

在这里插入图片描述

Pass-08

本关审计要点

仔细查看过滤逻辑,以及过滤中用到的函数。

源码

$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",".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); //首尾去空
        
        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 = '此文件类型不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

漏洞利用

利用思路

代码中未使用deldot()函数删除上传文件后缀末尾的.,我们可以上传9z1nc.php.文件,而windwos在读取文件的时候会去掉末尾的.号,上传文件时候php.绕过了代码的过滤,.号windows会自己去掉,所以可以成功访问到自己的webshell

在这里插入图片描述

上传成功(php 5.6.9) php7.4.30上传失败

在这里插入图片描述

Pass-09

本关审计要点

了解Windows中::$DATA特性

源码

$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",".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); //首尾去空
        
        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 . '文件夹不存在,请手工创建!';
    }
}

漏洞利用

利用思路

:: D A T A W i n d o w s 会将 : : DATA Windows会将:: DATAWindows会将::DATA当成文件流来处理

例如:"9z1nc_9.php::$DATA"Windows会自动去掉末尾的::$DATA变成"9z1nc_9.php"

代码中未对:: D A T A 进行过滤,我们可以通过 : : DATA进行过滤,我们可以通过:: DATA进行过滤,我们可以通过::DATA绕过代码的限制,上传我们的webshell

在这里插入图片描述

上传成功,上传到服务器的文件在Windows中会自动去掉::$DATA

在这里插入图片描述

Pass-10

本关审计要点

仔细查看过滤逻辑,以及str_ireplace()函数的作用。

源码

$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",".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); //转换为小写
        //str_ireplace  将::$DATA替换为空=去除字符串::$DATA
        $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;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件类型不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

漏洞利用

利用思路

​ 代码首先会获取上传的文件名并赋值给file_name变量并且使用trim()函数去掉上传文件名两边的空格再使用deldot()函数删除文件名末尾的点号;strrchr()函数处理filename变量获取到的文件名,取最后一次.号到后面的字符串赋值给file_ext 变量,接着对file_ext 变量进行转换为小写,去除字符串::$DATA,首尾去空的操作。这里还有一个问题就是未对上传的文件名进行重命名的操作,导致成功上传

​ 通过以上的代码逻辑,我们发现可以上传 名为**9z1nc.php.**空格. 的文件即可绕过代码逻辑,最后经过代码的处理 文件名为 9z1nc.php.

在这里插入图片描述

在这里插入图片描述

Pass-11

本关审计要点

仔细查看过滤逻辑,以及str_ireplace()函数的作用。

源码

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

        $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;        
        if (move_uploaded_file($temp_file, $img_path)) {
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }

漏洞利用

利用思路

​ 代码中的逻辑问题,$file_name = str_ireplace($deny_ext,"", $file_name);将deny_ext定义的黑名单文件名进行替换为空“”,也就是我们上传9z1nc_11.php会变成9z1nc。但该代码逻辑并没有循环的去处黑名单后缀名,所以我们可以上传9z1nc_11.pphphp进行绕过。

在这里插入图片描述

在这里插入图片描述

uploadfile代码审计12-16

Pass-12

本关审计要点

白名单中文件上传的绕过方式

源码

$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'];
        $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类型文件!";
    }
}

漏洞利用

利用思路

​ strrpos() 函数查找字符串在另一字符串中最后一次出现的位置。echo strrpos("Hello world",w)+1; //6。substr() 函数返回字符串的一部分。echo substr("Hello world",6);//word。$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);如果我们的上传文件名为demo.php。strrpos($_FILES['upload_file']['name'],".")+1 获取.号的下标为5,取到后缀名php。in_array( f i l e e x t , file_ext, fileext,ext_arr)函数搜索数组ext_arr中是否存在指定的值$file_ext。

我们将filename 修改为9z1nc_12.jpg绕过白名单校验,在通过get请求上传文件名为9z1nc_12.php%00

​ 由于在get传参时%00会被url编码转义一次变成0x00,而路径中如果遇到0x00空白字符会丢弃后面的内容

/upload/Pass-12/index.php?save_path=…/upload/9z1nc_12.php%00

filename=“9z1nc_12.jpg”

在这里插入图片描述

在这里插入图片描述

<think>好的,用户正在寻找upload-labs第21关的解决方案。首先我需要回顾一下相关的引用内容,看看有什么有用的信息。 根据引用[1],用户需要查看第21关的源码,具体路径是在upload或未重命名的upload-labs-master目录中找到第21关的index.php文件,并用记事本打开。这表明源码审计是关键步骤。 引用[2]提到这一关涉及POST上传数组的可能性,用户通过实验验证了可以上传数组形式。代码中存在分割数组的操作,然后发现文件拼接时有漏洞。这说明需要构造利用数组上传的payload。 引用[4]指出在处理文件后缀时,代码使用end($file)来取数组最后一个元素作为后缀,并与白名单比较。如果不在白名单中,就会被禁止上传。这里可能存在漏洞,因为如果$file是一个数组,我们可以控制最后一个元素,从而绕过检查。 结合这些信息,用户需要先进行代码审计,确认上传逻辑中的处理方式。例如,检查是否允许上传数组形式的数据,以及文件名的拼接方式是否存在问题。然后构造一个数组形式的文件名,使得最终拼接后的文件名包含可执行的后缀,如.php,但检查时取的是数组中的合法后缀,从而绕过白名单验证。 可能的步骤包括:使用Burp Suite拦截上传请求,将文件名改为数组形式(如name="upload_file[]"),然后构造文件名数组,最后一个元素是允许的后缀(如jpg),但实际拼接后的文件名为shell.php。这样,代码在检查时取的是数组最后一个元素jpg,通过验证,而保存的文件名则是拼接后的.php文件,从而执行恶意代码。 需要验证这个思路是否可行,并确保服务器配置允许执行上传的PHP文件。同时,可能还需要注意其他防护措施,例如是否有重命名文件的操作,或者是否对内容进行了检查。根据引用[3],成功上传后的访问路径可能类似于upfile.php?upfile=执行的命令,所以上传后的利用方式可能涉及直接访问上传的文件或通过参数执行命令。 总结解决方案步骤:1. 上传一个文件,将文件名改为数组形式,最后一个元素为合法后缀;2. 利用代码中的拼接漏洞,生成恶意文件名;3. 绕过白名单检查,上传PHP文件;4. 访问上传的文件执行命令获取flag。</think>根据upload-labs第21关的代码逻辑,其核心漏洞在于**数组上传的文件名拼接绕过白名单验证**。以下是详细解决方案: ### 步骤分析 1. **代码审计**: 通过引用[4]可知,代码使用`$ext = end($file)`获取文件后缀,若文件名为数组形式(如`["shell.php", "jpg"]`),`end()`会取最后一个元素`jpg`进行白名单验证。但实际保存时,文件名会被拼接为`$file[0].$ext`,即`shell.php.jpg`[^4]。但若构造特殊数组,如`$file = ["shell.php", "php"]`,拼接后实际文件名为`shell.phpphp`,可能绕过限制。 2. **构造Payload**: 修改上传请求中的文件名参数为数组格式: ```http POST /upload.php HTTP/1.1 ... Content-Disposition: form-data; name="upload_file[]"; filename="shell.php" Content-Disposition: form-data; name="upload_file[]"; filename="jpg" ``` 此时`$ext = end($file) = "jpg"`通过检查,但实际拼接的文件名可能为`shell.php.jpg`或`shell.php`(取决于代码实现)[^2]。 3. **利用漏洞**: 若代码使用`$file[0]`作为基础名,例如保存路径为`$file[0] . '.' . $ext`,则最终文件名为`shell.php.jpg`。需确保服务器配置允许解析`.php.jpg`为PHP脚本(部分环境默认支持),或通过路径包含漏洞直接执行。 ### 完整利用流程 1. **拦截上传请求**: 使用Burp Suite捕获文件上传请求,修改`filename`为数组形式: ```http Content-Disposition: form-data; name="upload_file[0]"; filename="shell.php" Content-Disposition: form-data; name="upload_file[1]"; filename="jpg" ``` 2. **绕过白名单**: 服务端取`$file[1]`作为后缀(`jpg`),验证通过后将文件保存为`shell.php.jpg`。 3. **访问恶意文件**: 若服务器解析`.php.jpg`为PHP,直接访问`http://target/upload/shell.php.jpg`执行命令;否则结合文件包含漏洞触发。 ### 引用验证 - 引用[2]提到通过数组上传验证漏洞存在性,并成功利用文件拼接漏洞[^2]。 - 引用[4]指出`end($file)`的验证逻辑是漏洞关键点[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值