文件上传漏洞: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靶场实验实例完成。

相关推荐
tingshuo291735 分钟前
S001 【模板】从前缀函数到KMP应用 字符串匹配 字符串周期
笔记
用户962377954485 小时前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机8 小时前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机8 小时前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户9623779544810 小时前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star10 小时前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户9623779544813 小时前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
cipher2 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
一次旅行5 天前
网络安全总结
安全·web安全
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习