ImageMagick内存泄漏漏洞分析(CVE-2018-16323)
概述
在本文中,我们主要对ImageMagick的内存泄漏漏洞进行分析。
ImageMagick是用于创建、编辑、转换位图图像的软件,它可以读取和写入超过200种格式的图像,包括PNG、JPEG、GIF、HEIC、TIFF、DPX、EXR、WebP、Postscript、PDF和SVG。使用ImageMagick还可以对图像进行调整大小、翻转、镜像、旋转、扭曲、剪裁和变换,可以调整图像颜色、应用各种特殊效果,可以绘制文本、线条、多边形、椭圆和Bézier曲线。
这是一个具有丰富功能的图像处理库,如果我们在搜索引擎中查找“如何在PHP中调整图片大小”和“如何剪裁图像”,那么很可能会搜到关于使用ImageMagick的建议。然而,这个库长期存在安全问题,我们本次对一个新发现的漏洞进行分析,同时会回顾一些此前发现的漏洞。
CVE-2018-16323的PoC生成工具(通过ImageMagick中的XBM图像实现内存泄漏)请参考:https://github.com/ttffdd/XBadManners
内存泄漏漏洞分析
在过去两年中,几乎每个月都会爆出一个ImageMagick库的漏洞。幸运的是,其中的许多漏洞都是某种不适用的DoS漏洞,并不会造成严重的安全问题。但是最近,我们注意到一个有趣的漏洞,其编号是CVE-2018-16323。
这一漏洞听起来很简单,但我们没有找到关于此漏洞利用的任何信息。
我们引用CVE的提交内容:
如果像素的十六进制值为负,则XBM编码器会将十六进制图像数据保留为未初始化的模式。
接下来,我们对XBM文件格式进行分析,常见的XBM图像如下所示:
这与C语言代码非常相似。这是一种非常老的格式,在X Window System中用于存储X GUI中使用的光标和图标位图。keyboard16_bits数组中的每个值都代表8个像素,每个像素是一个比特,其中编码黑色或白色这两种颜色中的一种。所以,并没有值为负的像素,因为一个像素只有两个可能的值。在下文中,我们将该数组称为XBM主体数组(XBM Body Array)。
我们分析ImageMagick的代码,并尝试找出“像素为负”具体代表什么含义。在这里,需要ReadXBMImage()函数,该函数用于读取图像,并准备用于图像处理的数据。似乎变量image中包含正在处理的图像数据(第225行)。
接下来,在第344-348行的位置是内存分配,并且指针数据现在指向所分配的存储器的起始地址,指针p也指向了同一地址。
接下来的第352-360行和第365-371行,代码相同,但它们分别负责处理不同版本的XBM图像。从提交中可以看出,两个分支都存在相同的漏洞,因此我们仅选取其中一个进行分析。XBM主体数组的读取过程发生在函数XBMInteger()中,它将int返回给变量c。此外,在第358行,存储在变量c中的值被赋值给p指针指向的变量,然后该指针将递增。
根据提交,我们看到先前版本中,会检查变量c是否为负值。如果c为负值,那么将会中断循环过程,这也就是内存泄漏的原因。如果XBM主体数组的第一个值为负,那么所有分配的内存都将保持未初始化,并且其中可能包含来自内存的敏感数据,这些数据将会进一步处理,以生成新的图像。在修复后版本中,这一问题已经被修复,现在如果XBM主体数组的值为负,那么ImageMagick将会抛出错误。
接下来,我们认真分析XBMInteger()函数。该函数将指针图像和指针hex_digits作为参数。后者是在第305行初始化的数组。该函数允许将值保存为XBM主体数组中的十六进制值。XBMInteger()读取XBM主体数组中定义的下一个字节,并将其赋值给无符号INT型变量。这一函数读取十六进制字符,直至出现停止标记。这也就意味着,我们可以指定任意长度的十六进制值,而不是char类型的0-255之间的预期长度范围。我们可以设置任何无符号INT值,它将存储在变量中,并且随后会将该变量值转换为有符号的INT类型。
所以,我们只要为XBM主体数组设置一个特定值(大于2147483647,或十六进制的0x80000000),该数组将转换为INT类型负数值。PoC如下:
#define test_width 500
#define test_height 500
static char test_bits[] = {
0x80000001, };
泄露的内存数量取决于攻击者设置高度和宽度参数的方式。如果设置为500×500,那么将会泄露31250(500*500/8)字节!但实际上,这取决于应用程序如何使用ImageMagick,它可能会将图像剪裁到一定的宽度和高度。
当我们在测试这个PoC时,遇到了一个问题。正如CVE的漏洞细节中所描述的那样,并非在7.0.8-9之内的所有ImageMagick版本都易受攻击。我们发现了一个用于修复另一个漏洞(CVE-2017-14175,XBM图像处理过程中DoS漏洞)的提交版本,正是这个特定的提交版本才将漏洞引入到代码中。
接下来,让我们尝试运行PoC。我们首先安装一个易受攻击的版本(例如6.9.9-51)。接下来,运行poc.xbm到poc.png的转换过程,我们将在xbm.c文件中调用处理XBM图像,从而调用存在漏洞的代码。
生成的图像如下所示:
概述
在本文中,我们主要对ImageMagick的内存泄漏漏洞进行分析。
ImageMagick是用于创建、编辑、转换位图图像的软件,它可以读取和写入超过200种格式的图像,包括PNG、JPEG、GIF、HEIC、TIFF、DPX、EXR、WebP、Postscript、PDF和SVG。使用ImageMagick还可以对图像进行调整大小、翻转、镜像、旋转、扭曲、剪裁和变换,可以调整图像颜色、应用各种特殊效果,可以绘制文本、线条、多边形、椭圆和Bézier曲线。
这是一个具有丰富功能的图像处理库,如果我们在搜索引擎中查找“如何在PHP中调整图片大小”和“如何剪裁图像”,那么很可能会搜到关于使用ImageMagick的建议。然而,这个库长期存在安全问题,我们本次对一个新发现的漏洞进行分析,同时会回顾一些此前发现的漏洞。
CVE-2018-16323的PoC生成工具(通过ImageMagick中的XBM图像实现内存泄漏)请参考:https://github.com/ttffdd/XBadManners
内存泄漏漏洞分析
在过去两年中,几乎每个月都会爆出一个ImageMagick库的漏洞。幸运的是,其中的许多漏洞都是某种不适用的DoS漏洞,并不会造成严重的安全问题。但是最近,我们注意到一个有趣的漏洞,其编号是CVE-2018-16323。 内容来自无奈安全网
这一漏洞听起来很简单,但我们没有找到关于此漏洞利用的任何信息。
我们引用CVE的提交内容:
如果像素的十六进制值为负,则XBM编码器会将十六进制图像数据保留为未初始化的模式。
接下来,我们对XBM文件格式进行分析,常见的XBM图像如下所示:
这与C语言代码非常相似。这是一种非常老的格式,在X Window System中用于存储X GUI中使用的光标和图标位图。keyboard16_bits数组中的每个值都代表8个像素,每个像素是一个比特,其中编码黑色或白色这两种颜色中的一种。所以,并没有值为负的像素,因为一个像素只有两个可能的值。在下文中,我们将该数组称为XBM主体数组(XBM Body Array)。
我们分析ImageMagick的代码,并尝试找出“像素为负”具体代表什么含义。在这里,需要ReadXBMImage()函数,该函数用于读取图像,并准备用于图像处理的数据。似乎变量image中包含正在处理的图像数据(第225行)。
www.wnhack.com
接下来,在第344-348行的位置是内存分配,并且指针数据现在指向所分配的存储器的起始地址,指针p也指向了同一地址。
接下来的第352-360行和第365-371行,代码相同,但它们分别负责处理不同版本的XBM图像。从提交中可以看出,两个分支都存在相同的漏洞,因此我们仅选取其中一个进行分析。XBM主体数组的读取过程发生在函数XBMInteger()中,它将int返回给变量c。此外,在第358行,存储在变量c中的值被赋值给p指针指向的变量,然后该指针将递增。
根据提交,我们看到先前版本中,会检查变量c是否为负值。如果c为负值,那么将会中断循环过程,这也就是内存泄漏的原因。如果XBM主体数组的第一个值为负,那么所有分配的内存都将保持未初始化,并且其中可能包含来自内存的敏感数据,这些数据将会进一步处理,以生成新的图像。在修复后版本中,这一问题已经被修复,现在如果XBM主体数组的值为负,那么ImageMagick将会抛出错误。 无奈人生安全网
接下来,我们认真分析XBMInteger()函数。该函数将指针图像和指针hex_digits作为参数。后者是在第305行初始化的数组。该函数允许将值保存为XBM主体数组中的十六进制值。XBMInteger()读取XBM主体数组中定义的下一个字节,并将其赋值给无符号INT型变量。这一函数读取十六进制字符,直至出现停止标记。这也就意味着,我们可以指定任意长度的十六进制值,而不是char类型的0-255之间的预期长度范围。我们可以设置任何无符号INT值,它将存储在变量中,并且随后会将该变量值转换为有符号的INT类型。
所以,我们只要为XBM主体数组设置一个特定值(大于2147483647,或十六进制的0x80000000),该数组将转换为INT类型负数值。PoC如下:
#define test_width 500
#define test_height 500
static char test_bits[] = { 无奈人生安全网
0x80000001, };
泄露的内存数量取决于攻击者设置高度和宽度参数的方式。如果设置为500×500,那么将会泄露31250(500*500/8)字节!但实际上,这取决于应用程序如何使用ImageMagick,它可能会将图像剪裁到一定的宽度和高度。
当我们在测试这个PoC时,遇到了一个问题。正如CVE的漏洞细节中所描述的那样,并非在7.0.8-9之内的所有ImageMagick版本都易受攻击。我们发现了一个用于修复另一个漏洞(CVE-2017-14175,XBM图像处理过程中DoS漏洞)的提交版本,正是这个特定的提交版本才将漏洞引入到代码中。
接下来,让我们尝试运行PoC。我们首先安装一个易受攻击的版本(例如6.9.9-51)。接下来,运行poc.xbm到poc.png的转换过程,我们将在xbm.c文件中调用处理XBM图像,从而调用存在漏洞的代码。
生成的图像如下所示:
无奈人生安全网