Microsoft released bulletin MS09-067 on Nov 10, 2009. Same as in 2008, this last bulletin for Microsoft Office Excel in 2009 gives a total number of 17 vulnerabilities for this popular product. As the biggest contributor, Fortinet is credited for seven of these vulnerabilities in 2009. Our topic today is the vulnerability referred as CVE-2009-3127. It is one of the eight vulnerabilities that were fixed in Bulletin MS09-067. I found this vulnerability by fuzzing (automatic crafted files creation) in April and when I analyzed it I found it is different from other vulnerabilities and so does the patch from Microsoft: the patched Excel is still crashing when proof of concept file is opened! What’s going on!? Does the patch work? You will find the answer in this blog post. My test environment is Microsoft Office 2003 SP3 under Windows XP SP3. The patch updates the Excel.exe file from version 11.0.8307.0 to 11.0.8316.0.
First we need to know what’s the CVE-2009-3127 is. What causes this vulnerability? The following is cited from bulletin MS09-067:
“The vulnerability exists in the way that Microsoft Office Excel parses
the Excel spreadsheet file format when opening a specially crafted
Excel spreadsheet.“
The spreadsheet format mentioned above is Excel Binary File Format (.xls). Regarding CVE-2009-3127, when Excel parses a crafted record SXDB(0xC6) in pivot cache stream (refer to page 53 of MS-XLS), if member cfdbdb is greater than cfdbTot (refer to the highlighted value in Figure 1), it will crash or execute code if the file is well-crafted.
Figure 1: crafted Excel file details
You may think this vulnerability is due to a lack of
sufficient sanitization on SXDB record. Let’s see the associated code in unpatched Excel.exe (11.0.8307.0). The crafted SXDB record is process at offset 0x301B5926.
.text:301B5926 sub_301B5926 proc near ; CODE XREF: sub_300E45E9+D1779p
.text:301B5926
.text:301B5926 push ebp
.text:301B5927 lea ebp, [esp-304h]
.text:301B592E sub esp, 384h
…
.text:301B5AFC push eax
.text:301B5AFD push 14h
.text:301B5AFF push 0C6h———————————-expected record type: SXDB(0xC6)
.text:301B5B04 push edi
.text:301B5B05 call sub_300DA264 ————————Read in record SXDB, edi point to the record data
.text:301B5B0A test eax, eax
.text:301B5B0C mov [ebp+304h+var_33C], eax
.text:301B5B0F js loc_30274DA9
.text:301B5B15 mov esi, [ebp+304h+var_330]————-esi point to structure created for this pivot cache stream
.text:301B5B18 mov [esi], ebx
.text:301B5B1A movsx eax, word ptr [edi+8]
.text:301B5B1E mov [esi+10h], eax
.text:301B5B21 mov eax, [edi]
.text:301B5B23 mov [esi+14h], eax
.text:301B5B26 movsx eax, word ptr [edi+0Ah]
.text:301B5B2A mov [esi+24h], eax————————-store cfdbdb
.text:301B5B2D movsx eax, word ptr [edi+0Ch]
.text:301B5B31 mov [esi+28h], eax————————-store cfdbTot
…
.text:301B5C19 mov eax, [esi+24h]
.text:301B5C1C cmp eax, [esi+28h]————————-compare cfdbdb with cfdbTot
.text:301B5C1F ja loc_301B5CEC
…
.text:301B5CEC push ebx
.text:301B5CED push ebx
.text:301B5CEE push esi
.text:301B5CEF call sub_30602D11—————————clear the structure pointed by esi!!!
As you can see, cfdbdb value is compared with cfdbToc value and the associate structure (remember this structure, we will refer to it later) is cleared if it is illegal. This is the unpatched version! It is not vulnerable. Let’s see whether the patched version improved this function. The function moves to address 301ABE5A in version 11.0.8316.0 and nothing changed! Now it is clear that the function handling SXDB record is not responsible for this vulnerability. But how cfdbdb can be the attack vector of this vulnerability?
Let’s see the real vulnerable code in unpatched Excel.exe(11.0.8307.0). The record SXVI(0xB2) in WorkSheet is processed at offset 0x301C0C2B
.text:301C0C2B sub_301C0C2B proc near ; CODE XREF: sub_301C0F83+E9p
.text:301C0C2B
.text:301C0C2B push ebp
.text:301C0C2C mov ebp, esp
…
.text:301C0C8F push 8
.text:301C0C91 push 0B2h————————————expected record type: SXVI(0xB2)
.text:301C0C96 push edi
.text:301C0C97 call sub_300DA264 ————————-Read in record SXVI
…
.text:301C0D4C test word ptr [esi], 8800h
.text:301C0D51 jnz loc_302767F6
…
.text:302767F6 loc_302767F6: ; CODE XREF: sub_301C0C2B+126j
.text:302767F6 movsx eax, word ptr [esi+4]
.text:302767FA push eax
.text:302767FB push [ebp+arg_18]————————–The SXVD(0xB1) record number
.text:302767FE call sub_301B0A05————————-The real vulnerable function!
.text:30276803 test byte ptr [esi+1], 8
.text:30276807 jz short loc_3027680D
.text:30276809 or byte ptr [eax+9], 8———————-eax register is controllable by changing SXVD(0xB1) record numbers!
As I comment inline, function at 0x301B0A05 is responsible for this vulnerability:
.text:301B0A05 sub_301B0A05 proc near ; CODE XREF: sub_301B0A3F+E3p
.text:301B0A05
.text:301B0A05 mov ecx, [esp+arg_0]
.text:301B0A09 mov eax, dword_30896958—————–The structure that have been cleared in 301B5926,remember it?
.text:301B0A0E cmp ecx, [eax+24h]————————-compare ecx=0×89 with [eax+24] which is cfdbdb (0 since the structure was cleared)
.text:301B0A11 jge loc_3029425C—————————-go to wrong path and the return result is controllable
…
.text:3029425C mov edx, [eax+2Ch]
.text:3029425F imul ecx, 1E4h——————————–SXVD(0xB1) record numbers
.text:30294265 mov eax, [esp+arg_4]
.text:30294269 inc eax
.text:3029426A imul eax, 0Ch
.text:3029426D add eax, [edx+ecx+1A8h]
.text:30294274 jmp locret_301B0A3C
Now, we are clear about this vulnerability: The function processing SXDB record cleared the structure when it found malformed SXDB record, but the code using this structure doesn’t handle this case. The cooperation of the producer and consumer failed.
Let’s see how Microsoft improves the function at offset 0x301B0A05 in the patched version. The function moved to address 301A7431.
.text:301A7431 sub_301A7431 proc near ; CODE XREF: sub_301A7474+E3p
.text:301A7431
.text:301A7431 mov ecx, [esp+arg_0]
.text:301A7435 mov eax, dword_308960A8
.text:301A743A cmp ecx, [eax+28h]—————————compare ecx=0×89 with [eax+28] which is cfdbTot (0 since the structure was cleared)
.text:301A743D jnb loc_30294818——————————patch point, jump to address 30294818 in our case
.text:301A7443 cmp ecx, [eax+24h]
.text:301A7446 jge loc_3029481F
…
.text:30294818 xor eax, eax————————————-clear eax
.text:3029481A jmp locret_301A7471
Without handling this 0 return value, Excel crash at address 30276DC1:
.text:30276DB6 call sub_301A7431——————————return 0
.text:30276DBB test byte ptr [esi+1], 8
.text:30276DBF jz short loc_30276DC5
.text:30276DC1 or byte ptr [eax+9], 8————————-Excel crashes with an access violation exception, the crash is non-exploitable
The patch is very simple. It just adds one more validation for cfdbdb when handling SXVI record and return zero if the validation fail. Excel doesn’t handle this zero value smoothly and crashes again. This is acceptable for Excel since the crash becomes non-exploitable. As a conclusion, the patch for CVE-2009-3127 is unshaped but we are safe now.


Twitter
FaceBook
LinkedIn
YouTube