导语:FortiGuard Labs对其发现的Microsoft Windows JET数据库引擎堆溢出漏洞CVE-2018-1003 进行了详细分析。
2017年底,FortiGuard Labs团队发现Microsoft Windows JET数据库引擎中存在堆溢出漏洞,并依据Fortinet的披露流程向微软报告。2018年4月10日,Microsoft发布了一个包含此漏洞修复程序的公告,并将其标识为CVE-2018-1003。
Microsoft JET数据库引擎的动态链接库msexcl40.dll中存在此堆溢出漏洞,该链接库历史悠久。它最初是在Windows XP中引入的,并且是从Windows 7到Windows 10的所有Windows系统的组件。
我发现的这个漏洞可以通过精心制作的Excel文件触发。当Excel使用指向精心制作的Excel文件的外部数据源ODBC Connect解析文件时,将执行长度不正确的堆复制操作。因此,由于边界检查不足,目标堆缓冲区溢出。
在本博客中,我想分享一下我对这个漏洞的详细分析。
分析
要重现此堆溢出漏洞,需在Excel中打开ODBC外部数据源,设置ODBC连接字符串为“DRIVER = {Microsoft Excel Driver(* .xls)}; DBQ = c:\ poc \ poc.xls”。然后可以看到Excel因此崩溃。PoC文件poc.xls可以放入任何本地文件夹或SMB共享。
以下是发生崩溃时的调用堆栈。
图1. 崩溃时的调用堆栈
从上面的调用堆栈输出中,我们可以看到崩溃发生在函数msexcl40!memcpy中,该函数被函数msexcl40!ExcelMIReadRecord调用。
目标堆内存的地址是0x0766efdc,分配的大小是0x202C。目标堆是通过调用函数RtlpAllocateHeap来分配的。
通过逆向和追踪,我们可以看到函数_ExcelScanFile @ 12的调用导致崩溃。
在多次调用函数_ExcelReadTotalRecord之后,可以通过计算第一个参数edi来确定堆复制的实际大小为poi(poi(poi(edi + 28h)+8)+4),这是一个HIWORD。跟踪程序,最后可以看到堆复制的大小由PoC文件中的三个链接列表节点确定。
图2显示了PoC文件中的第一个链接列表节点。
图2.PoC文件中的第一个链接列表节点
第一个链接列表节点的大小为0x1014,在图2中突出显示。由此可以获得第二个链接列表节点,其偏移量从0x1373 + 0x1014 = 0x2387开始。
图3.PoC文件中的第二个链接列表节点
第二个链接列表节点的大小为0x08,在图3中突出显示。由此我们可以得到第三个链接列表节点,其偏移量从0x238B + 0x08 = 0x2393开始。
同样从图3中,我们可以看到第三个链接列表节点的大小为0x2604,位于文件偏移0x2395处,此值为目标堆memcpy的size。从前面的分析中我们已经知道,目标堆分配的大小为0x202c(当整个页堆未启用时,大小由!heap -x 0x0766efdc确定)。结果,堆缓冲区溢出发生。
从上面的分析中,我们可以看到堆溢出的根本原因是位于PoC文件偏移0x1372处错误的大小值0x1014,正确的值应该是0x14。因此,格式错误的大小值导致第二个链接列表节点的位置错误,第三个链接列表节点也位于错误位置,导致memcpy时的参数size为无效的0x2604,而目标堆只分配了0x202c。由于边界检查不足,发生堆溢出。成功利用此漏洞可能会导致远程执行代码。
解决方案
所有存在漏洞的Microsoft Windows用户请升级到最新的Windows或应用最新的补丁。此外,已部署Fortinet IPS解决方案的机构已经通过签名MS.JET.Database.Engine.Heap.Overflow免受此漏洞的影响。