Imagemagick邂逅Getimagesize的那点事儿

访客4年前关于黑客接单704

  前段时间写的文章,在微博上说7月底结束分享一下,总算可以发了。感谢 @voidfyoo 提出的这个问题。

  今天遇到一个代码,大致如下:

  $filename=$_FILES['image']['tmp_name'];

  $size=getimagesize($filename);

  if ($size && $size[0] > 100 && $size[1] > 100) {

  $img=new Imagick($_FILES['image']['tmp_name']);

  $img->cropThumbnailImage(100, 100);

  $img->writeImage('newimage.gif');

  }

  用户上传的文件如果大于100px,则用Imagick处理成100×100的缩略图,再存储在硬盘上。

  通过这个代码,我们很容易想到用Imagemagick的漏洞进行测试,但这里前面对图片大小用getimagesize进行了限制,之前爆出来的那些POC均无法通过校验,因为getimagesize并不支持类似PostScript、MVG这样的图片格式。

  这时候我们怎么绕过这个限制呢?

  0×01 Imagemagick命令执行不完全回顾

  Imagemagick历史上曾出现过的很多命令执行漏洞,我在vulhub里做过以下三个:

  1.CVE-2016-3714

  2.CVE-2018-16509

  3.CVE-2019-6116

  之一个是Imagemagick在处理mvg格式图片时导致的命令注入,后两个都是在处理PostScript文件时因为使用了GhostScript,而GhostScript中存在的命令注入。

  Imagemagick是一个大而全的图片处理库,他能处理日常生活中见到的绝大多数图片格式,比如jpg、gif、png等,当然也包括日常生活中很少见到的图片格式,比如前面说的mvg和ps。

  这三个漏洞的具体原理网上很多文章也分析过,我这里就不再分析了,但我们思考一下:一个文件交给Imagemagick处理,他是怎么知道这是哪种格式的图片,并如何处理呢?

  显然需要一个 *** 来区分文件类型,而单纯用文件名后缀来判断是不合理的(文件后缀并不是构成文件名的必要元素),常规的做法就是通过文件头来判断。

  随便翻一下Imagemagick的代码,我就发现大多数文件格式的处理中,通常有一个函数,用来判断这个文件是否是对应的格式。

  比如:

  // coders/ps.c

  static MagickBooleanType IsPS(const unsigned char *magick,const size_t length)

  {

  if (length 4)

  return(MagickFalse);

  if (memcmp(magick,"%!",2)==0)

  return(MagickTrue);

  if (memcmp(magick,"\004%!",3)==0)

  return(MagickTrue);

  return(MagickFalse);

  }

  // coders/mvg.c

  static MagickBooleanType IsMVG(const unsigned char *magick,const size_t length)

  {

  if (length 20)

  return(MagickFalse);

  if (LocaleNCompare((const char *) magick,"push graphic-context",20)==0)

  return(MagickTrue);

  return(MagickFalse);

  }

  这两个函数就是判断文件是否是postscript和mvg格式。很显然,他这里是通过文件头来判断,也就是说,如果想让Imagemagick用ps的处理 *** 来处理图片,这个图片的前几个字节必须是%!或\004%!。

  这也很好理解,文件头的意义就是标示这个文件是什么类型的文件。

  所以,如果我们想利用Imagemagick的命令执行漏洞,必须要给他传入一个合法的mvg或ps文件,或者至少文件头要满足要求。

  0×02 深入getimagesize

  通过翻阅PHP文档,可知getimagesize支持的图片类型有:GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM,WBMP:

  

  那么这时候就犯难了,ps和mvg并不在其中。如果我们传入一个ps文件,getimagesize处理时就会失败并返回false,那么就不会执行到Imagick那里。这种 *** 也是当初ImageTragick漏洞出现时,很多文章推荐的缓解措施。

  似乎很安全,不过我们应该深入研究一下getimagesize究竟是如何处理图片的。

  下载php源码,ext/standard/image.c这个文件是关键,看到如下函数:

  static void php_getimagesize_from_stream(php_stream *stream, zval *info, INTERNAL_FUNCTION_PARAMETERS)

  {

  int itype=0;

  struct gfxinfo *result=NULL;

  if (!stream) {

  RETURN_FALSE;

  }

  itype=php_getimagetype(stream, NULL);

  switch( itype) {

  case IMAGE_FILETYPE_GIF:

  result=php_handle_gif(stream);

  break;

  case IMAGE_FILETYPE_JPEG:

  //...

  case ...

  可见,这里逻辑是首先用php_getimagetype(stream, NULL)来获取图片格式,然后进入一个switch语句,根据格式来分配具体的处理 *** 。

  看看PHP是如何获取图片格式的:

  PHPAPI int php_getimagetype(php_stream * stream, char *filetype)

  {

  char tmp[12];

  int twelve_bytes_read;

  if ( !filetype) filetype=tmp;

  if((php_stream_read(stream, filetype, 3)) !=3) {

  php_error_docref(NULL, E_NOTICE, "Read error!");

  return IMAGE_FILETYPE_UNKNOWN;

相关文章

苏宁易购好还是京东好(两个平台实力大比拼)

苏宁易购好还是京东好(两个平台实力大比拼)

老李前边对京东商城干了一些简易剖析,京东商城的发展趋势還是众所周知的,和天猫商城对比還是有非常大差别。因为我仅仅剖析了一下京东商城有它一定的优点和发展模式,就被大伙儿误会成,京东商城立刻要灭掉阿...

植物大战僵尸花园战争3上市时间!

植物大战僵尸花园战争3上市时间!

作为PopCap Games开发的植物大战僵尸系列衍生作品,花园战争已经推出了两款系列游戏。根据亚马逊网上商城的商品信息,似乎《植物大战僵尸:花园战争3》也就要出现了。 根据美国亚马逊商城关于《...

公积金怎么提取?取公积金需要什么材料?

公积金怎么提取?取公积金需要什么材料?

现在几乎每个单位都会为员工缴纳公积金。当满足一定的条件时,公积金是可以提取的。那么,公积金提取需要什么材料呢?公积金的提取流程是什么呢?一起来看看本文的介绍吧。 一、取公积金需要什么材料? 1...

新手开网店教程(老店长手把手教你开网店教程

新手开网店教程(老店长手把手教你开网店教程

想要在网络上开一个商店,就必须要选择一个平台,有了这个交易平台,就可以在这个平台上进行各种交易。今天就以淘宝为例子,给大家讲解一下怎么样在淘宝开店。 1、在淘宝网注册帐户 进入淘宝网的首页,点左上...

会编程可以找什么工作(会编程可以做什么工作)

会编程可以找什么工作(会编程可以做什么工作)

学计算机专业找什么工作呢? 1、学计算机专业出来后可以做软件工程师、网络安全与管理工程师、编程语言工程师等。软件工程师:软件工程师一般从事软件开发,程序开发。2、计算机相关管理岗位有软件和硬件架构师、...

超市搞活动的广告词怎么吸引人(超市搞啥活动最吸引人)

现如今,愈来愈多的人不想上班。她们感觉她们不可以赚钱和认真工作。她们都想做生意。她们开疆辟土,想认真工作,开辟工作。因而,市场需求愈来愈猛烈。适者生存,弱肉强食,怎样在这不计其数的新天地中存活,怎样运...