深入分析Microsoft Outlook漏洞CVE-2018-8587

TRex 漏洞 2018年12月20日发布
Favorite收藏

导语:FortiGuard实验室研究人员分享了对FortiGuard实验室自己发现的Microsoft Outlook漏洞CVE-2018-8587的详细分析。

今年早些时候,FortiGuard实验室研究员Yonghui Han通过Fortinet的负责任披露流程,向微软报告了Office Outlook中的Heap Corruption漏洞(Heap Corruption vulnerability)。2018年12月的周二补丁日,微软宣布他们已修复此漏洞,发布了相应的通报(corresponding advisory),并为其分配了漏洞ID号CVE-2018-8587。

Microsoft Outlook是Microsoft Office套装的组件之一,广泛用于发送和接收电子邮件、管理联系人、记录和跟踪日程安排以及执行其他任务。在Windows系统上的多个Outlook版本中都发现了Heap Corruption漏洞,涵盖了从Outlook 2010到最新的Outlook 2019以及Office 365 ProPlus的所有32/64位版本。该漏洞由格式错误的RWZ(邮件分类规则)文件触发。当Outlook收到不正确的RWZ文件内容时,分配的堆内存不足并且缺少适当的边界检查,从而导致堆的越界写入。

在本博客中,我将分享对此漏洞的详细分析。

一、重现漏洞

要重现此漏洞,需要运行Microsoft Outlook,然后单击“规则=>管理规则和警报=>选项=>导入规则”,并选择导致Outlook崩溃的PoC文件。

图1.重现漏洞

发生崩溃时,调用堆栈如下所示:

图2.崩溃发生时的堆栈

二、漏洞分析

正如从调用堆栈中看到的那样,崩溃发生在堆释放时。由于我们现在无法确认释放的堆块有什么问题,我们可以打开整页堆来跟踪有问题的堆块。命令如下:

YOUR_WINDBG_INSATALL_LOCATION\gflags.exe /p /enable outlook.exe /full

可以看到如下返回结果,表明它已成功执行。

图3.完整页面堆已成功打开

完成此操作后,我们可以再次打开Outlook并选择PoC文件以便在发生崩溃时监视新堆栈:

图4.打开Full Page Heap时的崩溃位置

现在我们可以看到ECX指向的非零内存地址是不可读的,并且在将数据写入该内存地址时会发生异常。因此将数据写入未分配(或释放)的内存的可能性很高。可以通过检查内存页面分配来验证这个预测,我们可以看到内存仍然具有Reserve属性。这是截图:

图5.保留的内存页面

我们现在需要弄清楚程序为什么要将数据写入未使用的内存页面。通过静态分析,我们可以看到ECX的值来自EDI,并且在调用MAPIAllocateBuffer之后正在修改EDI,如下面的屏幕截图所示:

图6. ECX值的来源

通过静态分析,我们了解到函数MAPIAllocateBuffer是RtlAllocateHeap的封装函数,它进行检查确保请求的堆大小参数不大于0x7FFFFFF7。这意味着它不是负的。但是,在此情形之下,它不会检查0是否可以用作参数。并且因为实际分配的堆大小比请求的堆大小多8个字节,这8个字节用0x0000000001000010填充。之后,MAPIAllocateBuffer在这8个字节后返回堆地址。因此,调用MAPIAllocateBuffer后的EDI值为8 +从RtlAllocateHeap接收的分配堆地址。截图如下:

图7.检查分配的堆的大小

图8.分配额外的8个字节

从上面的静态分析中,我们可以粗略地预测在Reserve堆中写入数据很大概率是由整数溢出引起的。结合调试,我们发现调用MAPIAllocateBuffer的堆大小参数确实为0。但是,由于MAPIAllocateBuffer请求分配大小为0 + 8 = 8的堆,因此RtlAllocateHeap不会返回错误并成功返回正确的堆地址。但是,MAPIAllocateBuffer使用这8个字节写入0x0000000001000010,然后向用户返回无效的堆尾地址。截图如下:

图9.只减少一个字节,但堆是正确的

接下来,我们需要弄清楚为什么请求的堆大小的值会变为0。结合调试和静态分析,我们发现值0来自当前函数的参数:arg_4(eax = arg_4 * 4 + 4)。但是,当调用当前函数时,arg_4的值不是传入参数的值,这意味着此函数会修改arg_4。通过调试我们可以看到更改是在子函数sub_65F7DA中完成的。截图如下:

图10.堆大小为0的源头

分析子函数sub_65F7DA,我们发现它是另一个封装函数。经过一系列调试后,我们终于知道名为ReadFile的函数,即arg_4的值,实际上来自PoC文件。截图如下:

图11. ReadFile的封装函数

图12.调用sub_65F7DA之前arg_4的值

调试显示arg_4读取的文件中的内容为0xFFFFFFFF,因此由于整数溢出,传递的堆的分配大小为0xFFFFFFFF * 4 + 4 = 0。但是,程序没有检查这一点,导致后一个堆越界写入行为。截图如下:

图13.调用sub_65F7DA后arg_4的值

检查PoC文件,我们可以看到0xFFFFFFFF值确实存在。

图14. PoC文件中的0xFFFFFFFF

将其修改为0xAABBCCDD,我们再次执行调试并设置相同的断点以验证溢出是否由这4个字节引起。

图15.修改后的PoC文件

图16.测试修改后的PoC文件

所以我们找到了原因。

通过在Patch发布之后比较程序的汇编代码,我们可以看到现在已经添加了对所请求的分配堆大小的验证。请参见下面的截图:

图17.补丁之前和之后的比较

应用此修补程序至关重要,因为成功利用此漏洞的攻击者可以使用特制文件在当前用户的安全context中执行操作。

三、解决方案

鼓励存在漏洞的Microsoft Outlook版本的所有用户升级到最新的Outlook或立即应用最新的补丁。此外,已部署Fortinet IPS解决方案的机构已通过以下特征受到保护:

MS.Outlook.CVE-2018-8587.Remote.Code.Execution

本文翻译自:https://www.fortinet.com/blog/threat-research/a-deep-analysis-of-the-microsoft-outlook-vulnerability-.html如若转载,请注明原文地址: http://www.4hou.com/vulnerable/15282.html
点赞 4
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论