文件上传漏洞:upload-labs靶场11-20

目录

pass-11

pass-12

pass-13

pass-14

pass-15

pass-16

pass-17

pass-18

pass-19

pass-20


pass-11

分析源代码 ,发现上传文件的存放路径可控

php 复制代码
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类型文件!";
    }
}

抓包查看,利用%00截断

save_path=../upload/修改为save_path=../upload/web.php%00

抓包后的信息可以看见有save_path,说明路径可控。我们通过修改路径令save_path: ../uploads/web.php%00,然后上传一个文件后缀为.jpgphpinfo文件,代码处得到的后缀为jpg,能够通过对文件后缀的检测,$img_path变量为../uploads/info.php%00+随机日期.jpg,当执行move_uploaded_file函数时,服务器会对路径中%00后的内容不做解析,默认迁移文件为../uploads/web.php

结果

漏洞点:文件上传路径可控,利用%00截断

pass-12

php 复制代码
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 = $_POST['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类型文件!";
    }
}

分析代码发现11关是get传参,本关是post传参,

二者区别

在GET请求中会对输入的内容进行URL解码。但POST请求有不同,因为在上传表单中存在一个enctype的属性,而且在enctype="multipart/form-data"这里,是不会对表单中的数据进行解码的,需要我们将POST中的%00解码后传入。

再web.php后面的%00进行url解码

成功

pass-13

本关设计文件包含漏洞

需要上传图片马

制作图片马

php 复制代码
copy a.png /b + 1.php /a webshell2.png

应该包含如下内容

接着直接上传图片,然后我们通过文件包含漏洞进行解析文件。该文件包含解码通过get传参,我们复制图片地址,链接到文件包含界面,然后访问。

成功

pass-14

同13关,直接上传我们的图片马即可

pass-15

同13关

pass-16

同样,我们尝试上传图片马

发现上传成功,但是访问文件发现并没有执行我们的php脚本

查看源代码

php 复制代码
if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefromgif($target_path);
            if($im == false){
                $msg = "该文件不是gif格式的图片!";
                @unlink($target_path);
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".gif";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagegif($im,$img_path);

                @unlink($target_path);
                $is_upload = true;
            }

发现图片进行了二次渲染。

针对二次渲染,我们的方法是利用beyond compare工具,进行上传前和上传后的16进制对比,找出相同的位置插入我们的脚本代码,接着重新上传该图片。

访问图片,成功

当然,还可以尝试利用jpg和png格式的图片

pass-17

上传我们的php文件,发现上传失败

查看源代码

php 复制代码
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 file_put_contents('../web.php','<?php phpinfo();?>');?>

创建的路径在上一级路径防止被删除

可以利用bp一边进行竞争,一边进行访问

访问文件

成功。

pass-18

上传图片,发现upload中没有该图片,而是在上一级目录中

我们上传图片马,然后可以利用文件包含。

成功。

pass-19

本关可以利用大小写绕过或者/.绕过

大小写绕过

直接将web.php改为web.phP

当然利用/.也可以,生成一个一句话木马的脚本改为jpg类型上传

然后bp抓包修改保存的文件名即可

修改为

查看文件

上传成功

pass-20

源代码分析

php 复制代码
 if (file_exists(UPLOAD_PATH)) {

        $is_upload = false;
        $msg = null;
        if(!empty($_FILES['upload_file'])){
            //mime check
            $allow_type = array('image/jpeg','image/png','image/gif');
            if(!in_array($_FILES['upload_file']['type'],$allow_type)){
                $msg = "禁止上传该类型文件!";
            }else{
                //check filename
                $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 = "请选择要上传的文件!";
        }
        
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }

分析代码

php 复制代码
empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];

如果save_name为空,则把$_FILES['upload_file']['name']赋值给file,反之`_POST['save_name']`赋值给$file

php 复制代码
if (!is_array($file)) {
            $file = explode('.', strtolower($file));
        }

如果$file不是数组,则将其处理为数组,通过.符号将其分割 [ "muma.php","","jpg"]

php 复制代码
$ext = end($file);   //文件后缀
 $allow_suffix = array('jpg','png','gif');
 if (!in_array($ext, $allow_suffix)) {
           $msg = "禁止上传该后缀文件!";
}

end()函数获得file中的最后一个元素,赋值给ext,并进行后缀校验

php 复制代码
}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 = "文件上传失败!";
                    }

后缀符合,则拼接文件名为首元素.尾元素 reset()获取数组首元素

因此我们可以修改数组,上传php文件,后缀名改为jpg

抓包查看一下

我们需要的是web.php,可以试着将数组传为save_name=["web.php"," ","jpg"],当我们save_name[1]不设置的时候,count结果仍然是2,但是文件名后缀拼接出来为空,结果为web.php. 再根据windows特性将.省略,从而上传文件。

我们可以构造数组

php 复制代码
------geckoformboundary55e8518e38caa5df9e9d15a4791fe8bd
Content-Disposition: form-data; name="save_name[0]"

web.php

------geckoformboundary55e8518e38caa5df9e9d15a4791fe8bd
Content-Disposition: form-data; name="save_name[2]"

jpg

修改为如下内容

上传成功。

访问文件

至此upload-labs靶场实验实例完成。

相关推荐
weixin_502539851 小时前
rust学习笔记12-hashmap与1. 两数之和
笔记·学习·rust
Nijika...2 小时前
MySQL学习笔记(2)并发问题与事务隔离级别
笔记·学习·mysql
L73S372 小时前
C/C++输入输出(1)
c++·笔记·学习·考研·蓝桥杯
Minner-Scrapy3 小时前
智能合约安全指南 [特殊字符]️
安全·区块链·智能合约
网络安全指导员3 小时前
cenos7网络安全检查
开发语言·安全·web安全·php
同学小张4 小时前
Ollama有安全漏洞! 国家网络安全通报中心紧急通报
人工智能·gpt·学习·安全·web安全·aigc·agi
网硕互联的小客服4 小时前
如何排查服务器内存泄漏问题
linux·运维·服务器·安全·ssh
救救孩子把4 小时前
智能笔记,智慧管理:Obsidian 与 DeepSeek 携手引领 AI 知识新时代
人工智能·笔记·大模型·deepseek
重生之成了二本看我逆天改命走向巅峰4 小时前
从0搭建Tomcat第二天:深入理解Servlet容器与反射机制
java·开发语言·笔记·学习·servlet·tomcat·idea