前言

我是根据upload-lab来总结文件上传漏洞。
思维导图:
VtMs0S.png

pass-01

提示:在客户端使用js对不合法图片进行检查!
所以我们可以通过抓包,改包就可以绕过。。。

pass-02

提示:服务端对数据包的MIME进行检查!

这里是对Content-Type: 进行验证。所以改一下

Content-Type: image/jpeg

VtQA1I.png
就可以上传上webshell。

pass-03

提示:禁止上传.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 . '文件夹不存在,请手工创建!';
    }
}

发现是黑名单限制。我们可以通过使用其他的别名:

PHP: php2、php3、php5、phtml、pht 
ASP: aspx、ascx、ashx、cer、asa 
JSP: jspx 

我的是php环境,上传别名后发现文件上传成功,但是不能被apache解析

查资料发现需要修改httpd.conf:(#号是注释符)

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

这样apache才会把文件解析成php。

pass-04

提示:禁止上传.php|.php5|.php4|.php3|.php2|php1|.html|.htm|.phtml|.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后缀文件!

这里的黑名单比较全了,但是它少了.htaccess

htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。

也就是说,我们能控制这个目录的解析方式。
这里我们可以上传文件名为.htaccess的文件,里面写上:

SetHandler application/x-httpd-php

这是把目录下的文件当作php来解析。
这时我们可以上传一个图片马,就可以当做php文件来解析。。。
即weshell

pass-05

这一关增加了.htaccess限制。
查看源码:

$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); //首尾去空

发现他没有忽略大小写。。这时我们就可以通过大小写绕过。

pass-06

这关同上关一样,黑名单很全。需要查看源码:

$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

发现没有去除文件名末尾的空格。这里就可以在文件名后加空格来绕过过滤。。。

pass-07

查看源码:

$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); //首尾去空

发现没有删除文件末尾的点。然后就是windows操作系统的一个特性:

在windows操作系统中,会自动去掉后缀名中的“.”

所以我们可以通过在文件名后加点来绕过过滤。。。

pass-08

查看源码:

$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); //首尾去空

发现缺少去除::$DATA。
这是windows系统的一个特性:

VtxSs0.png

所以这里我们可以在文件名后面加上::$DATA来绕过过滤。。

pass-09

$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); //首尾去空

这里,先去掉文件末尾的点再去空格。然而只去掉一次。所以可以使用文件名后加点空格点的方式来绕过。。。

pass-10

这关对文件名进行去除可解析后缀替换成空。。然而只替换一次。。。所以这里就存在双写后缀绕过过滤。

pass-11

这关提示文件路径可控。

这里指的是move_uploaded_file中的save_path可控。这里存在%00截断.
这里有版本限制:
5.4.x<= 5.4.39, 5.5.x<= 5.5.23, 5.6.x <= 5.6.7
我没有环境,没有得到webshell。

pass-12

方式同上。。。只是请求方式变了。

pass-13

提示:
本pass检查图标内容开头2个字节!
只需在图片末尾加上木马就行。。

pass-14

提示:
本pass使用getimagesize()检查是否为图片文件!

这样上一关的方式就不行了。
需要我们制作图片马。
在cmd下执行:

copy 图片名/b+马文件名 生成图片马名

就可得到图片马。上传即可。

pass-15

提示:
本pass使用exif_imagetype()检查是否为图片文件

方法同上

pass-16

这关对图片进行了二次渲染

gif只需要找到渲染前后没有变化的位置,然后将php代码写进去,就可以了。

jpg图片可以通过脚本进行实现。
命令:

使用脚本处理1.jpg,命令php jpg_payload.php 1.jpg

png请参考学长的文章:
二次渲染绕过

pass-17

$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 = '上传出错!';
    }
}

可以看到文件先经过保存,然后判断后缀名是否在白名单中,如果不在则删除,此时可以利用条件竞争在保存文件后删除文件前来执行php文件。
抓包。
VNSF29.png

一边上传文件
VNpnLq.png
一边访问文件
VNpQoT.png

最后成功执行命令:
VN9gCF.png

pass-18

方式同上。

Pass-19

利用文件名加点来绕过检测

Pass-20

$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 = "请选择要上传的文件!";
}

可以发现$file_name经过reset($file) . '.' . $file[count($file) - 1];处理。

如果上传的是数组的话,会跳过$file = explode('.', strtolower($file));。并且后缀有白名单过滤.

而最终的文件名后缀取的是$file[count($file) - 1],因此我们可以让$file为数组.

$file[0] = alex.php
$file[2] = jpg

我们没有定义$file[1],所以count($file)等于2,那么$file[count($file)-1]就为空,最后文件名就是$file[0]。

总结:

姿势很多。还需努力…

  • bypass disfunction

    前言PHP 的 disabled_functions主要是用于禁用一些危险的函数防止攻击者执行系统命令。但是有一些绕过方法。这里做个总结。 基本思路有四种绕过 disable_functions 的手法:第一种,攻击后端组件,寻找存在...

    bypass disfunction
  • RCE提高篇

    前言首先,需要了解一下命令执行的函数,这里推荐几篇文章,来认识这些函数。浅谈eval和assert从底层分析eval和assert的区别命令执行与代码执行的小结巧用命令注入的N种方式命令注入绕过姿势我就不在说这几个东西,大牛们都说的很...

    RCE提高篇
  • php代码审计之文件包含

    文件包含文件包含分为本地文件包含(Local File Inclusion,简LFI)和远程文件包含(Remote File Inclusion,简RFI)。 在php中常见的文件包含函数有: include() include_on...

    php代码审计之文件包含
  • sql注入知识总结

    前言最近,感觉知识学的有点混乱,来整理一波自己的知识。先总结一下sql注入吧。 知识储备sql注入中常用到的库和表information_schema库 这个数据库中保存着mysql服务器所保存的所有的其他数就库的信息,如数据库名,...

    sql注入知识总结
  • linux基本操作

    centos常用命令及快捷键整理常用linux命令文件和目录cd /home 进入 '/home' 目录 cd .. 返回上一...

    linux基本操作
  • linux查看系统信息

    linux系统下经常查看各种信息,总结一下。 系统uname -a # 查看内核/操作系统/CPU信息 head -n 1 /etc/issue # 查看操作系统版本 cat /etc/issue | ...

    linux查看系统信息
  • linux三剑客

    前言之前用一些脚本都经常用到grep,sed,awk。但是一直不太熟悉,今天来学习一下,做个备忘录。 grep格式: grep [OPTIONS] PATTERN [FILE...] grep [OPTIONS] [-e PATTER...

    linux三剑客
  • i春秋2020新春战“疫”网络安全公益赛 web Writeup

    前言这次比赛题目质量挺好的,除啦环境可能有时候有点问题。(就让我遇到了。心态炸了一天。。。)其他都挺好的。 DAY1简单的招聘系统知识点:sql注入的联合注入或盲注存在注册和登陆功能,首先进行注册后登陆进系统,发现有一个模块是管理员才...

    i春秋2020新春战“疫”网络安全公益赛 web Writeup
  • 计算机组成原理学习

    计算机组成原理第一章 计算机系统概论计算机系统的层次结构 冯·诺依曼计算机的特点 计算机由运算器、存储器、控制器、输入设备和输出设备五大部件组成 指令(程序)和数据以二进制同等地位地存储在存储器中,可按址寻访 指令由操作码和地址码组...

    计算机组成原理学习
  • 2019安洵杯+2019广外比赛web部分题解

    2019安洵杯easy_web知识点:MD5强碰撞,命令执行这个题比较简单,看题目发现传入参数img和cmd,然而图片是传入的img参数控制,让我想到ddctf的一道题,然后发现img是通过把文件名进行转十六进制后两次base64编码...

    2019安洵杯+2019广外比赛web部分题解