• upload-Labs靶场“11-15”关通关教程


    君衍.

    • 一、第十一关 %00截断GET上传
      • 1、源码分析
      • 2、%00截断GET上传
    • 二、第十二关 %00截断POST上传
      • 1、源码分析
      • 2、%00截断POST上传
    • 三、第十三关 文件头检测绕过
      • 1、源码分析
      • 2、文件头检测绕过
    • 四、第十四关 图片检测绕过上传
      • 1、源码分析
      • 2、图片马绕过上传
    • 五、第十五关 图片检测绕过上传
      • 1、源码分析
      • 2、图片马绕过上传

    upload-Labs靶场“1-5”关通关教程

    一、第十一关 %00截断GET上传

    1、源码分析

    $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类型文件!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    添加注释解读:

    $is_upload = false;
    $msg = null;
    # 检查是否有名为 submit 的表单提交
    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,使用 rand(10, 99) 生成两位随机数和当前日期时间
            $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
            # 使用 move_uploaded_file($temp_file, $img_path) 将上传的文件移动到目标路径
            if(move_uploaded_file($temp_file,$img_path)){
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else{
            $msg = "只允许上传.jpg|.png|.gif类型文件!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    代码中使用白名单限制上传的文件后缀名,只允许指定的图片格式。但是
    $_GET['save_path']服务器接受客户端的值,这个值可被客户端修改。

    2、%00截断GET上传

    这里我们便将上传参数更改:
    在这里插入图片描述
    在这里插入图片描述
    更改掉之后就会将1.jpg覆盖给1.php通过%00进行截断,即为1.php%001.jpg变为1.php:
    在这里插入图片描述
    然后访问执行即可。

    二、第十二关 %00截断POST上传

    1、源码分析

    $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 = $_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类型文件!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    添加注释解读代码:

    $is_upload = false;
    $msg = null;
    # 检查是否有名为 submit 的表单提交
    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,使用 rand(10, 99) 生成两位随机数和当前日期时间
            $img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
    		# 这里使用 $_POST['save_path'] 构建目标文件路径,而不是之前的 $_GET['save_path']
    		# 将上传的文件移动到目标路径
            if(move_uploaded_file($temp_file,$img_path)){
                $is_upload = true;
            } else {
                $msg = "上传失败";
            }
        } else {
            $msg = "只允许上传.jpg|.png|.gif类型文件!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    这段代码同样是白名单限制后缀名,$_POST['save_path']是接收客户端提交的值,客户端可任意修改。所以会产生安全漏洞。

    2、%00截断POST上传

    这里我们同十一关一样,通过抓包修改参数,使用%00进行截断文件名,在GET传参中是可以使用的,但是这里是POST,所以我们使用decode编码:
    在这里插入图片描述
    将%00进行编码:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    我们可以看到这里上传成功,然后我们访问图像链接来执行:
    在这里插入图片描述
    即可完成上传。

    三、第十三关 文件头检测绕过

    1、源码分析

    function getReailFileType($filename){
        $file = fopen($filename, "rb");
        $bin = fread($file, 2); //只读2字节
        fclose($file);
        $strInfo = @unpack("C2chars", $bin);    
        $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    
        $fileType = '';    
        switch($typeCode){      
            case 255216:            
                $fileType = 'jpg';
                break;
            case 13780:            
                $fileType = 'png';
                break;        
            case 7173:            
                $fileType = 'gif';
                break;
            default:            
                $fileType = 'unknown';
            }    
            return $fileType;
    }
    
    $is_upload = false;
    $msg = null;
    if(isset($_POST['submit'])){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $file_type = getReailFileType($temp_file);
    
        if($file_type == 'unknown'){
            $msg = "文件未知,上传失败!";
        }else{
            $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
            if(move_uploaded_file($temp_file,$img_path)){
                $is_upload = true;
            } else {
                $msg = "上传出错!";
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    添加注释解读以上代码:

    # 用于获取文件的真实类型
    function getReailFileType($filename){
    	# 打开文件并读取前两个字节
        $file = fopen($filename, "rb");
        $bin = fread($file, 2); //只读2字节
        fclose($file);
        # 使用 unpack 函数将二进制数据解析为数组 $strInfo
        # 每个字节被解析为一个无符号字符(C),总共解析两个字节
        $strInfo = @unpack("C2chars", $bin);  
        # 将解析后的两个字节拼接成一个整数,存储在 $typeCode 中
        $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    
        # 初始化变量 $fileType 为空字符串
        $fileType = '';
        # 根据 $typeCode 的值执行不同的操作    
        switch($typeCode){      
            case 255216:            
                $fileType = 'jpg';
                break;
            case 13780:            
                $fileType = 'png';
                break;        
            case 7173:            
                $fileType = 'gif';
                break;
            default:            
                $fileType = 'unknown';
            }    
            return $fileType;
    }
    
    $is_upload = false;
    $msg = null;
    # 检查是否接收到名为 submit 的 POST 请求
    if(isset($_POST['submit'])){
    	# 获取上传文件的临时文件路径
        $temp_file = $_FILES['upload_file']['tmp_name'];
        # 调用之前定义的 getReailFileType 函数获取上传文件的真实类型
        $file_type = getReailFileType($temp_file);
    	# 检查文件类型是否为 'unknown'
        if($file_type == 'unknown'){
            $msg = "文件未知,上传失败!";
        }else{
        	# 构建目标文件路径,包括上传路径、随机生成的文件名和文件扩展名
            $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
            # 将临时文件移动到目标路径if(move_uploaded_file($temp_file,$img_path)){
                $is_upload = true;
            } else {
                $msg = "上传出错!";
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    上传时候会检测头文件,不同的文件,头文件也不尽相同。常见的文件上传图片头检测 它检测图片是两个字节的长度,如果不是图片的格式,会禁止上传。

    常见的文件头
     JPEG (jpg),文件头:FFD8FF
     PNG (png),文件头:89504E47
     GIF (gif),文件头:47494638
     TIFF (tif),文件头:49492A00
     Windows Bitmap (bmp),文件头:424D

    在这里插入图片描述

    2、文件头检测绕过

    首先我们创建图片马:

    copy 1.gif/b+1.php shell.gif
    copy 图片文件/b + 敏感文本文件 web.jpg
    
    • 1
    • 2

    将 php 文件附加在gif图片上,直接上传即可
    在这里插入图片描述
    直接上传这里利用文件包含漏洞来执行:
    在这里插入图片描述
    复制文件链接,然后利用文件上传漏洞访问执行:

    http://192.168.217.130/up/include.php?file=http://192.168.217.130/up/upload/1620240301170724.gif
    
    • 1

    在这里插入图片描述

    我们即可看到执行成功。
    当然,我们也可以直接加上GIF89a
    我们上传一个木马,同时进行抓包:
    在这里插入图片描述
    在这里插入图片描述
    改为:
    在这里插入图片描述
    放通后进行访问执行:
    在这里插入图片描述
    即可看到执行成功。

    四、第十四关 图片检测绕过上传

    1、源码分析

    function isImage($filename){
        $types = '.jpeg|.png|.gif';
        if(file_exists($filename)){
            $info = getimagesize($filename);
            $ext = image_type_to_extension($info[2]);
            if(stripos($types,$ext)>=0){
                return $ext;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }
    
    $is_upload = false;
    $msg = null;
    if(isset($_POST['submit'])){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $res = isImage($temp_file);
        if(!$res){
            $msg = "文件未知,上传失败!";
        }else{
            $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;
            if(move_uploaded_file($temp_file,$img_path)){
                $is_upload = true;
            } else {
                $msg = "上传出错!";
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    使用注释解读代码:

    # 检查文件是否为图片
    function isImage($filename){
    	# 定义了允许上传的图片文件类型
        $types = '.jpeg|.png|.gif';
        # 检查指定的文件是否存在
        if(file_exists($filename)){
        	# 获取文件的基本信息,包括图片的宽度、高度以及图像类型等
            $info = getimagesize($filename);
            # 将图像类型转换为对应的文件扩展名
            $ext = image_type_to_extension($info[2]);
            # 用 stripos 函数检查文件扩展名是否在允许的类型列表中
            if(stripos($types,$ext)>=0){
                return $ext;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }
    
    $is_upload = false;
    $msg = null;
    # 检查是否接收到名为 submit 的 POST 请求
    if(isset($_POST['submit'])){
    	# 获取上传文件的临时文件路径
        $temp_file = $_FILES['upload_file']['tmp_name'];
        # 调用 isImage 函数检查上传文件是否为图片
        $res = isImage($temp_file);
        # 如果上传文件不是图片输出
        if(!$res){
            $msg = "文件未知,上传失败!";
        }else{
        	# 构建目标文件路径,包括上传路径、随机生成的文件名和文件扩展名
            $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;
            # 将临时文件移动到目标路径
            if(move_uploaded_file($temp_file,$img_path)){
                $is_upload = true;
            } else {
                $msg = "上传出错!";
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    2、图片马绕过上传

    源码中使用getimagesize来获取图片的大小,如果头文件不是图片直接报错,所以我们可以直接使用图片马绕过检测。
    在这里插入图片描述
    然后直接使用文件包含漏洞访问执行:
    在这里插入图片描述
    即可看到成功上传并执行。

    五、第十五关 图片检测绕过上传

    1、源码分析

    function isImage($filename){
        //需要开启php_exif模块
        $image_type = exif_imagetype($filename);
        switch ($image_type) {
            case IMAGETYPE_GIF:
                return "gif";
                break;
            case IMAGETYPE_JPEG:
                return "jpg";
                break;
            case IMAGETYPE_PNG:
                return "png";
                break;    
            default:
                return false;
                break;
        }
    }
    
    $is_upload = false;
    $msg = null;
    if(isset($_POST['submit'])){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $res = isImage($temp_file);
        if(!$res){
            $msg = "文件未知,上传失败!";
        }else{
            $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$res;
            if(move_uploaded_file($temp_file,$img_path)){
                $is_upload = true;
            } else {
                $msg = "上传出错!";
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    添加注释解读以上代码:

    function isImage($filename){
        // 需要开启php_exif模块
        $image_type = exif_imagetype($filename); // 获取图片的类型
        switch ($image_type) { // 根据图片类型执行不同的操作
            case IMAGETYPE_GIF:
                return "gif"; // 如果是 GIF 类型的图片,返回 "gif"
                break;
            case IMAGETYPE_JPEG:
                return "jpg"; // 如果是 JPEG 类型的图片,返回 "jpg"
                break;
            case IMAGETYPE_PNG:
                return "png"; // 如果是 PNG 类型的图片,返回 "png"
                break;    
            default:
                return false; // 如果不是上述类型的图片,则返回 false
                break;
        }
    }
    
    $is_upload = false; // 初始化变量,用于表示文件是否上传成功,默认为 false
    $msg = null; // 初始化变量,用于存储错误消息,默认为 null
    
    if(isset($_POST['submit'])){ // 检查是否接收到名为 'submit' 的 POST 请求,表示用户提交了表单
        $temp_file = $_FILES['upload_file']['tmp_name']; // 获取上传文件的临时文件路径
        $res = isImage($temp_file); // 调用 isImage 函数检查上传文件是否为图片
        if(!$res){ // 如果上传文件不是图片,则执行以下操作
            $msg = "文件未知,上传失败!"; // 将错误消息设置为 "文件未知,上传失败!"
        }else{ // 如果上传文件是图片,则执行以下操作
            $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$res; // 构建目标文件路径,包括上传路径、随机生成的文件名和文件扩展名
            if(move_uploaded_file($temp_file,$img_path)){ // 将临时文件移动到目标路径,如果移动成功,则执行以下操作
                $is_upload = true; // 设置文件上传状态为完成
            } else { // 如果移动文件失败,则执行以下操作
                $msg = "上传出错!"; // 将错误消息设置为 "上传出错!"
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    2、图片马绕过上传

    第十五关同样进行判断是否为图片,所以同十四关相同:
    在这里插入图片描述
    然后直接使用文件包含漏洞访问执行:
    在这里插入图片描述
    即可看到成功上传并执行。

  • 相关阅读:
    jQuery实现输入框提示并点击回显功能呢
    第6章 数据存储全方案——详解持久化技术
    dgl安装教程
    【算法|贪心算法系列No.2】leetcode2208. 将数组和减半的最少操作次数
    Zookeeper分布式应用协调软件的核心概念以及部署
    leetcode 9
    Android---网络编程优化
    sql计算占比
    我的测试开发十年之路
    高性能MySQL实战第05讲:高性能索引该如何设计(上)
  • 原文地址:https://blog.csdn.net/weixin_63172698/article/details/136392155