upload-labs靶场通关姿势(11-19)

Pass 11

绕过方法:00截断

因为截断条件是php版本小于5.3.4,php的magic_quotes_gpc为OFF状态,所以得先在相应的php版本目录下找到配置文件php.ini,然后把magic_quotes_gpc的状态修改为OFF,修改完之后重启一下服务就可以了。

upload-labs靶场通关姿势(11-19)_第1张图片

upload-labs靶场通关姿势(11-19)_第2张图片

用Burp Suite代理构造sava_path=/upload/ok.php%00,然后再filename处修改文件拓展名为png(jpggif)

upload-labs靶场通关姿势(11-19)_第3张图片

 

 

源码分析

$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类型文件!";
    }
}

 

这里使用了白名单过滤,只允许上传.jpg|.png|.gif类型文件,而且文件保存的方式是上传路径+随机数+时间+截取的文件拓展名,就是说上传的文件会被重命名为一个随机数+时间的字符串,所以不能再从filename那里下手了,得在保存文件的时候下手。因为$img_path是直接拼接的,可以考虑对sava_path下手,在save_path后面加上文件名并且在文件名后面加上%00,这样保存文件的时候就会用加上去的文件名,又因为在后面加了%00,move_uploaded_file函数遇到%00就会认为已经结束,从而忽略了后面的随机数和时间以及拓展名。

 

相关函数:

move_uploaded_file($temp_file,$img_path) 函数把上传的文件($temp_file)移动到新位置($img_path)。如果成功该函数返回 TRUE,如果失败则返回 FALSE。

参考链接:https://www.runoob.com/php/func-filesystem-move-uploaded-file.html

 

Pass 12

绕过方法:00截断

还是和上一关一样,用Burp Suite代理构造sava_path=/upload/ok.php%00,然后再filename处修改文件拓展名为png(或jpg、gif),由于这一关不能对%00进行自动解码,所以还需要在二进制中进行修改,把ok.php对应的二进制数后面一位改成00。

 

upload-labs靶场通关姿势(11-19)_第4张图片

 

upload-labs靶场通关姿势(11-19)_第5张图片

 

源码分析

$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类型文件!";
    }
}

 

这里的源码基本和pass 11一样,唯一的不同就是,这里的save_path参数通过POST方式传递的,pass 11的save_path参数通过GET方式传递的,因为POST不会像GET对%00进行自动解码,所以这里需要在二进制中进行修改。

 

Pass 13

绕过方法:添加图片文件头标识

制作图片木马,在文件头部加上GIF文件的头部标识(GIF89a),当服务器检测文件头时,检测到GIF89a即判定该文件为GIF文件。再写入一句话木马,将文件保存为GIF格式,上传。

图片文件头标识参考链接:https://blog.csdn.net/qq_37414405/article/details/84660148

upload-labs靶场通关姿势(11-19)_第6张图片

上传文件后在响应包中可以找到文件上传的路径,以便后面访问。

upload-labs靶场通关姿势(11-19)_第7张图片

因为直接访问GIF格式图片不能正常解析里面的php代码,所以这里得结合文件包含漏洞利用。用下面代码写一个include.php的文件放在靶场的WWW\upload-labs\upload\下面。

 

##include.php

 

通过文件包含漏洞访问GIF文件,其中的php被成功解析。

upload-labs靶场通关姿势(11-19)_第8张图片

 

 

源码分析

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 = "上传出错!";
        }
    }
}

 

这里相对之前的代码,多了个文件内容检测,即通过读文件的前2个字节判断文件类型,因此想通过文件名绕过检测上传木马已经行不通了,但可以在内容里面加上图片文件的头标识,这样当服务器检测到添加图片文件头标识时,就会判定该文件为图片格式,成功绕过内容检测。

 

Pass 14

绕过方法:添加图片文件头标识

方法同pass 13一样

 

源码分析

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 = "上传出错!";
        }
    }
}

这里还是和上一关一样,对文件做了内容检测。但这里用的是getimagesize() 函数判断文件类型,该函数作用是获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。

getimagesize() 函数参考链接:https://www.runoob.com/php/php-getimagesize.html

Pass 15

绕过方法:添加图片文件头标识

绕过方法和pass 13 一样,但这关需要开启php_exif模块才能正常运行。

开启php_exif模块方法:

1.在php.ini文件中找到;extension=php_exif.dll,去掉前面的分号
2.在php.ini文件中找到;extension=php_mbstring.dll,去掉前面的分号,并将此行移动到extension=php_exif.dll之前,使之首先加载*。
3.找到[exif]段,把下面语句的分号去掉。
;exif.encode_unicode = ISO-8859-15
;exif.decode_unicode_motorola = UCS-2BE
;exif.decode_unicode_intel = UCS-2LE
;exif.encode_jis =
;exif.decode_jis_motorola = JIS
;exif.decode_jis_intel = JIS
4.重启php服务

参考链接:https://www.cnblogs.com/cookies9/p/9209252.html

 

 

源码分析

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 = "上传出错!";
        }
    }
}

 

这里基本和前面2关一样,绕过方法也一样,不同的是这里用到php_exif模块来判断文件类型。

exif_imagetype函数参考:https://www.cnblogs.com/phpBigbin/p/7945273.html

 

Pass 16

绕过方法:图片木马(二次渲染)

制作图片木马,在cmd命令下执行copy 1.gif/b + ok.php/a 2.gif,将1.gif的图片文件和ok.php的木马合并成2.gif。

upload-labs靶场通关姿势(11-19)_第9张图片

一句话木马被插入到gif图片中。

upload-labs靶场通关姿势(11-19)_第10张图片

上传2.gif,上传的图片都经过了二次渲染,我们16进制编辑器将经过二次渲染和正常的图片打开进行对比。看那一部分没被覆盖,然后将代码插入到该地方。再次上传重新制作的木马图片,结合文件包含漏洞即可访问木马。

具体参考:https://xz.aliyun.com/t/2657#toc-2

 

源码分析

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){
    // 获得上传文件的基本信息,文件名,类型,大小,临时文件路径
    $filename = $_FILES['upload_file']['name'];
    $filetype = $_FILES['upload_file']['type'];
    $tmpname = $_FILES['upload_file']['tmp_name'];

    $target_path=UPLOAD_PATH.'/'.basename($filename);

    // 获得上传文件的扩展名
    $fileext= substr(strrchr($filename,"."),1);

    //判断文件后缀与类型,合法才进行上传操作
    if(($fileext == "jpg") && ($filetype=="image/jpeg")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefromjpeg($target_path);

            if($im == false){
                $msg = "该文件不是jpg格式的图片!";
                @unlink($target_path);
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".jpg";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagejpeg($im,$img_path);
                @unlink($target_path);
                $is_upload = true;
            }
        } else {
            $msg = "上传出错!";
        }

    }else if(($fileext == "png") && ($filetype=="image/png")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefrompng($target_path);

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

                @unlink($target_path);
                $is_upload = true;               
            }
        } else {
            $msg = "上传出错!";
        }

    }else if(($fileext == "gif") && ($filetype=="image/gif")){
        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;
            }
        } else {
            $msg = "上传出错!";
        }
    }else{
        $msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";
    }
}

 

这里判断了后缀名以及Content-Type,然后再用imagecreatefrom[gif|png|jpg]函数判断是否是图片格式,如果是图片的话再用image[gif|png|jpg]函数对其进行二次渲染,经过二次渲染的文件有可能会把我们添加进去的内容覆盖掉,所以绕过方法是把内容添加在不会被覆盖的地方。

 

 

Pass 17

绕过方法:条件竞争

  • 上传木马文件ok.php

upload-labs靶场通关姿势(11-19)_第11张图片

  • Burp suite抓包利用intuder模块进行大量重放

upload-labs靶场通关姿势(11-19)_第12张图片

  • 浏览器访问木马文件,并用burp suite抓包

upload-labs靶场通关姿势(11-19)_第13张图片

  • 利用Burp suite的intuder模块进行大量重复访问

upload-labs靶场通关姿势(11-19)_第14张图片

观察结果可以发现有一小部分访问成功。

源码分析

$is_upload = false;
$msg = null;

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 = '上传出错!';
    }
}

 

这里是条件竞争,先将文件上传到服务器,然后判断文件后缀是否在白名单里,如果在则重命名,否则删除,因此我们可以上传木马文件,只需要在它删除之前访问即可,可以利用burp的intruder模块不断上传,然后利用burp的intruder模块不断访问木马文件,有部分访问是成功的。

 

Pass 18

绕过方法:条件竞争

方法与pass 17一样

 

源码分析

upload-labs靶场通关姿势(11-19)_第15张图片

 

这里先用move函数将上传的文件保存,再用renameFile函数重命名。所以也存在条件竞争,绕过方法和上面Pass-17差不多。

 

Pass 19

绕过方法:00截断

上传文件ok.php,保存文件那里填ok.php.jpg,上传,用burp将save_name那里的ok.php.jpg中php后面的点的十六进制(2e)改为00

upload-labs靶场通关姿势(11-19)_第16张图片

 

源码分析

$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");

        $file_name = $_POST['save_name'];
        $file_ext = pathinfo($file_name,PATHINFO_EXTENSION);

        if(!in_array($file_ext,$deny_ext)) {
            $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 = '禁止保存为该类型文件!';
        }

    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

这里利用了黑名单过滤,发现这里img_path可控(通过post sava_name),所以可以利用move_uploaded_file\x00截断(save_name=ok.php%00jpg)绕过。

总结

pass 11、12、19 是利用00截断绕过,主要原理是在文件拓展名后面加上00(表示字符串结束),当函数读取到00的时候就会截断

pass 13-15 主要是在文件内添加图片头文件标识,以此绕过服务器对内容的检测

pass 16 是绕过二次渲染,通过对比找出二次渲染后没有被覆盖的部分,然后在该部分出入木马

pass 17-18是条件竞争,通过Burp suite的intuder模块进行大量的上传请求及访问请求,以求文件被删除之前访问

 

参考链接:https://www.jianshu.com/p/aabc1e7408d5

你可能感兴趣的:(文件上传漏洞)