美文网首页
文件上传漏洞靶场--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