当前位置:   article > 正文

文件上传漏洞靶场upload-labs学习(pass11-pass15)_pass靶场所有题目分析

pass靶场所有题目分析

0x00 Pass11(str_ireplace复写绕过)

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在PHP中

str_replace() 函数
定义:使用一个字符串替换字符串中的另一些字符,对大小写敏感的搜索
语法:str_replace(find,replace,string,count)

str_ireplace() 函数
定义:使用一个字符串替换字符串中的另一些字符,对大小写不敏感的搜索
语法:str_ireplace(find,replace,string,count)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

可见无法通过后缀名的大小写绕过,但对于replace函数中直接替换为空的场景通常可以用复写来绕过,例如本关中的test1.pphphp即可在replace后变成test1.php

在这里插入图片描述

0x01 Pass12(GET方式%00截断)

本题考查%00截断,相当于复现CVE-2006-7243,所以需将php版本设置为PHP 5.3.4以下, 并关闭magic_quotes_gpc选项。
具体代码为:

$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

可见保存的路径也可以由用户所控制,GET类型的传参。因此在保存路径中修改为:

save_path=../upload/test.php%00
  • 1

再上传一个正常的jpg图片即可。

在这里插入图片描述这时由于受空字符%00的影响,后面所有的内容均被截断。
最终上传test.php文件。

在这里插入图片描述

0x02 Pass13(POST方式%00截断)

上一关中看到save_path变量是通过GET形式传参接受的,因此在url中直接使用%00截断使得后面的路径拼接不被读取。

$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

而在13关中,$_POST['save_path']以POST形式传参时,直接使用%00无法截断,因为POST的数据不会被直接解码,需要手动使用burp中的URL-decode解码。

在这里插入图片描述
解码后就变为了不可见字符,绕过POST形式的00截断。

在这里插入图片描述

0x03 Pass14(文件头截取判断)

可以看到题目的要求为:

1.保证上传后的图片马中仍然包含完整的一句话或webshell代码。
2.使用文件包含漏洞能运行图片马中的恶意代码。
3.图片马要.jpg,.png,.gif三种后缀都上传成功才算过关!

代码如下:

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

可见每次上传的文件都会被读取前两个字节来判断文件类型,这里判断的也就是文件头。
这里把三种文件类型的文件头加上:

PNG文件:hex格式8950,取值输出为13780

在这里插入图片描述
在这里插入图片描述

JPG文件:hex格式FFD8,取值输出为255216。

在这里插入图片描述
在这里插入图片描述

GIF文件:GIF89a,当文件第一行为GIF头时,取值输出为7173。

在这里插入图片描述
在burp中,GIF文件我们只需要在要发送的数据包前面加上文件头即可。
而png和jpg文件受不可见字符的影响,建议以copy /b 1.png+test.php upload.png的命令制作图片木马。
打开后如图所示:
在这里插入图片描述

上传成功后使用题目中给出的链接测试文件包含是否可以执行图片木马。
在这里插入图片描述

0x04 Pass15(getimagesize函数绕过)

判断是否为图片的代码为:

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

使用 $info = getimagesize($filename);和 $ext = image_type_to_extension($info[2]);取文件后缀名。
在php中getimagesize会获取7个元素的值,分别为:

索引 0 给出的是图像宽度的像素值
索引 1 给出的是图像高度的像素值
索引 2 给出的是图像的类型,返回的是数字,其中1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF(intel byte order),8 = TIFF(motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM
索引 3 给出的是一个宽度和高度的字符串,可以直接用于 HTML 的<image> 标签
索引 bits 给出的是图像的每种颜色的位数,二进制格式
索引 channels 给出的是图像的通道值,RGB 图像默认是 3
索引 mime 给出的是图像的 MIME 信息,此信息可以用来在 HTTP Content-type 头信息中发送正确的信息,如: header(“Content-type: image/jpeg”);

上传一张示例图片返回结果为:
在这里插入图片描述可以看到info[2]的值为2,也就是JPG,与返回的相同。
在本关中,使用刚刚copy /b 1.png+test.php upload.png生成的图片马即可绕过。
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/848487
推荐阅读
相关标签
  

闽ICP备14008679号