漏洞描述
- Microsoft OfficeXP SP3、Office 2003 SP3、Office 2007 SP2、Office2010等多个版本的OFFice软件中的Open XML文件格式转换器存在栈溢出漏洞,主要是在处理RTF中的“pFragments”属性时存在栈溢出,导致远程攻击者可以借助特制的RTF数据执行任意代码,因此该漏洞又名“RTF栈缓冲区溢出漏洞”。
分析环境
|
使用的环境 |
备注 |
操作系统 |
Windows7 32位 |
旗舰版 |
虚拟机 |
VMware |
12.1.1 |
调试器 |
windbg、Immunity Debugger |
6.3/1.85 |
反汇编器 |
Ida |
6.8 |
漏洞软件 |
Microsoft Office Word |
2007 |
十六进制工具 |
010Edito |
7.0 |
RTF文件格式
- RTF格式是Microsoft公司为进行文本和图像信息格式的交换而制定的一种文件格式,适用于不同的设备、操作系统。RTF文件基本元素是正文、控制字、控制符号和群组。
- 控制字是RTF用来标记打印控制符和管理文档信息的一种特殊格式的命令,RTF用它作为正文格式的控制代码,每个控制字均以一个反斜杠\开头,由a~z小写字母组成,通常应该不包含任何大写字母,而分隔符标志着控制字名称的结束。它的使用格式为:\字母序列<分隔符>。
- 控制符号由反斜杠后跟一个单独的、非字母的字符,表示一个特定的符号。
- 群组由包含在大括号中的文本、控制字和控制符组成。左括弧表示组的开始,右括弧表示组的结束。每个组包括文本和文本的不同属性。RTF文件也能同时包括字体、格式、屏幕等属性。一个完整的RTF文件包括文件头和文档区两大部分,可以用下列语法表示。
<File>{<header><document>}
通过微软官方文档的目录,可以了解到文件头和文档区各自所包含的数据如图1所示
![]()
图1
* CVE-2010-3333部分数据,如图2所示。

图2
* RTF部分数据分析如下
```c
\rtf1-RTF版本
\ansi-支持ANSI字符集
\shp-绘图对象
\*\shpinst-图片引用
\sp-绘图对象属性定义
\sn pFragments-定义属性名称,pFragments段是图形的附加部分,属于数组结构。允许图形包含多个路径和分段,该属性列出图形各个碎片
\sv-定义属性值
```
* RTF分析器正是在解析pFragments属性值时,没有正确计算属性值占用的空间大小,导致栈溢出漏洞的发生。
####生成样本
* 通过Metasploit生成可触发漏洞的Poc样本,通过直接生成样本以供分析漏洞。
* 通过search搜索cve-2010-3333漏洞相关利用代码,如图3所示。

图3
* 利用use命令指定exploit,并用info命令生成关于此exploit的信息,包括参数值、漏洞描述等,如图4所示。

图4
* 主要是为了分析漏洞成因,因此选择可触发崩溃的Poc样本,直接通过set命令即可设置target参数值,如图5所示。

图5
* 利用exploit命令直接生成测试样本,如图6所示。

图6
####漏洞分析
* 获取样本后,打开WINWORD.exe,并使用WinDbg附加进程。然后打开msf.rtf,触发异常,如图7-11所示。

图7

图8

图9

图10

图11
* 这是mso.dll上的一处栈溢出漏洞,由于循环复制内存数据到栈空间的时,未检测复制内存的大小。导致覆盖到edi(0x00130000)这个只读内存,造成访问违例。
* 使用Immunity Debugger分析,如图12所示。

图12
* 栈回溯,找到memcpy,如图13所示。

图13

图14
* 回头看下msf.rtf中的样本数据,可以发现上面的0xc8ac是源于样本数据的,位于pFragements属性值的第三个字段,偏移八个字符后四个字符即为复制数据的大小,如图14所示。
* 查看memcpy函数的参数地址,如图15-16所示。

图15

图16
* 跟踪进去发现覆盖返回地址,如图17所示。

图17
* 复制内存目标地址edi刚好偏移栈底ebp共0x10字节,加上ebp所占四字节,刚好0x14字节,在覆盖下去就是返回地址了。

图18
* 0xc8ac后面的数据正是实际内存复制的数据,复制内存原地址esi刚好指向这里,如图18所示。
* 由于msf.rtf复制内存数据比较大,导致复制过程中覆盖到不可写的内存地址而触发异常,没有去执行返回地址或者seh异常处理函数。
####漏洞利用
* 分析完漏洞成因,利用该漏洞还是比较容易的。只需将jmp esp指令地址覆盖返回地址,也就是复制数据大小的值之后在偏移.0x14字节,即可覆盖返回地址。然后将shellcode放在后面,即可执行任意代码,如图19所示。

图19
* 以覆盖返回地址0x77411463(这个地址是随机的,需要手动去调试确认)。

图20
* 覆盖完成继续跟踪执行,发现在0x610d7977处有一个判断,[ebp+0x14]是否为0,此时[ebp+0x14]相当于[eip+0x14]这里的eip指的是我们覆盖的返回地址。不为0发生跳转,就会发生异常。如图20所示。
* 由于Office存在内存异常处理,也无法执行我们覆盖的seh,以至无法使eip得到执行,如图21所示。

图21
* 跟进触发异常的函数
* 为了让eip能够执行,必须不让他它跳转,也就是[eip+0x14]处必须为0x00000000,才能让程序正常执行。
* 更改后的msf.rtf,如图22所示。

图22
* 注:shellcode要使用小写

图23
补丁比对
- 如图24所示
![]()
图24
* 漏洞主要是在复制内存的时候未检测内存大小导致的栈溢出。但是里面调用的函数都是通过eax索引的,利用动态调试。
* 主要是通过动态监测pFragments属性值是否大于4字节,若大于则跳走并返回,而不进行内存复制,从而解决栈溢出问题。