在本文中我们将讨论ImageMagick漏洞。
太长不看
PoC 生成器 CVE-2018–16323 (XBM文件导致的内存泄漏)
什么是ImageMagick呢?来自其官网的说明:
使用ImageMagick®创建,编辑,撰写或转换位图图像。
它可读写超过200种格式的图像,包括PNG,JPEG,GIF,HEIC,TIFF,DPX,EXR,WebP,Postscript,PDF和SVG。
使用ImageMagick调整大小,翻转,镜像,旋转,扭曲,剪切和变换图像,调整图像颜色,应用各种特殊效果,或绘制文本,线条,多边形,椭圆和Bézier曲线。
这是一个十分强力的图像处理库。如果你进行搜索”如何在php中调整图像”或”如何裁剪图像”那么你就会找到很多有关如何使用ImageMagick的结果。
章节一: 又一次内存泄漏
在过去的两年中,ImageMagick组件几乎每个月都会有漏洞产生。幸运的是,这些漏洞大多都像是DoS(拒绝服务)这种无法造成严重安全问题的漏洞。但最近我们又发现了一个有趣的漏洞CVE-2018-16323。
但遗憾的是,我们并没有在网络上发现任何这个漏洞详细利用分析。
我们只好自己动手,让我们看到对应这个CVE的 代码提交
如果像素的十六进制值为负数,则XBM编码器将保留这段未初始化的数据。
恩~让我们先来了解下XBM文件格式,一个常见的XBM图像如下所示:
这非常像是一段C代码。这是一种十分古老的格式,在X Windows System中用于存储X GUI所使用的光标和图标的位图。keyboard16_bits数组中每一个值代表了8个像素,每一个像素是一个bit,用于标记是黑色还是白色。因此没有负像素值,因为一个像素值可能有两个值。
在下文中,我们将该数组称为XBM主体数组。
接下来让我们来更仔细的查阅ImageMagick的源代码,并且寻找”像素值为负数”具有什么样的含义。我们需要关注ReadXBMImage()函数。这个函数读取图像并准备用于图像处理的数据。其中的image变量像是包含了被处理的图像数据。(Line 225)
紧接着,在[Line 344-348][xbm.c Line 344-348]处存在内存分配,并且指针data指向所分配的起始地址。指针p亦指向同一地址。
然后,Line 352-360、Line 365-371两段相同的代码用于处理不同版本的XBM图像。从提交日志中可以看出,两个版本的分支受到影响,我们只着眼于其中216d117f05bff87b9dc4db55a1b1fadb38bcb786这个提交。XBM主体数组在XBMInteger()中被读取,然后返回一个整型给变量c。接着在Line 358存储在变量c中的值赋值给指针p指向的地址,然后指针递增。
在提交中,我们看到在以前的版本中,如果变量c是负数,则中断循环,这就是出现内存泄漏的原因。如果XBM主体数组的第一个值为负,则所有分配的内存都不会被初始化,就可能包含来自内存中的敏感数据,随后将进一步处理并从该数据生成新图像。在修补后的版本中,如果XBM正文数组的值为负,则ImageMagick会抛出错误。
现在让我们着眼于XBMInteger()函数。指针image和指针hex_digits是参数。hex_digits是一个在Line 305被初始化的数组。这用于将XBM主体数组中十六进制值转化为对应的十进制值。XBMInteger读取XBM主体数组中的数据,并将其放入unsigned int变量value。这里存在一个有趣的逻辑,此函数读取十六进制值,直到出现停止标记才停止。这意味着我们可以指定任意长度的十六进制值,因此可以不是char类型原本0-255之间的值,我们可以设置任何unsigned int值,它将存储在变量value中。而下面的处理将变量value将转换为signed int。好了这里就是重头戏了。
所以我们只需要为XBM主体数组设置一个值,然后利用XBMInteger()将该数组将转换为一个负int值即可。那么这个值应该是十六进制中大于2,147,483,647或0x80000000的任何值。
如下形式即是一种满足条件的PoC
#define test_width 500 #define test_height 500 static char test_bits[] = { 0x80000001, };
泄漏的内存的量取决于设置高度和宽度参数。
因此,如果设置500×500,则会泄漏31250(500 * 500/8)字节!
但这取决于应用程序如何使用ImageMagick,它可能会将图像切割到一定的高度和宽度。
当我们在尝试这个PoC的时候,我们有一些新的发现,并不是像cvedetails中所描述的所有低于 7.0.8–9的ImageMagick都收到影响。而是在一个修复CVE-2017-14175(这是一个XBM处理图像时会触发DoS的漏洞)的提交中产生的该漏洞。
好的,确切的确定了影响版本。让我们试试PoC吧。首先我们安装一个易受攻击的版本(例如6.9.9-51)。现在,运行
convert poc.xbm poc.png
我们将使用xbm.c文件中的函数处理XBM图像。因此触发了含有漏洞的代码。
生成的图像应如下所示:
你可以在生成的图像上看到一些噪点,这是一个泄漏的内存块,每个黑色或白色像素都是泄漏内存中的一些信息。如果你重复转换,那么你可能会得到另一个图像,因为将捕获的可能是另一个内存块。
那么我们该如何提取泄漏内存中的确切信息呢?
只需将其转换回来
convert poc.png leak.xbm
现在我们在XBM主体数组中看到泄漏的内存字节,这将变得容易处理。
那么整个漏洞的利用步骤如下
- 生成一个PoC
- 上传这个图像到受影响的应用中
- 存储结果图片
- 将其转换为xbm格式以提取信息
ttffdd为这个名为XBadManners的漏洞编写了一个简单易用的工具。它可以生成PoC并从图像中恢复泄露的数据。
章节二:ImageMagick安全吗?
简而言之: 不安全
它不是ImageMagick软件中发现的第一个严重漏洞。
在这之前已经有了很多影响面广,危害大的漏洞。
ImageMagick已有近500个已知的固定漏洞!
每个月都会被发现一些可能难以利用或不适用的新漏洞,并且每年都会被发现一些具有高影响的严重漏洞。
以下是众所周知的ImageMagick漏洞中最严重的列表。
ImageMagick中最著名的一系列漏洞。
它包括RCE,SSRF,svg和mvg文件中的本地文件读取/移动/删除。
它于2016年4月由stewie和Nikolay Ermishkin发现。
- CVE-2016–3714 — RCE
- CVE-2016–3718 — SSRF
- CVE-2016–3715 — File deletion
- CVE-2016–3716 — File moving
- CVE-2016–3717 — Local file read
Patch发布在2016-04-30 ImageMagick版本号为6.9.3-9。这个漏洞非常受bug hunters的欢迎:
CVE-2017-15277 a.k.a. gifoeb
由Emil Lerner于2017年7月发现。
此漏洞是GIF图像处理中的内存泄漏。
如果不存在全局调色板或局部调色板,则ImageMagick会使调色板保持未初始化状态,并且内存泄漏恰好通过调色板发生。
调色版的存储大小会限制泄露数据的长度。
这个漏洞也很受bug hunters的欢迎。
GhostScript Type Confusion RCE (CVE-2017–8291)
在2017年5月发现的。它不是ImageMagick漏洞,但ImageMagick受到影响,因为ImageMagick使用ghostscript处理PostScript的某些类型的图像,即EPS,PDF文件。
CVE-2018-16509
GhostScript中的另一个RCE,于2018年8月发布。同样影响ImageMagick,就像GhostScript一样,就像之前的bug一样。
有多少其他带有严重安全问题的漏洞仍然未知?
我们不知道。
我们专门准备了ImageMagick安全漏洞的小历史图解。
章节三: 我们如何以安全的方式使用ImageMagick?
停止使用ImageMagick?这也许是个主意,但。。。我们不会告诉你让你停止使用ImageMagick。
我们建议你以安全的方式执行此操作以降低信息安全风险。
首先,您可能已经注意到ImageMagick的漏洞不断出现,因此它也经常更新。
如果您使用ImageMagick,请注意新版本并确保始终安装最新版本。
请注意,ImageMagick不会在官方存储库中频繁更新,因此它可能包含旧的易受攻击的版本。最好从源代码安装稳定的ImageMagick版本。
但正如从我们的示例中看到的那样,修复旧漏洞可能会带来新的漏洞:)
因此,保持更新ImageMagick可能无法完全解决你的担忧。
ImageMagick的最佳实践是在像Docker这样的隔离环境中运行它。
设置使用ImageMagick的服务的最低必需权限。
将其置于具有最小网络权限的隔离网段中。
并且仅使用此隔离环境来执行使用ImageMagick处理自定义用户图像的特定任务。
ImageMagick也拥有可以配置的安全策略。
在这里,您可以找到有关开发人员ImageMagick安全性的详细指南。