• 文件上传方法总结


    以upload-labs讲解   

    项目地址https://github.com/c0ny1/upload-labs/releases

    每道题都要通过上面这张图判断文件校验的方式,才能有大体绕过思路


    PASS 01      前端js校验

    image尝试上传符合条件的文件,将一句话木马后缀改为jpg,抓包修改成php文件。

    PASS 02       MIME文件类型校验

    image

    提示文件类型不正确,可能是MIME校验

    image

    image


    PASS 03        php多种扩展名绕过

    上传php文件时出现提示,php被加入了黑名单,并且会将上传的文件重新命名,无法通过上传.htaccess文件绕过,大小写失败了,尝试上传php3,phtml等其他扩展名文件绕过黑名单限制

    image

    image


    PASS 04     上传.htaccess文件绕过

    image

    通过上传jpg图片发现文件名并未改变,但是各种扩展名大小写都被限制,尝试上传.htaccess文件,内容为

    SetHandler application/x-httpd-php
    

    将所有文件解析为ph执行,此时上传文件改为jpg格式成功上传,查看解析


    PASS 05    后缀名大写绕过

    将后缀名大写绕过

    PASS 06      Windows特性文件命名规则

    相比前几题,大小写绕过和上传.htaccess文件已经行不通了。查看源代码没有去掉末尾的空格,那可以利用Windows的特性,Windows下xx.jpg[空格]xx.jpg.这两类文件都是不允许存在的,若是这样命名,Windows会默认除去空格或点。

    上传1.php,抓包修改为1.php[空格]

    image


    PASS 07       Windows特性文件命名规则

    原理同pass 06,通过Windows文件命名规则绕过,抓包将文件改为1.php.即可

    综合pass06和pass07,碰到此类型的都可以将文件修改为1.php[空格].


    PASS 08      Windows特性   ::$DATA绕过

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

    抓包修改1.php为如图所示

    image

    上传成功后查看链接,链接为http://192.168.135.144/upload/202004231705477566.php::$data

    查看http://192.168.135.144/upload/202004231705477566.php 即为已上传文件

    image


    PASS 09

    从源码可以看出这次拼接的路径是$file_name的值,结合Windows特性构造文件

    image

    image

    image


    PASS 10     后缀名双写绕过

    通过上传1.php文件后查看文件后缀.php被过滤,猜测可能之过滤一次,尝试双写后缀名绕过,这里双写要注意:1.pphphp和1.phphpp产生的文件是不同的,过滤是从左往右的,所以1.phphpp会生成文件1.hpp

    image


    PASS 11     %00截断绕过

    通过测试得知是后端白名单限制,对内容并未过滤

    image

    image

    代码分析发现最终返回的图片链接是”存储路径名+重命名后的文件名“,看到这个我们可以联想到使用%00截断路径。

    截断条件:1.php版本小于5.3.4        2.php.ini的magic_quotes_gpc为OFF状态(默认为OFF)

    image

    image

    访问链接http://192.168.135.144/upload/1.php  上传成功

    image


    PASS 12     %00截断绕过

    image

    同pass 11一样使用00截断绕过,但这里是通过POST方式,由于POST不像GET可以自动解码%00,所以需要手动解码,如下

    image

    image

    访问http://192.168.135.144/upload/2.php   上传成功


    PASS 13   文件内容头部检测

    分析代码可知通过读文件的前2个字节判断文件类型,因此直接上传图片马即可,制作方法:

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

    成功上传后利用的话还需结合文件包含漏洞。


    PASS 14     文件内容头部检测

    通过代码得知这里使用getimagesize获取文件类型,直接上传图片马可绕过


    PASS  15     图片马绕过

    这里用到php_exif模块来判断文件类型,同样可以利用图片马直接绕过

    PASS 16    图片二次渲染

    绕过思路:对比上传前和上传后的图片的差异,找到相同数据同时又是非图片数据区的地方,在此处写入恶意代码。不同的图像类型插入方式有区别。

    GIF

    GIF的二次渲染绕过是最简单的,将源文件和二次渲染过的文件进行比较,找到源文件中没有被修改的那段区域,写入PHP代码即可。 使用工具winhex

    802776a027b4b20d43c42b91f8e7ce2a

    PNG和JPG通过脚本可以生成,使用方法:

    1.先将一张正常的jpg图片上传,上传后将服务器存储的二次渲染的图片保存下来。

    2.将保存下来经过服务器二次渲染的那张jpg图片,用脚本进行处理生成payload.jpg

    3.然后再上传payload.jpg


    PASS 17  利用竞争条件绕过

    可以从代码看到,文件是先上传再判断是否是合法文件,不是则将文件删除

    image

    绕过思路:可以上传一个php文件,文件的功能是写一句话木马,然后再重复访问该php文件,目的是卡在删除之前执行该文件,上传的php文件代码如下:

    <?php
    
    fputs(fopen('eval.php','w'),'<?php eval($_POST[cmd]);?>');
    
    ?>
    

    <?php $f= fopen ("shell.php","w") ; fputs ($f,'<?php phpinfo();?>'); ?>


    PASS 18   条件竞争上传图片马


    PASS  19   利用/.达到00截断的效果

    move_uploaded_file会忽略掉文件末尾的/.

    image

    因此可以构造smile.php/. 达到00截断的作用image.png



    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]smi1e.php/,也就是reset($file),然后再令$file[2]为白名单中的jpg。
    此时end($file)等于jpg,$file[count($file) - 1]为空。
    $file_name = reset($file) . '.' . $file[count($file) - 1];,也就是smi1e.php/.,最终move_uploaded_file会忽略掉/.,最终上传smi1e.php

    image.png

    image.png

  • 相关阅读:
    sys.stdout.flush-倒计时
    wget 网站扒取
    万能英数脚本
    sample function
    get_time
    读取指定行
    request设置cookies
    resize2fs
    闭包与认识装饰器
    函数的名称空间与作用域
  • 原文地址:https://www.cnblogs.com/sup3rman/p/12767936.html
Copyright © 2020-2023  润新知