upload-labs靶场通关详解

文章目录

    • Pass-01
    • Pass-02
    • Pass-03
    • Pass-04
    • Pass-05
    • Pass-06
    • Pass-07
    • Pass-08
    • Pass-09
    • Pass-10
    • Pass-11
    • Pass-12
    • Pass-13
    • Pass-14
    • Pass-15
    • Pass-16
    • Pass-17
    • Pass-18
    • Pass-19
    • Pass-20
      • 方法一(文件夹名欺骗绕过)
      • 方法二(%00截断攻击)
    • Pass-21


Pass-01

绕过js前端检测

我们已经知道会对上传文件进行检测

我们F12,找到checkFile()的方法调用处

upload-labs靶场通关详解_第1张图片

然后删掉即可绕过检测(或者将checkFile()改为Ture
upload-labs靶场通关详解_第2张图片

现在可以正常上传.php文件,然后蚁剑连接

upload-labs靶场通关详解_第3张图片

然后getshell成功

upload-labs靶场通关详解_第4张图片

Pass-02

绕过MIME检测

查看后端源代码,发现只对MIME类型进行检测

我们创建1.php,写入一句话木马


上传,bp抓包修改MIME的application/octet-streamimage/jpeg

upload-labs靶场通关详解_第5张图片

蚁剑连接,getshell成功

upload-labs靶场通关详解_第6张图片

Pass-03

老样子传图片马,发现失败

upload-labs靶场通关详解_第7张图片

查看源代码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array('.asp','.aspx','.php','.jsp');
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');//从右向左查找最后一个出现的点号".",并返回该字符及其后面的所有字符
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //收尾去空

        if(!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;            
            if (move_uploaded_file($temp_file,$img_path)) {
                 $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

结合源代码分析,1.php.1.Php1.php(空格)1.php::$DATA1.php.aa均无法上传成功

那么我们可以上传1.php后,抓包改为1.php3,上传成功

upload-labs靶场通关详解_第8张图片

由于phpstudy新版本没有TS,所以无法解析上传的php3文件(被当作文本)

反正是成功绕过

Pass-04

查看源代码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //收尾去空

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

发现相比于第三关黑名单多了很多,这次不能用php版本绕过

那么可以用.htaccess配置文件攻击

先打开配置文件

upload-labs靶场通关详解_第9张图片

启用AllowOverride

upload-labs靶场通关详解_第10张图片

创建.htaccess文件,写入


SetHandler application/x-httpd-php

上传后可以匹配到1.jpg,然后被当成php文件解析

我们先上传.htaccess文件

上传成功后,再上传1.jpg

upload-labs靶场通关详解_第11张图片

由于phpstudy是新版本,对.htaccess支持存在问题,会出现返回值为空

也就是说.htaccess文件没有上传成功(算是getshell,就是有点无语。。)

Pass-05

源代码

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空
        
        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 . '文件夹不存在,请手工创建!';
    }
}

发现.htaccess文件被办了

发现.ini文件没有被禁用,又因为提示上传目录存在php文件(readme.php)

我们可以上传.ini文件,让所有php文件都“自动”包含某个文件(比如一句话木马)

不过前提是含有.user.ini的文件夹下需要有正常的php文件

创建.user.ini

auto_prepend_file=1.jpg

上传成功后,再上传1.jpg

我们再访问../upload/readme.php(因为我们的一句话木马包含在readme.php)

成功getshell

upload-labs靶场通关详解_第12张图片

Pass-06

源代码

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空

        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件类型不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

.ini被办了,直接卡住。。

仔细发现过滤条件少了大小写转换

结合黑名单,我们可以上传.Php文件绕过

上传成功

upload-labs靶场通关详解_第13张图片

出现服务器配置问题,有点无语

upload-labs靶场通关详解_第14张图片

Pass-07

源代码

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");
        $file_name = $_FILES['upload_file']['name'];
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        
        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file,$img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件不允许上传';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

发现过滤条件少了去空格

思路很清晰,bp抓包手动添加空格(重命名windows系统会吞掉空格)

上传1.php文件,添加空格

upload-labs靶场通关详解_第15张图片

成功绕过

upload-labs靶场通关详解_第16张图片

Pass-08

源代码

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空
        
        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 . '文件夹不存在,请手工创建!';
    }
}

相比于前几关,发现过滤少了去除.

那么我们可以用1.php.绕过

bp抓包手动添加.

upload-labs靶场通关详解_第17张图片

访问../upload/1.php.,成功绕过

upload-labs靶场通关详解_第18张图片

Pass-09

源代码

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = trim($file_ext); //首尾去空
        
        if (!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '此文件类型不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

相比于前一关,发现少了过滤条件去除字符串::$DATA

::$DATA是一个流传输,可以把后面的数据当成流处理和.(空格)类似

那么我们可以先上传1.php然后抓包手动添加::$DATA

upload-labs靶场通关详解_第19张图片

访问../upload/202307160004185100.php,成功绕过

(注意访问路径不带有::$DATA

upload-labs靶场通关详解_第20张图片

Pass-10

源代码

$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",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空
        
        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 . '文件夹不存在,请手工创建!';
    }
}

根据提示,发现只允许上传.jpg|.png|.gif后缀的文件!

但是.htaccess.ini文件都被办了

结合deldot函数,我们可以上传1.php. .绕过

因为deldot函数从后往前检测,检测到末尾的第一个点时会继续它的检测,但是遇到空格会停下来

这样我们既绕过了去除点号,也绕过了去除空格

bp抓包,手动修改

upload-labs靶场通关详解_第21张图片

访问../upload/1.php.(空格),成功绕过

upload-labs靶场通关详解_第22张图片

Pass-11

源代码

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

发现过滤条件会根据黑名单,把我们上传不合格的文件名删掉

$file_name = str_ireplace($deny_ext,"", $file_name);

那么我们可以双写绕过,直接上传1.pphphp

成功绕过

upload-labs靶场通关详解_第23张图片

Pass-12

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

观察源代码,发现多了一个GET参数save_path,这是我们上传文件的路径

说明我们可以控制我们上传文件的保存路径

move_uploaded_file($temp_file,$img_path)是移动文件的函数

我们上传1.php,路径为../upload/

upload-labs靶场通关详解_第24张图片

由于对文件后缀有检测

我们抓包修改文件后缀

upload-labs靶场通关详解_第25张图片

我们在修改上传路径为../upload/1.php%00

因为当程序检测后缀合法后,通过拼接路径和文件名来保存上传的文件

原本的拼接结果为../uploads/1.php%00/9820230717123050.jpg

由于截断字符,移动文件的时候会将文件保存为../uploads/1.php,从而达到getshell

(这里php版本不满足要求,所以magic_quotes_gpc找不到,也就无法上传成功)

Pass-13

源代码

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

和第十二关类似,不过上传路径变为POST传参

先上传1.php,然后抓包修改后缀绕过

upload-labs靶场通关详解_第26张图片

然后修改POST参数为../upload/1.phpa

upload-labs靶场通关详解_第27张图片

点开Hex,找到我们标记的a,修改为00

因为在Hex中改成00后,得到的结果是一个ASCII码为0的字符,也就是null字符或空字符。

在URL编码中,null字符会被替换为%00,从而达到截断效果

upload-labs靶场通关详解_第28张图片

因为php版本问题,和第十二关一样

Pass-14

源代码

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个字节

那么我们既要绕过文件后缀名检测,也要绕过文件头检测

我们创建1.php,写入

 phpinfo();?>

然后修改后缀为.gif

上传抓包,手动添加绕过

在这里插入图片描述

题目告诉我们可以结合文件包含漏洞,点开查看源代码

upload-labs靶场通关详解_第29张图片

要利用include函数去文件包含,才能解析木马的执行

(上述页面存在文件包含漏洞)

upload-labs靶场通关详解_第30张图片

Pass-15

源代码

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

方法和第十四关相同

Pass-16

源代码

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

方法和第十四关相同

Pass-17

源代码

$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的图片文件!";
    }
}

考点是二次渲染,网站展示的是经过二次渲染后的

我们上传的文件得为.jpg.png.gif之一

gif二次渲染容易,我们用准备好的图片马上传,然后下载下来

upload-labs靶场通关详解_第31张图片

拉到010里面对比两张图片相同的地方,即未被二次渲染修改

打开比较文件

upload-labs靶场通关详解_第32张图片

找到相同地方,说明没被二次渲染

upload-labs靶场通关详解_第33张图片

在其中插入一句话木马或getshell

upload-labs靶场通关详解_第34张图片

然后再重新上传

发现被重命名了(当然可以抓包看上传成功后的URL,懒得打开bp了)

upload-labs靶场通关详解_第35张图片

成功访问有文件包含漏洞的URL

upload-labs靶场通关详解_第36张图片

Pass-18

源代码

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

分析一下,发现先对我们上传的文件进行白名单检测,然后会对上传文件重命名,如果不符合,unlink()会删除该文件

也就是说如果我们要传图片马绕过,得要有文件包含漏洞。显然这一关没有,那么我们传的图片马就解析不了,那么就只能传一句话木马

我们可以利用条件竞争上传,因为代码执行的过程是需要耗费时间的,我们只要在上传的一句话被删除之前访问就行了

可以利用burp多线程发包,然后不断在浏览器访问我们的webshell,会有一瞬间的访问成功。

创建1.php,写入微调后的一句话木马

');?>

作用:一旦访问到该文件就会在当前目录下生成一个shell.php的一句话

上传bp抓包,清除payload

upload-labs靶场通关详解_第37张图片

改为Null payload,设置无限重复

upload-labs靶场通关详解_第38张图片

然后写py脚本,通过它来不停的访问我们上传上去的PHP文件

upload-labs靶场通关详解_第39张图片

现在bp开始攻击

upload-labs靶场通关详解_第40张图片

在bp攻击的同时,运行脚本,当出现OK时说明访问到了该文件

upload-labs靶场通关详解_第41张图片

那么我们的一句话木马被成功解析,然后蚁剑连接

(注意连接的是我们在当前目录写的shell.php

upload-labs靶场通关详解_第42张图片

成功getshell

upload-labs靶场通关详解_第43张图片

Pass-19

此题要修改下文件

upload-labs靶场通关详解_第44张图片

源代码

$is_upload = false;
$msg = null;
if (isset($_POST['submit']))
{
    require_once("./myupload.php");
    $imgFileName =time();
    $u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);
    $status_code = $u->upload(UPLOAD_PATH);
    switch ($status_code) {
        case 1:
            $is_upload = true;
            $img_path = $u->cls_upload_dir . $u->cls_file_rename_to;
            break;
        case 2:
            $msg = '文件已经被上传,但没有重命名。';
            break; 
        case -1:
            $msg = '这个文件不能上传到服务器的临时文件存储目录。';
            break; 
        case -2:
            $msg = '上传失败,上传目录不可写。';
            break; 
        case -3:
            $msg = '上传失败,无法上传该类型文件。';
            break; 
        case -4:
            $msg = '上传失败,上传的文件过大。';
            break; 
        case -5:
            $msg = '上传失败,服务器已经存在相同名称文件。';
            break; 
        case -6:
            $msg = '文件无法上传,文件不能复制到目标目录。';
            break;      
        default:
            $msg = '未知错误!';
            break;
    }
}

//myupload.php
class MyUpload{
......
......
...... 
  var $cls_arr_ext_accepted = array(
      ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
      ".html", ".xml", ".tiff", ".jpeg", ".png" );

......
......
......  
  /** upload()
   **
   ** Method to upload the file.
   ** This is the only method to call outside the class.
   ** @para String name of directory we upload to
   ** @returns void
  **/
  function upload( $dir ){
    
    $ret = $this->isUploadedFile();
    
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->setDir( $dir );
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->checkExtension();
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->checkSize();
    if( $ret != 1 ){
      return $this->resultUpload( $ret );    
    }
    
    // if flag to check if the file exists is set to 1
    
    if( $this->cls_file_exists == 1 ){
      
      $ret = $this->checkFileExists();
      if( $ret != 1 ){
        return $this->resultUpload( $ret );    
      }
    }

    // if we are here, we are ready to move the file to destination

    $ret = $this->move();
    if( $ret != 1 ){
      return $this->resultUpload( $ret );    
    }

    // check if we need to rename the file

    if( $this->cls_rename_file == 1 ){
      $ret = $this->renameFile();
      if( $ret != 1 ){
        return $this->resultUpload( $ret );    
      }
    }
    
    // if we are here, everything worked as planned :)

    return $this->resultUpload( "SUCCESS" );
  
  }
......
......
...... 
};

相比于前一关多了对后缀名检测,所以我们只能传图片马,而且需要在图片马没有被重命名之前访问它。要让图片马能够执行还要配合其

他漏洞,比如文件包含,apache解析漏洞等。

此题可以结合文件包含漏洞

先创建2.php,写入一句话木马

');?>

利用cmd命令合成图片马

在这里插入图片描述

上传图片马,然后流程跟第十八关类似

不过要修改脚本,因为是结合文件上传漏洞

import requests
url = "http://upload-labs-master/include.php?file=upload/3.png"
while True:
    html = requests.get(url)
    if ( 'Warning'  not in  str(html.text)):
        print('ok')
        break

bp开始攻击

upload-labs靶场通关详解_第45张图片

攻击时运行脚本

upload-labs靶场通关详解_第46张图片

然后蚁剑连接

(注意URL,因为我们修改文件,保存的位置是在根目录)

upload-labs靶场通关详解_第47张图片

Pass-20

源代码

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

分析源代码,首先会对文件名后缀检测,上传文件类型不能在黑名单中

然后通过pathinfo()内置函数,$file_ext变量将包含$file_name中的文件扩展名(不包括点号)

然后拼接路径$img_path = UPLOAD_PATH . '/' .$file_name;

方法一(文件夹名欺骗绕过)

由于题目的保存文件名是可控的

upload-labs靶场通关详解_第48张图片

我们可以借助move_uploaded_file()的特性会忽略掉文件末尾的 /来进行绕过

(即保存的文件名可以为upload-19.php/.

我们上传php文件的一句话木马

抓包,修改两个位置绕过检测

upload-labs靶场通关详解_第49张图片

成功getshell

(注意URL末尾没有.)

upload-labs靶场通关详解_第50张图片

当然,保存的文件名可以为upload-19.php.

upload-labs靶场通关详解_第51张图片

也能绕过

upload-labs靶场通关详解_第52张图片

方法二(%00截断攻击)

文件保存为upload-19.php%00.jpg也能绕过

(不过版本问题,上传不成功)

Pass-21

源代码

$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
    //检查MIME
    $allow_type = array('image/jpeg','image/png','image/gif');
    if(!in_array($_FILES['upload_file']['type'],$allow_type)){
        $msg = "禁止上传该类型文件!";
    }else{
        //检查文件名
        $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 = "请选择要上传的文件!";
}

注:

reset() 获取数组的第一个元素

end() 获取数组的最后一个元素

count()获取数组或对象的元素数量(至关重要

分析源代码:

  1. 首先是MIME检测
  2. 继续运用三元运算符判断POST的参数是否为空
  3. 然后再判断是否为数组,若不为则根据点号分开(即让文件名和扩展名分别为数组的值)
  4. 接着将拓展名即$file[count($file) - 1]与白名单对比
  5. 最后若合法则拼接路径

绕过条件比较难,不过可以利用POST传参数组

  • 只需要让第一个值即save_name[0]=upload-20.php.php是为了能被解析)
  • 然后再让数组最后一个值为jpg就能绕过

但是这里就有问题,为什么最后一个值jpg不会拼接路径里呢

因在于这个拼接过程用的是count函数,如果数组有三位,但是有一位为空,最后count出来的数就为2,而非为3。

所以我们传参save_name[2]=jpg,让save_name[1]为空即可

上传抓包

upload-labs靶场通关详解_第53张图片

成功getshell

upload-labs靶场通关详解_第54张图片

你可能感兴趣的:(文件上传,web安全,php)