这是文件上传靶场的最后一关,同时我也会总结一下每一关的绕过方法。

pass-21

通过源码观察一下网站信息,准备php代码,同样是使用了phpinfo()函数

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

观察一下源码中的函数,了解一下文件上传经过了哪几步验证。

strtolower把字符串转换为小写

emply()用来检查一个变量是否为空,当一个变量并不存在,或者它的值等同于 FALSE,那么它会被认为不存在。如果变量不存在的话,empty()并不会产生警告

end() 函数将数组内部指针指向最后一个元素,并返回该元素的值(如果成功)。

reset() 函数将内部指针指向数组中的第一个元素,并输出。

count(array,mode) 函数返回数组中元素的数目

验证上传路径是否存在
验证(upload_file)的content-type是否合法
判断POST参数是否为空定义$file变量
判断file不是数组则使用explode(‘.’, strtolower($file))对file进行切割,将file变为一个数组
判断数组最后一个元素是否合法
数组第一位和$file[count($file) - 1]进行拼接,产生保存文件名file_name
上传文件

那么我们就一点点的将上面说的全部修改一下,修改Content-Type为image/png

然后将POST参数修改为数组形式,第二个save_name括号内的数字只要部位一,那么$file[count($file) - 1]就等价于$file[2-1],值为空,就会直接输出save_name[0]的文件名,修改后的如下图

image-20211002111948408

放包尝试一下是否能上传成功,提示php文件上传成功

image-20211002112020698

那么就可以浏览器控制台查看文件路径访问了,php代码执行成功。

image-20211002112140559

那么21关就全部绕过成功了。

总结

pass-1 修改文件后缀绕过

pass-2 修改Content-Type绕过

pass-3 特殊后缀绕过.phtml .php5 .php3

pass-4 上传.htaccess文件解析php代码绕过

pass-5 .php. .特殊后缀或者上传.user.ini文件绕过

pass-6 .PHP特殊后缀绕过

pass-7 .php后加空格,特殊后缀绕过

pass-8 特殊后缀.php.绕过

pass-9 .php::$DATA后缀绕过

pass-10 .php.1.绕过,deldot($file_name)遇到字符会停止检测

pass-11 .pphphp后缀绕过,str_ireplace(find,replace,string,count)函数特性

pass-12 GET 00截断

pass-13 POST 00截断

pass-14 修改gif文件头借助文件包含实现php代码执行

pass-15 同14关,只不过换了一个getimagesize函数来检测图片

pass-16 同14关,exif_imagetype()检测图片

pass-17 二次渲染绕过

pass-18 条件竞争,burpsuite爆破

pass-19 条件竞争结合文件包含

pass-20 修改$_POST模块+move_uploaded_file的漏洞

pass-21 修改$_POST+添加数组构造php文件后缀

上方是upload一些给关卡,下面给介绍一下其他中间件上传漏洞