This month Microsoft patched two vulnerabilities which were discovered and reported by me, one is an information disclosure vulnerability in Internet Explorer (IE) (CVE-2016-0059 in MS16-009), the other is a memory corruption vulnerability in Microsoft Office (CVE-2016-0055 in MS16-015). In this blog, we will provide in-depth analysis of CVE-2016-0059. The vulnerability exists because Microsoft Hyperlink Object Library improperly discloses the contents of its memory. An attacker who successfully exploited this vulnerability could obtain information to further compromise the user’s system. To exploit the vulnerability, an attacker must convince a user to either click a link in an email message or open an Office file, and then click a link in the file.
In my original vulnerability report to Microsoft, I marked the vulnerability as Microsoft Office Excel heap overflow vulnerability. Because the vulnerability actually lies in the library hlink.dll (Microsoft Hyperlink Object Library) which is a component in Internet Explorer, Microsoft classifies it as Internet Explorer information disclosure vulnerability. In this blog, I still use Microsoft Office to demonstrate and analyze this vulnerability.
What Products Are Affected?
All major IE versions are affected by this vulnerability.
IE11 (including the version for Windows 10)
Proof of Concept
To reproduce the vulnerability, we can open the PoC FG-VD-15-073_PoC.xls with Microsoft Office Excel 2007. Then we can see Excel.exe crashes and the crash information shows below:
(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
6cd40b40 668b06 mov ax,word ptr [esi] ds:002b:18b23000=????
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
770f32e6 combase!CRetailMalloc_Alloc+0x00000016 [d:\th\com\combase\class\memapi.cxx @ 641]
6cd40c32 hlink!operator new+0x00000023
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files (x86)\Common Files\Microsoft Shared\office12\mso.dll -
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files (x86)\Microsoft Office\Office12\oart.dll -
0:000> dp 18b22fe8
18b22fe8 00720041 00610072 00440079 006d0075
18b22ff8 00320070 d0d0d000 ???????? ????????
18b23008 ???????? ???????? ???????? ????????
18b23018 ???????? ???????? ???????? ????????
18b23028 ???????? ???????? ???????? ????????
18b23038 ???????? ???????? ???????? ????????
18b23048 ???????? ???????? ???????? ????????
18b23058 ???????? ???????? ???????? ????????
# 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
The vulnerability arises from an attempt to read a string from an invalid memory location due to missing NULL terminator at the end of the input string. This happens during string duplication attempt in hlink!WzDupWzToWz() function. Successful exploitation of this vulnerability could lead to information disclosure.
Let’s look into the specially-crafted XLS file first. The minimized PoC file has two differences at offset 0x66C and 0x140DC respectively. The comparison between the normal XLS file and the minimized PoC file shows below.
Figure 1. The Normal XLS File vs The Minimized PoC File (Offset 0x66C)
Figure 2. The Normal XLS File vs The Minimized PoC File (Offset 0x140DC)
Then let’s use the tool Offvis to parse the minimized PoC file as follows.
Figure 3. Parsing of The Minimized PoC File (Offset 0x66c)
Figure 4. Parsing of the Minimized PoC File (Offset 0x140DC)
From figure 3, we can see the 8 bytes starting at offset 0x66c is the ModifyTime field. It actually doesn’t result in the vulnerability, so ignore it. From figure 4, we can see the byte |D0| at offset 0x140DC is in the complexData field. And the complexData field is a part of the fopt (OfficeArtRGFOPTE) structure. The OfficeArtRGFOPTE structure is defined by Microsoft as follows.
Figure 5. OfficeArtRGFOPTE Structure
From the above definition, we cannot find the complexData field contains specific structures.
Then let’s set a breakpoint as follows in WinDbg.
bu hlink!HLNK::GetMonikerReference " .printf \"GetMonikerReference:\\n\"; db poi(poi(esp+4)+0x4c);"
After this breakpoint is hit several times, you can get the following debug information.
From the above debug information, we can see the heap buffer starting at 0x16c52fe8 contains part of the complexData field. It's a wide string without NULL terminator.
The following is a snippet of function hlink!HLNK::GetMonikerReference which calls the function hlink!WzDupWzToWz() to handle the wide string.
The following is the analysis of the function hlink!WzDupWzToWz().
Figure 6. The Analysis of Function hlink!WzDupWzToWz() in IDA Pro
In conclusion, the issue arises from an attempt to read a string from an invalid memory location due to missing NULL terminator at the end of the input string. This happens during string duplication attempt in hlink!WzDupWzToWz() function.
The library hlink.dll is used to handle Hyperlink objects. We might manually construct the PoC file via creating a hyperlink as follows.
Figure 7. Create a Hyperlink in XLS File.
Save it as test.xls and use the tool Offvis to parse it as follows.
Figure 8. Parsing of The New Excel File
From the above, we can clearly see that the created hyperlink is stored in a HLink structure. The HLink structure is defined by Microsoft as follows.
The Hyperlink structure is defined by Microsoft as follows.
Let’s compare the data of HLink structure with the complexData field. The following is the HLink structure in test.xls.
Figure 9. HLink Structure in test.xls
Then we can speculate the inner structure of the complexData field as follows.
Figure 10. Inner Structure of The complexData Field
Let's modify the value of hyperlinkBitFields to |08 00 00 00| and modify the NULL terminator to |00 D0| in string of HyperlinkString as follows.
Figure 11. Modified HLink Structure in test.xls
Save it and test the modified test.xls in Windows 7 and Windows 10. It can trigger this vulnerability. The following is the test screenshots in Windows 10.
Figure 12. Open The Manually-Crafted PoC File in Windows 10
When open the modified test.xls, hlink.dll isn't loaded. Then click the hyperlink of the "test" string, hlink.dll is loaded and it triggers this vulnerability.
Figure 13. Crash Triggered by The Manually-Crafted PoC File in Windows 10
All users of Microsoft IE are encouraged to upgrade to the latest version of this software. Additionally, organizations that have deployed Fortinet IPS solutions are already protected from this vulnerability with the signature MS.IE.hlink.WzDupWzToWz.Memory.Corruption.