upload-labs通关记录

upload-labs通关记录,第1张

目录

Pass-01-JS绕过

Pass-02 文件类型绕过

Pass-03 黑名单绕过

Pass-04 .htaccess绕过

Pass -05 后缀大小写绕过

Pass-06 空格绕过

Pass-07 点绕过

Pass-08 ::$DATA文件流特性绕过

Pass-9-点+空格+点绕过

Pass-10 双写绕过

Pass-11 %00截断

Pass -12 00截断

Pass-13 图片马

Pass - 14 getimagesize()-图片马

Pass-15-exif_imagetype()-图片马

Pass -16 图片马+二次渲染+文件包含

Pass-17-条件竞争

Pass-18-条件竞争

Pass-19-00截断

Pass -20 / + 数组 绕过

Pass-21 MIME、数组、%00绕过


Pass-01-JS绕过

开启代理抓包,发现没有产生流量,说明是前端js验证

#解决思路:
1、禁用js脚本 
2、直接修改前端代码,允许上传.php文件或者删除οnsubmit="return checkFile()函数

Pass-02 文件类型绕过

上传一个php文件,返回提示为文件类型不正确

这里猜测应该是对文件类型进行过滤。

#查看源码
$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: application/octet-stream改为Content-Type: image/jpeg

 上传成功,查看地址,连接蚁剑。

 

 

Pass-03 黑名单绕过

上传一个php文件,提示我们过滤了一些后缀名的文件

#解决思路:
上传其他可以解析的后缀名文件进行绕过
如 .phtml .phps .php5 .pht

 上传一个php文件,进行抓包,修改后缀名为1.php5,返回数据包,上传成功

 并且还可以找到上传文件返回的路径。

 #这里的文件名之所以被重名命,是由于源码中对文件名进行了重名命

Pass-04 .htaccess绕过
#源码
$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 . '文件夹不存在,请手工创建!';
    }
}

观察源码。这里几乎对所有的文件后缀名都进行了黑名单过滤。         

#这里会学习一个新的知识点-.htaccess 绕过
.htaccess是一个纯文本文件,它里面存放着Apache服务器配置相关的指令。
.htaccess主要的作用有:URL重写、自定义错误页面、MIME类型配置以及访问权限控制等。主要体现在伪静态的应用、图片防盗链、自定义404错误页面、阻止/允许特定IP/IP段、目录浏览与主页、禁止访问指定文件类型、文件密码保护等。
 #简单的说就是:上传.htaccess文件,可以重写文件解析规则绕过

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

上传webshell,根据提示,为黑名单绕过,并且限制了.htaccess文件的上传  

 #观察提示发现,没有过滤大小写混合绕过。可以尝试进行大小写绕过
#将上传的1.php文件通过burp抓包修改为1.PHP,返回数据包,上传成功,成功连接蚁剑

Pass-06 空格绕过

与上一题的大小写绕过,这里的区别就是没有对空格进行处理。

#思路
在末尾添加空格,进行空格绕过,返回数据包,成功连接蚁剑

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 = 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);//删除文件名末尾的点
#思路
点绕过,在文件名后面加点,进行绕过

返回数据包,上传成功,成功连接蚁剑

Pass-08 ::$DATA文件流特性绕过
#源码
$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 . '文件夹不存在,请手工创建!';
    }
}

#观察源码的过滤条件发现,这里的条件没有
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
#思路
::$DATA上传绕过(这是什么意思?)
#在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名
例如:"phpinfo.php::$DATA"Windows会自动去掉末尾的::$DATA变成"phpinfo.php"
所有这里我们直接在文件名后面加上::$DATA即可!

 

返回数据包,上传成功,成功连接蚁剑  

Pass-9-点+空格+点绕过
#源码
$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 . '文件夹不存在,请手工创建!';
    }
}

#观察发现,这里的过滤条件全部都有,我的思路是构造后缀名,抵消掉过滤条件,最后剩下的就是可以上传的文件名。
这里主要看两个过滤条件。
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = trim($file_ext); //首尾去空


通过这两个条件,我们可以先构造1.php .  当上传该后缀文件时,代码会先去掉末尾的点,再去掉末尾的空格,我们上传的文件就变成了1.php 发生存在黑名单绕过,无法上传。
后面观察代码发现了这条语句
 $file_ext = strrchr($file_name, '.');  --什么意思呢?
 strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。语法:strrchr(string,char)
 意思就是查找'.'最后一次出现的位置,并且返回这个位置到结尾的所有字符串,那不就是查看我们的后缀名是什么嘛,比如1.php 通过该语句处理返回的就是.php 与黑名单进行比较。


 所有我们现在有思路了,那就是只要让最后返回的东西不在黑名单里面就可以了
 构造1.php. . 最终返回1.php. 上传成功,再利用windows特性,会自动去掉后缀名中最后的”.”,最终我们上传的文件就变成了1.php  

果然如我们所想,文件最终返回1.php.上传到我们的文件目录中。

 再利用windows特性,会自动去掉后缀名中最后的”.”,最终我们上传的文件就变成了1.php

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","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini");

        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = str_ireplace($deny_ext,"", $file_name);
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = UPLOAD_PATH.'/'.$file_name;        
        if (move_uploaded_file($temp_file, $img_path)) {
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

#这里我先上传一个1.php,发现上传成功,查看路径,文件后缀名php没有了,也就是没有了文件类型。

#观察源码,发现了str_ireplace函数
str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。
格式为str_ireplace(find,replace,string,count)
 $file_name = str_ireplace($deny_ext,"", $file_name);
 这里的意思就是搜索$file_name,与$deny_ext(黑名单),再将$file_name替换为空,即过滤掉文件类型
 #思路
 双写文件后缀名,绕过str_ireplace函数

 

 成功上传!

Pass-11 %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 = $_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类型文件!";
    }
}

#何为00截断
1、0x00截断
0x00是十六进制表示方法,是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符。这个可以用在对文件类型名的绕过上
这里主要是对文件的目录/upload/下手,由post方式上传1.jpg ,并且在目录中添加1.php 返回的结果就变为了1.php1.jpg
#原理
系统在对文件名的读取时,如果遇到0x00,就会认为读取已结束。0x表示16进制
0x:16进制表示
00:表示0
0x00:就是代表16进制的0

#思路

1、取后缀名: $file_ext=png 后缀名在白名单中,符合
2、拼接上传路径:$img_path=…/upload/1.php/3220210812084323.png (1.php后面的%00不见了,因为他变成了hex值为00的结束字符,所以看不见)
3、将上传的文件移动到新位置 :move_uploaded_file函数在进行文件移动的时候,在读取$img_path的值的时候,读到1.php的后面时,遇到了hex值为00的结束字符,他会认为$img_path的值读取完毕,这个时候$img_path=…/upload/1.php,最后上传的文件名为1.php,实现了00截断。

Pass -12 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获得,需要在hex里面去进行修改

Pass-13 图片马
#源码
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 = "上传出错!";
        }
    }
}

这里通过读文件的前两个字节判断文件的类型。因此直接 上传图片马即可,制作图片马

copy 1.jpg /b + shell.php /a shell.jpg

上传成功后,查看图片地址可以得到上传图片的名字。

 这里需要注意的是:直接访问图片并不能把图片当做PHP解析,因此还需要利用文件包含漏洞 。

  
Pass - 14 getimagesize()-图片马
#源码
function isImage($filename){
    $types = '.jpeg|.png|.gif';
    if(file_exists($filename)){
        $info = getimagesize($filename);
        $ext = image_type_to_extension($info[2]);
        if(stripos($types,$ext)>=0){
            return $ext;
        }else{
            return false;
        }
    }else{
        return false;
    }
}

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $res = isImage($temp_file);
    if(!$res){
        $msg = "文件未知,上传失败!";
    }else{
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传出错!";
        }
    }
}

这题是用getimagesize函数判断文件类型,还是可以图片马绕过,方法同pass-13,上传成功后连接蚁剑。

Pass-15-exif_imagetype()-图片马
#源码
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模块来判断文件类型,用图片马绕过,方法同pass-13

Pass -16 图片马+二次渲染+文件包含

此题麻烦的地方在于找出二次渲染后,图片没有被改变的地方。

请参考如下链接: upload-labs16(二次渲染)_Luckysec的博客-CSDN博客_文件上传二次渲染

Pass-17-条件竞争
$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 = '上传出错!';
    }
}

这里是条件竞争,先将文件上传到服务器,然后判断文件后缀是否在白名单里,如果在则重命名,否则删除,因此我们可以上传1.php只需要在它删除之前访问即可,可以利用burp的intruder模块不断上传,然后我们不断的访问刷新该地址即可.

Pass-18-条件竞争
//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" );
  
  }
......
......
...... 
};

 因此也存在条件竞争的问题,不过这题对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,因此可以通过不断上传图片马,由于条件竞争可能来不及重命名,从而上传成功。

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

发现move_uploaded_file()函数中的img_path是由post参数save_name控制的,因此可以在save_name利用00截断绕过,方法同pass-12

Pass -20 / + 数组 绕过
$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 = "请选择要上传的文件!";
}

pathinfo(path,options) 函数以数组的形式返回文件路径的信息。

思路:源码类似与第12、13关只不过是,这关作者是用POST方法来对我们的文件名进行接收,同时拼接到路径上去,那么这就和我们第13关类似,只不过是13关是由POST接收的路径名,而这关只接收了文件名。但是两关所要考察我们的内容应该是一样的

我们首先上传一个php脚本,然后在save_name文件名的后面添加%00(注意要URL解码,或者更改16进制码

最后上传成功。

Pass-21 MIME、数组、%00绕过
$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 = "请选择要上传的文件!";
}

作者首先检查了我们上传文件的MIME类型,然后定义了允许的上传类型,然后判断我们上传文件的类型,如果我们上传的文件类型在白名单里面,然后判断我们由POST接收的文件名是否为空,如果为空,那么我们上传文件就会保存为原来的文件名,如果不为空,那么我们上传的文件名会保存为,我们POST接收的文件名。然后作者判断了我们的file变量如果不是数组,那么我们将file变量先转换为小写然后再用explode打成数组(以点为分隔符),然后取它的后缀名,并且定义了一个允许上传的后缀名数组,然后判断如果我们取的后缀名在白名单里面,然后取到了我们的文件名,然后进行移动

 思路:结合我上面对源码的讲解,其实这关我们需要注意几个点,一个是如果上传的是php文件,那么记得要改MIME类型,这样第一层我们突破了,二我们需要上传一个数组,否则我们只要上传后缀名为php的文件,就会被拦截,所以我们需要抓包更改我们上传的文件为数组,然后在路径那块,运用%00截断

可以参考如下链接:https://blog.csdn.net/m0_46436640/article/details/107809772?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.opensearchhbase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.opensearchhbase#Pass21_MIME00_1489

如果有错误的地方,希望各位指正出来,如果有更好方法,,欢迎大家来一起交流。

目录

Pass-01-JS绕过

Pass-02 文件类型绕过

Pass-03 黑名单绕过

Pass-04 .htaccess绕过

Pass -05 后缀大小写绕过

Pass-06 空格绕过

Pass-07 点绕过

Pass-08 ::$DATA文件流特性绕过

Pass-9-点+空格+点绕过

Pass-10 双写绕过

Pass-11 %00截断

Pass -12 00截断

Pass-13 图片马

Pass - 14 getimagesize()-图片马

Pass-15-exif_imagetype()-图片马

Pass -16 图片马+二次渲染+文件包含

Pass-17-条件竞争

Pass-18-条件竞争

Pass-19-00截断

Pass -20 / + 数组 绕过

Pass-21 MIME、数组、%00绕过


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1321048.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-11
下一篇 2022-06-11

发表评论

登录后才能评论

评论列表(0条)

保存