美文网首页
文件上传漏洞靶场--c0ny1 / upload-labs

文件上传漏洞靶场--c0ny1 / upload-labs

作者: Pig_deng饲养员 | 来源:发表于2022-12-13 20:13 被阅读0次

c0ny1/upload-labs

c0ny1/upload-labs是一个文件上传漏洞靶场,地址:https://github.com/c0ny1/upload-labs

以docker方式安装并启动,在这里我启动的是81端口,可以自行设置端口:

$ docker pull c0ny1/upload-labs
$ docker run -d -p 81:80 upload-labs:latest

启动后,打开靶场 127.0.0.1:81,可以看到一共有20关:


upload-labs

创建upload文件夹

随意上传一个png文件进行测试,提示“../upload文件夹不存在,请手工创建!”


提示

进入docker容器创建文件夹

### 查看运行的docker id
docker ps -a 

### 进入docker bash
docker exec -it dockerId /bin/bash

### 在 /var/www/html路径下创建upload文件夹
mkdir upload

### 修改文件夹的所有者为 www-data:www-data
chown www-data:www-data upload

此时重新上传png图片,能够成功上传。


成功上传

Pass-01

随意上传一个php文件,可以看到提示只允许上传.jpg .png .gif类型的文件,属于白名单检测

pass-01

将一句话木马文件名修改为test.png,抓包获取数据包,修改文件后缀为.php,判断是否只是前端验证,以及能够控制的输入是什么
从数据包中可以看到,能控制的输入是文件名,修改文件后缀为.php

修改png为php
可以看到能够成功上传,进行元素审查,获取上传的路径为../upload/test.php
上传结果
浏览器访问../upload/test.php,能够成功访问
访问成功
使用curl,执行post请求访问一句话木马,可以看到成功执行
访问一句话木马执行成功
查看源码

从源码中看,在前端进行了后缀检测

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

Pass-02

随意上传.php文件,提示文件上传类型不正确

提示
随意修改文件后缀为.php3 .phpt .phptml .123判断是否是黑名单,发现提示均为文件类型不正确,上传.png,可以成功上传,猜测应该为白名单检测,且是后台进行检测。
抓包查看数据包,发现仅能控制文件名,不能控制文件后缀。
对文件名后缀尝试00截断,能够成功上传,且能够成功访问我们的一句话木马
文件名尝试00截断
查看源码

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

再次尝试,抓包,修改文件类型,文件名仍为test.php,可以看到能够成功上传。

修改文件类型

Pass-03

随意上传php文件,提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!

黑名单检测
尝试修改后缀名

修改文件后缀为.php3,能够成功上传,进行图片审查,找到文件路径,可以看到这里对文件进行了重命名

修改文件后缀为php3
访问../upload/202212121105064700.php3,发现服务器把该文件当作文本文件进行处理,无法对.php3后缀进行解析。
服务器无法解析.php3后缀
尝试.htaccess上传

上传.htaccess文件

上传.htaccess
查看上传结果,可以看到成功上传,但是文件名被修改,该方法失败
上传结果
尝试大小写绕过

修改文件后缀为.pHp

大小写
上传失败,提示:不允许上传.asp,.aspx,.php,.jsp后缀文件!
查看源码

查看源码,可以看到对文件后缀名进行了大小写转换和黑名单限制

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

在网上查看了一些通关方法,发现都是修改文件后缀名为.php3 .php5 .phpt等特殊后缀,同时修改服务器的解析配置让服务器能够解析这样的特殊后缀。
如果是这样,尝试的第一种方法就对了,有疑问的是在实战中是无法直接修改服务器的解析配置的,那么这种方法也就无效了。

Pass-04

随便上传php文件,提示 :此文件不允许上传

Pass-04

随便上传.test后缀的文件,可以成功上传,且文件名没有被修改

.test后缀

上传.htaccess文件,文件内容为:AddType application/x-httpd-php .test,成功上传

.htaccess文件

访问phpinfo.test,可以看到成功访问,成功绕过


访问phpinfo.test
查看源码

查看源码,代码限制了特殊后缀,对后缀进行了大小写转换,去除了末尾加点。
文件名没有被修改,如果文件名被修改,.htaccess文件就不能被成功利用。

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");
        $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文件上传是不能被利用的,进入docker容器,查看Pass-04的实际代码,是上面的代码,没有修改文件名,注意这里的差别。

$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");
        $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 = '此文件不允许上传!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

Pass-05

随意上传.php文件,提示:此文件类型不允许上传

Pass-05
首先尝试一遍黑名单检测绕过的方法,大小写、特殊后缀、.htaccess等方法,发现都不可以上传;
尝试白名单检测绕过的00截断方法,查看数据包,只能够控制文件名,尝试进行文件名00截断,无法绕过;
尝试apache解析漏洞绕过,上传.php.abc后缀
上传.php.abc后缀
可以成功上传,但是文件名被修改为xxx.abc,文件名被随机修改,文件后缀为.abc
成功上传
猜测文件源码为获取最后一个点后面的后缀名,然后进行随机命名。

没有思路,最后看了别人的通关方法,发现是最简单的大小写绕过,.Php即可绕过,自己在尝试时只尝试了.pHp,所以以后要多尝试,或者可以尝试使用自动化工具进行尝试。

查看源码

从源码中可以看到,进行了各样的限制,包括.htaccess限制,但是没有进行大小写限制

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

Pass-06

随意上传php文件,提示:此文件不允许上传

Pass-06

尝试各种后缀绕过,发现无法绕过

尝试文件名00截断,提示:此文件不允许上传
尝试apache 解析漏洞,上传.php.test后缀,apache解析漏洞在无法解析后缀时会向前进行解析,直到遇到能解析的后缀为止。
该文件能成功上传,文件名被修改

上传.php.test文件后缀
访问上传的文件,可以看到文件被解析为.php文件
成功访问
查看源码
$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 = $_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

在浏览器里进行访问,发现文件以文件格式被解析,并没有以php的格式被解析。这里注意空格要进行url编码,输入%20,否则无法识别。


文件无法被解析
再次查看了其他人的通关攻略,可能是版本的原因,说是windows在存储时会自动去掉空格,所以能够成功解析。我的是docker版本,所以可能这是没有绕过的原因。

Pass-07

随意上传.php文件,提示:文件类型不允许上传
在文件名后缀加一个.,比如上传文件名为test.php.,即可上传成功
(我这里依旧是不能解析这个.结尾的文件)

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

从源码看,限制了对文件后缀点的限制。

Pass-08

这一关考察windows文件流特性。
在文件名后缀加上::$DATA,比如test.php::$DATA,能够成功上传。
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");
        $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 . '文件夹不存在,请手工创建!';
    }
}

可以看到,源码确实去掉了windows文件流特性的检查。

Pass-09

这一关代码把所有的限制都加上去了,查看源码和通关攻略可知,虽然代码对后缀进行了全面的限制,但是在拼接文件路径时,使用的是上传的文件名进行拼接,这样就有了操作的空间,可以对文件名进行构造来绕过限制。

源码

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

代码先对后缀名进行检查和转化,最后拼接路径时,使用上传的文件原名进行拼接,对文件名进行处理的是下面两行代码,因此只要绕过下面两行代码即可。因此选择对文件名进行构造,比如test.php. .即可上传成功且访问成功。

 $file_name = trim($_FILES['upload_file']['name']);
 $file_name = deldot($file_name);//删除文件名末尾的点

Pass-10

首先上传一个文件名为phpinfo.php的文件,成功上传,查看文件路径,发现文件名为info.
查看提示可知,代码会去除文件名中相应的字符。

提示
对文件名进行构造即可,构造info.pphphphpp,即php三个字符中间夹杂一个php,这样等程序去除php后,留下来的仍然是php后缀,经测试,能成功上传且访问
image.png

源码

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

Pass-11

Pass-12

Pass-13

Pass-14

Pass-15

Pass-16

Pass-17

Pass-18

Pass-19

Pass-20

相关文章

网友评论

      本文标题:文件上传漏洞靶场--c0ny1 / upload-labs

      本文链接:https://www.haomeiwen.com/subject/thsgfdtx.html