频道栏目
首页 > 资讯 > 杀毒防毒 > 正文

ImageMagick(CVE-2016-3714)执行过程,漏洞分析以及解决方案

16-05-13        来源:[db:作者]  
收藏   我要投稿


什么是ImageMagick
ImageMagick是一个免费的创建、编辑、合成图片的软件。它可以读取、转换、写入多种格式的图片。图片切割、颜色替换、各种效果的应用,图片的旋转、组合,文本,直线,多边形,椭圆,曲线,附加到图片伸展旋转。
在本周二,ImageMagick披露出了一个严重的0day漏洞,此漏洞允许攻击者通过上传恶意构造的图像文件,在目标服务器执行任意代码。Slack安全工程师Ryan Hube发现了这一0day漏洞。
漏洞分析
这次披露的是ImageMagick的一个命令执行漏洞。首先定位到最终漏洞代码执行的地方,老外给出的poc是在一个文件内填充以下字符命名为`.mvg`格式
push graphic-context
viewbox 0 0 640 480
fill’url(https://example.com/image.jpg“ls “-la)’
pop graphic-context

POC执行效果如上图所示,可以执行mvg中注入的命令
我以POC为一个切入点,分析POC的执行过程。

首先从入口函数CovertMain()开始,在第81行MagickCommandGenesis()的第二个参数传入了ConvertImageCommand这个变量,这个变量是一个函数指针,指向了ConvertImageCommand()的函数首地址。所以MagickCommandGenesis()实现了函数的动态调用(非常好的写法)。
文件:wand/delegate.c:417行

的函数ExternalDelegateCommand()中调用了system()函数,执行了我们注入的命令。
整个执行流程是
ConvertMain() -> MagickCommandGenesis()-> ConvertImageCommand()
-> ReadImages() -> ReadImage() ->ReadMVGImage() -> DrawImage() ->ReadImage()
-> InvokeDelegate() -> system()
这一段
ConvertImageCommand() -> ReadImages()-> ReadImage()
主要做了读取判断文件名类型,根据文件类型调用相应的decoder,而调用decoder的方式使用的是delegate模式。
在coders/mvg.c:67行中
有一个IsMVG()函数
if (LocaleNCompare((const char *)magick,"push graphic-context",20) == 0)
   return(MagickTrue);
这一段读取了文件前20个字符,判断是否是一个MVG格式的图片,
`viewbox 0 0 640 480`主要由`文件:coders/mvg.c
*/
  while (ReadBlobString(image,primitive) != (char *) NULL)
  {
    for (p=primitive; (*p == ' ') || (*p == '\t'); p++) ;
    if (LocaleNCompare(BoundingBox,p,strlen(BoundingBox)) != 0)
      continue;
    (void) sscanf(p,"viewbox %lf %lf %lf %lf",&bounds.x1,&bounds.y1,
      &bounds.x2,&bounds.y2);
    image->columns=(size_t) floor((bounds.x2-bounds.x1)+0.5);
    image->rows=(size_t) floor((bounds.y2-bounds.y1)+0.5);
    break;
  }
}
这一段代码处理。
处理`fill`字段就是出问题的地方, 当mvg文件有`fill`字段代表需要填充外部的图片进当前的图片,`pattern_info->filename`就是从`fill`中解析出来的填充文件的字符串

`magick/delegate.c`
中的InvokeDelegate()进行了调用了ExternalDelegateCommand()执行外部命令。
题外话:可以看出来这个功能使用了delegate代理模式(对方法的封装)
在调用前实际上是对当前种类的请求方法,相应的权限进行了判断
if(IsRightsAuthorized(domain,rights,read_info->magick) == MagickFalse)
  {
   errno=EPERM;
   (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
     "NotAuthorized","`%s'",read_info->filename);
   read_info=DestroyImageInfo(read_info);
   return((Image *) NULL);
  }
并不是像网上说的这个程序一点安全都没有做
并且在`delegate.c`中也有对权限的检测。
if (IsRightsAuthorized(DelegatePolicyDomain,rights,encode)== MagickFalse)
  {
   errno=EPERM;
   (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
     "NotAuthorized","`%s'",encode);
   return(MagickFalse);
  }
并且在`delegate.c`中定义了合法字符的白名单,问题有一部分出在白名单这。
static char
 whitelist[] =
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"
   ".@&;()|/\\\'\":%=~`";
...
for (p+=strspn(p,whitelist); p != q;p+=strspn(p,whitelist))

 *p='_';
return(sanitize_command);
我们可以看到不在白名单中的字符全部会被替换成_,但是官方却把`|`和`;`放在了白名单中,导致了可以执行多个命令…
解决方案:
所以,经过以上的流程分析,可以有两种解决方案:
1.设置`Policy`文件
policy.xml
```
policymap>
 policy domain="coder" rights="none"pattern="EPHEMERAL" />
 policy domain="coder" rights="none"pattern="URL" />
 policy domain="coder" rights="none"pattern="HTTPS" />
 policy domain="coder" rights="none"pattern="MVG" />
 policy domain="coder" rights="none"pattern="MSL" />
 policy domain="coder" rights="none"pattern="TEXT" />
 policy domain="coder" rights="none"pattern="SHOW" />
 policy domain="coder" rights="none"pattern="WIN" />
 policy domain="coder" rights="none"pattern="PLT" />
policymap>
```
ps:来自imagetragick.com
2.如果不需要一些不常用的delegate里面的功能只保留https这个功能的话,去掉whitelist[]里面的管道符号`|`,还有`;`号等特殊符号,https这个delegate就可以正常使用了
复现之前的exploit可以看到去掉白名单里面的`;`和`|`之后,命令执行已经不成功了:)

相应的,想要发掘对应的delegate可以有什么样的利用,可以看以下具体的委托

 

 

相关TAG标签
上一篇:SS7协议攻击可入侵加密应用
下一篇:对康创联盛的一次安全检测(成功getshell并可访问数据库)
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站