阿里基础安全威胁情报中心
0x01 漏洞概述
今年4月份微软修补了一个名为CVE-2015-1641的word类型混淆漏洞,攻击者可以构造嵌入了docx的rtf文档进行攻击。word在解析docx文档处理displacedByCustomXML属性时未对customXML对象进行验证,可以传入其他标签对象进行处理,造成类型混淆,导致任意内存写入,最终经过精心构造的标签以及对应的属性值可以造成远程任意代码执行。
根据微软官方MS15-33安全公告里显示,这个漏洞覆盖Office 2007 SP3,Office 2010 SP2(32位和64位),Office 2013 SP1(32位和64位),Office 2013RT SP1,Word for Mac 2011以及Office在SharePoint服务器上的Office 2010/2013和Office Web 2010/2013应用,除此之外,经过验证Office 2010 SP1也受该漏洞的影响,但是微软针对该漏洞在2010上的补丁KB2553428并未推出SP1版本,因此SP1版本的Office 2010到目前即使更新所有补丁仍然存在该漏洞。
CVE-2015-1641这个漏洞的触发非常稳定,几乎影响微软目前所支持的所有office版本(最新推出的Office 2016除外),影响范围十分广泛。目前无论是在VirusTotal还是在野外抓到的样本,利用这个漏洞的攻击样本已经开始逐渐增加。根据以上原因可以推断,在今后很长的一段时间内都会存在该漏洞的攻击,并且有替代CVE-2012-0158的趋势。
0x02 漏洞原因分析
使用阿里谛听引擎扫描RTF文档,解析出其中的一个word文档的document.xml中有如下代码,包含了4个smartTag标签,每个smartTag中又有permStart标签,而在permStart标签中的则是带有displacedByCustomXml属性的moveFromRangeStart和moveFromRangeEnd标签:
首先来说明一下几个标签及属性的作用。smartTag标签是用于word和excel中的智能标签,针对人名、日期、时间、地址、电话号码等进行智能识别并允许用户执行特定操作的标签。比如如果Steve Jobs被识别为人名,则smartTag标签可以执行诸如打开通讯录、添加到联系人、预约会议等操作,给office用户提供更多自定义的智能选择。displacedByCustomXml在很多标签中都可以使用,目的是当前标签处需要被一个customXML中的内容代替,它的值是next表示被下一个customXML代替,prev则表示被上一个代替。
这个漏洞是一个类型混淆漏洞,本来带有displacedByCustomXml的标签会被上一个或下一个customXML代替,但是word没有对传入的customXML对象进行严格的校验,导致可以传入诸如smartTag对象,然而smartTag对象的处理流程和customXML并不相同,上述特殊处理的smartTag标签中的element属性值会被当作是一个地址,随后经过简单的计算得到另一个地址。最后处理流程会将moveFromRangeEnd的id值覆盖到之前计算出来的地址中,导致任意内存写入,漏洞代码如下:
通过下面的补丁对比可以很容易看到打上最新补丁的word代码增加了对customXML对象处理函数的校验:
0x03 漏洞利用分析
利用的分析环境为win7 64位+office2010 sp2 32位。
虽然这上面有4个smartTag标签,但就目前分析来看,前两个标签是漏洞利用的关键。首在解析第一个smartTag标签时会把其moveFromRangeEnd子标签的id进行解析,然后写到0x7c38bd74这个地址中去,这个地址是根据smartTag的element即0x7c38bd50计算出来的:
然后解析第二个smartTag标签,esi指向的内存就是smartTag的结构体,esi+4的内容是element属性值:
而eax的值为0x7C376FC3,刚好就是moveFromRangeEnd对象id “2084007875”的十六进制值:
然后覆盖MSVCR71.dll中0x7c38a428,这是一个虚函数的指针,而0x7c38a428这个地址是通过当前smartTag的element属性值即0x7c38bd68和第一个smartTag标签中moveFromRangeStart的id共同计算出来的:
调试可以看到如下内存,ecx的内存如下,ecx+0xc就是上面解析第一个smartTag标签时写入的值,最终计算得到的被覆盖的地址便是0x7c38a428:
而在覆盖之前0x7c38a428处的指针指向kernel32! FlsGetValue:
最后调用memcpy函数进行覆盖:
覆盖之后的0x7c38a428指向的便是攻击者想要执行的代码位置:
总结一下利用流程如下:首先smartTag_1(第一个smartTag标签)的element属性值进行简单计算得到一个地址addr1,然后将其moveFromRangeEnd_1子标签的id写入到addr1中备用;然后解析smartTag_2,根据他的element属性值和前面计算出来的addr1共同计算出另一个地址addr2,并将其子标签moveFromRangeEnd_2的id写入到addr2,而addr2是一个虚函数表中的地址,这样原本是这个虚函数的地址就被覆盖成攻击者想要执行的任意代码的地址,漏洞利用成功。
word在office2010的环境下没有打补丁的情况下执行的堆喷射后的地址为0x0900080C,如下:
看到这段内存想必都已经清楚了,这里就是RTF文档释放的activeX.bin文件的内容,而0x7c342404处的代码是ret,因此这里会一直执行ret直到到达最终ROP的位置,ROP链如下:
毫无疑问ROP的作用还是调用VirtualProtect函数对当前这块内存添加可执行权限:
获得执行权限之后开始执行shellcode:
0x04 漏洞利用检测
想要检测这个漏洞的攻击样本必须要先从rtf文档提取出docx然后获取到document.xml,yara规则如下:
rule CVE_2015_1641
{
meta:
description="Word Type Confusion Vulnerability"
output="Nday & CVE-2015-1641"
strings:
$smart_tag=/<w:smartTag[\w\W]+?w:element=\"(&#x[a-zA-Z0-9]{4};){2}\">[\w\W]+?<w:permStart[\w\W]+?w:displacedByCustomXml=\"prev\"\/>[\w\W]+?<w:permEnd[\w\W]+?<\/w:smartTag>/
condition:
$smart_tag
}
上面的规则匹配其实就是一个正则匹配,从左到右流程如下:1.匹配到smartTag标签,查看其element属性是否为十六进制数值作为地址;2.在smartTag标签中匹配到permStart标签,在它的属性或子标签的属性中存在displacedByCustomXml=”prev”。满足上述两个条件则认为就是这个漏洞的攻击样本。依据上面的yara规则检测该攻击样本的document.xml结果如下:
0x05 参考链接
- 微软MS15-033安全公告
- Fortinet对CVE-2015-1641的简要分析报告
- Office Smart Tag标签说明
- Office permStart标签及displacedByCustomXml属性
关于阿里基础安全威胁情报中心
阿里基础安全威胁情报中心是2015年6月新成立的部门,以沉淀阿里的安全数据、安全能力和建设阿里安全的威胁情报体系为使命,欢迎志同道合的小伙伴们加盟。