upload-labs-env文件上传漏洞 1-10关
阅读原文时间:2023年07月15日阅读:1

Pass-01

首先先看源码:

function checkFile() {
var file = document.getElementsByName('upload_file')[].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 + "|") == -) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}

源码发现是前段验证上传文件,那么前段验证绕过的方法就很多也很简单啦

  前段的绕过:

1、修改前段的JS,添加白名单

2、浏览器解析禁用JS

3、破坏JS代码,修改引用的地方

4、修改webshell后缀名,shell.php->shell.png,拦截数据包,修改后缀名,最后放行

Pass-02

源码:

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
$img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
$is_upload = true;

        }  
    } else {  
        $msg = '文件类型不正确,请重新上传!';  
    }  
} else {  
    $msg = $UPLOAD\_ADDR.'文件夹不存在,请手工创建!';  
}  

}

在响应中,Content-Type标头告诉客户端实际返回的内容的内容类型

看代码发现是Content-Type请求头白名单验证,那么好我满足你

上传shell.php文件-》抓包-》修改Content-Type请求头为image/jpeg-》上传成功

Pass-03

源码:

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$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)) {  
        if (move\_uploaded\_file($\_FILES\['upload\_file'\]\['tmp\_name'\], $UPLOAD\_ADDR. '/' . $\_FILES\['upload\_file'\]\['name'\])) {  
             $img\_path = $UPLOAD\_ADDR .'/'. $\_FILES\['upload\_file'\]\['name'\];  
             $is\_upload = true;  
        }  
    } else {  
        $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';  
    }  
} else {  
    $msg = $UPLOAD\_ADDR . '文件夹不存在,请手工创建!';  
}  

}

通过源码发现这个限制有点多啊=。=,

什么大小写绕过啊,利用windows系统特性的空格和.绕过啊,NTFS文件流绕过啊,MIME验证绕过都不能用啊

最后发现用服务器解析特性可以进行绕过

如以下后缀名有可能被解析为前面的文件(需要服务器的配置文件有解析的配置)

ASP:asa/cer/cdx

ASPX:ashx/asmx/ascx

PHP:php4/php5/phtml

JSP:jspx/jspf

操作步骤:上传shell.php-》抓包-》修改文件为shell.phtml-》上传成功-》成功连接蚁剑(直接连接shell.phtml文件就好)

Pass-04

源码:

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".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)) {  
        if (move\_uploaded\_file($\_FILES\['upload\_file'\]\['tmp\_name'\], $UPLOAD\_ADDR . '/' . $\_FILES\['upload\_file'\]\['name'\])) {  
            $img\_path = $UPLOAD\_ADDR . $\_FILES\['upload\_file'\]\['name'\];  
            $is\_upload = true;  
        }  
    } else {  
        $msg = '此文件不允许上传!';  
    }  
} else {  
    $msg = $UPLOAD\_ADDR . '文件夹不存在,请手工创建!';  
}  

}

源码中除了把03关的禁用了之外,基本跟03相同。

在发现没有前段过滤的情况下,果断的使用.htaccess文件绕过

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

1、创建1.htaccess文件,写入如下代码

SetHandler application/x-httpd-php

代码主要作用于把jpg的文件当做php的代码来执行

2、把一句话木马文件改为.jpg格式

3、把1.htaccess和shell.jpg文件分别上传

4、使用蚁剑连接shell.jpg成功

Pass-05

源码:

if (file\_exists($UPLOAD\_ADDR)) {  
    $deny\_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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); //首尾去空

发现源码中什么都有,就是没有大小写绕过,那么好后缀大小写绕过

把shell.php改为shell.PhP

上传shell.PhP文件

Pass-06

源码:

if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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

缺少首尾去空

利用Windows系统特性,以空格和.结尾的文件对于windows来说,是不允许的,最后保存的 时候把空格和.去掉

上传顺序:上传文件shell.php-》抓包-》在shell.php后面加个空格-》上传成功-》蚁剑连接成功

Pass-07

源码:

if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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); //首尾去空

缺少删除文件名末尾的点

利用Windows系统特性,以空格和.结尾的文件对于windows来说,是不允许的,最后保存的 时候把空格和.去掉

上传顺序:上传文件shell.php-》抓包-》在shell.php后面加个点.-》上传成功-》蚁剑连接成功

Pass-08

源码:

if (file\_exists($UPLOAD\_ADDR)) {  
    $deny\_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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); //首尾去空

没有去除字符串::$DATA,选择利用NTFS文件流绕过,具体如下

我们这里选择Test.php::$DATA

上传顺序:上传文件shell.php-》抓包-》在shell.php后面加上::$DATA-》上传成功-》蚁剑连接成功

上传成功的文件名为shell.php

Pass-09

源码

if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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); //首尾去空

可以看到源码的处理顺序为,1、删除文件末尾的点,最后在去空

那我们写一个shell.php. . 的文件处理出来是什么样子呢?

答案是shell.php.

所以我们通过bp抓包之后修改文件名为:shell.php. .就可以了

那么最后上传出来的文件是这个样子的 shell.php  所以我们就可以为所欲为啦=。=

Pass-10

源码:

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists($UPLOAD_ADDR)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","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);  
    if (move\_uploaded\_file($\_FILES\['upload\_file'\]\['tmp\_name'\], $UPLOAD\_ADDR . '/' . $file\_name)) {  
        $img\_path = $UPLOAD\_ADDR . '/' .$file\_name;  
        $is\_upload = true;  
    }  
} else {  
    $msg = $UPLOAD\_ADDR . '文件夹不存在,请手工创建!';  
}  

}

$file_name = str_ireplace($deny_ext,"", $file_name);
可以看到上面这句话的大概意思是:如果有黑名单的后缀出现则转换为空

那么能不能也像SQL注入的那样进行双写或者重写呢?

pphphp和phphpp两种双写方式输出的后缀一样吗?

pphphp通过解析完的后缀是php   p后面的php通过上面的代码直接转换为了空 所以输出php

而phphpp解析完的后缀则是hpp  所以这种双写是不可以用的

所以我们通过bp抓包之后修改文件名为:shell.pphphp就可以了