0x00 概要
本文将对CVE-2016-0059进行深度分析,该漏洞是由于微软超链接对象库内存数据泄露造成的,成功利用该漏洞可以获得一些信息从而对用户系统造成进一步威胁。要利用该漏洞,攻击者必须诱导用户点击一个email里的或者一个office文档里的超链接。
起初是把该漏洞作为Microsoft Office Excel 堆溢出漏洞报告给微软的 ,但是该漏洞实际上是由 Internet Explorer对象库 hlink.dll (微软超链接对象库) 引起的,因此微软把该漏洞定义为 Internet Explorer信息泄露漏洞。本文将仍然用Microsoft Office来证明和分析该漏洞。
受影响产品:
- IE 9
- IE 10
- IE 11(包括win10版)
0x01 漏洞验证
要重现该漏洞,我们可以用 Microsoft Office Excel 2007打开POC FG-VD-15-073_PoC.xls。然后我们可以到Excel.exe崩溃了,崩溃信息显示如下:
(3344.1804): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=1a06d0d0 ebx=00000002 ecx=18b22fea edx=00000001 esi=18b23000 edi=18b22fe8
eip=6cd40b40 esp=00b739b4 ebp=00b739c4 iopl=0 nv up ei ng nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010282
hlink!WzDupWzToWz+0x16:
6cd40b40 668b06 mov ax,word ptr [esi] ds:002b:18b23000=????
0:000> u
hlink!WzDupWzToWz+0x16:
6cd40b40 668b06 mov ax,word ptr [esi]
6cd40b43 03f3 add esi,ebx
6cd40b45 6685c0 test ax,ax
6cd40b48 75f6 jne hlink!WzDupWzToWz+0x16 (6cd40b40)
6cd40b4a 2bf1 sub esi,ecx
6cd40b4c d1fe sar esi,1
6cd40b4e 8d5e01 lea ebx,[esi+1]
6cd40b51 85d2 test edx,edx
0:000> !heap -p -a esi
address 18b23000 found in
_DPH_HEAP_ROOT @ 5601000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
1a173a5c: 18b22fe8 16 - 18b22000 2000
5e6d9abc verifier!AVrfDebugPageHeapAllocate+0x0000023c
77c97ab1 ntdll!RtlDebugAllocateHeap+0x0000003c
77c4ba4e ntdll!RtlpAllocateHeap+0x0004cfde
77bfdc26 ntdll!RtlpAllocateHeapInternal+0x00000146
77bfdab8 ntdll!RtlAllocateHeap+0x00000028
770f32e6 combase!CRetailMalloc_Alloc+0x00000016 [d:thcomcombaseclassmemapi.cxx @ 641]
6cd337fd hlink!CMalloc::Alloc+0x0000002d
6cd40c32 hlink!operator new+0x00000023
6cd3d50e hlink!HrReadLengthWzStm+0x00000034
6cd39b2c hlink!HLNK_PersistStm::Load+0x0000010c
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:Program Files (x86)Common FilesMicrosoft Sharedoffice12mso.dll -
3280dc07 mso!Ordinal2575+0x00000320
3280dac1 mso!Ordinal2575+0x000001da
3280da7a mso!Ordinal2575+0x00000193
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:Program Files (x86)Microsoft OfficeOffice12oart.dll -
3a99fb87 oart!Ordinal5476+0x00000709
0:000> dp 18b22fe8
18b22fe8 00720041 00610072 00440079 006d0075
18b22ff8 00320070 d0d0d000 ???????? ????????
18b23008 ???????? ???????? ???????? ????????
18b23018 ???????? ???????? ???????? ????????
18b23028 ???????? ???????? ???????? ????????
18b23038 ???????? ???????? ???????? ????????
18b23048 ???????? ???????? ???????? ????????
18b23058 ???????? ???????? ???????? ????????
0:000> kb
# ChildEBP RetAddr Args to Child
00 00b739c4 6cd3590d 00000000 00b73a88 00b73a1c hlink!WzDupWzToWz+0x16
01 00b739e0 6cd331cf 1a068f28 00000000 00b73a1c hlink!CExtensionService::Release+0x105d
02 00b73a28 3280da8e 1a068f28 00000000 00b73a88 hlink!HLNK::GetStringReference+0x5f
WARNING: Stack unwind information not available. Following frames may be wrong.
03 00b73a58 3a99fb87 08f74fd0 00000000 00b73a88 mso!Ordinal2575+0x1a7
04 00b73d70 77bf6d70 77cc74a8 19cd6ff0 00000000 oart!Ordinal5476+0x709
05 00b73d98 77c91c3a 000df3e0 00000060 14b90fa0 ntdll!RtlpPopEntrySListLockedAlt+0x20
06 00b73de8 32c8de4f 32195748 2fc48b8c 00000000 ntdll!RtlpStdLockRelease+0x14
07 00b73dec 32195748 2fc48b8c 00000000 00000000 mso!Ordinal1743+0x2f43
08 00b73df0 2fc48b8c 00000000 00000000 00000000 mso!MsoPvAllocCore+0x36
09 00b73df4 00000000 00000000 00000000 00b73c90 Excel!Ordinal40+0x108b8c
0x02 漏洞分析
由于输入字符串缺失结尾标志符,从而导致读取字符串时读取到了字符串以外的内存数据,最终导致了该漏洞的产生。这个漏洞发生在hlink!WzDupWzToWz() 函数里,当该函数进行字符串复制的时候产生了漏洞,成功利用该漏洞可导致信息泄露。
首先我们看一下这个特制的XLS文件,在偏移0x66C 和 0x140DC处分别不同,POC文件和正常文件在这两处对比如图:
图1 正常文件和POC文件在偏移0x66c处对比
图2 正常文件和POC文件在偏移0x140dc处对比
然后我们用工具Offvis来解析POC文件如图:
图3 POC文件0x66c处解析
图4 POC文件0x140dc处解析
从图3我们看到,0x66C处对应的是ModifyTime域,实际上它不会导致漏洞产生,这里我们忽略它。从图4可以看到0x140dc处的 字节D0对应complexData域。并且complexData是fopt (OfficeArtRGFOPTE)结构的一部分,OfficeArtRGFOPTE结构被微软定义为:
结构
从上面的定义中,我们看不到complexData域包含特定的结构。
然后我们在windbg用如下方式设置断点:
bu hlink!HLNK::GetMonikerReference " .printf "GetMonikerReference:\n"; db poi(poi(esp+4)+0x4c);"
该断点被断几次后你会看到如下调试信息:
从上面调试信息可以看到,堆缓冲区0x16c52fe8处包含了complexData域的一部分。它指向一个没有结束标志符的宽字节字符串。
下面是hlink!HLNK::GetMonikerReference函数的部分代码,它调用 hlink!WzDupWzToWz() 函数来处理这个宽字节字符串。
下图是对函数hlink!WzDupWzToWz()的分析
函数分析
总的来说,该问题是由于读取输入字符串的时候,该字符串没有结束标识符,从而读取到了该字符串内存以外的数据造成的。这个过程是 hlink!WzDupWzToWz() 函数进行字符串复制操作的时候发生的。
库文件hlink.dll时用来处理超链接对象的。我们可以通过如下方式创建一个超链接来构造POC文件:
图7 在XLS 文件里创建超链接
我们把它保存为 test.xls,然后用 Offvis解析如下:
图8 新构造的EXCEL文件解析
从上图可以清楚第看到我们创建的超链接被存储在了HLink 结构中,HLink结构被微软定义如下:
Hyperlink结构定义如下:
根据上面的定义,我们可以通过与HLink结构进行对比,来推断complexData域的数据结构。上面构造的test.xls里HLink结构如下:
由此推断complexData域数据内部结构如下(译者注:这里红框中00 D0,可能应该是 00 00):
我们修改hyperlinkBitFields字段的值为 |08 00 00 00|
,修改HyperlinkString字段的字符串结束符NULL 为 |00 D0|
如图:
保存后在WIN7 和WIN10里测试,可以触发漏洞。下图是在WIN10里的截图:
如上图所示,打开修改后的test.xls,可以看到hlink.dll并没有被加载。然后点击超链接"test",这时候hlink.dll被加载,并触发了漏洞,如图: