首页 -> 安全研究

安全研究

安全漏洞
Microsoft GDI+库WMF图形处理缓冲区溢出漏洞(MS08-052)

发布日期:2008-09-09
更新日期:2008-09-11

受影响系统:
Microsoft Office XP SP3
Microsoft Office 2007
Microsoft Office 2003 Service Pack 2
Microsoft PowerPoint Viewer 2003
Microsoft SQL Server 2005 SP2
Microsoft Windows XP x64 SP2
Microsoft Windows XP x64
Microsoft Windows XP SP3
Microsoft Windows XP SP2
Microsoft Windows Vista SP1
Microsoft Windows Vista
Microsoft Windows Server 2008
Microsoft Windows Server 2003 SP2
Microsoft Windows Server 2003 SP1
Microsoft Works 8.0
Microsoft .NET Framework 1.0 SP3
Microsoft Visio 2002 SP2
Microsoft Forefront Client Security 1.0
Microsoft Report Viewer 2008 SP1
Microsoft Report Viewer 2005 SP1
描述:
BUGTRAQ  ID: 31021
CVE(CAN) ID: CVE-2008-3014

Microsoft产品中所使用的GDI+库(GdiPlus.dll)通过基于类的API提供对各种图形方式的访问。

GDI+库为WMF图像文件分配内存的方式中存在一个远程执行代码漏洞,如果用户打开特制的WMF图像文件或浏览包含特制内容的网站,该漏洞可能允许远程执行指令。

Microsoft产品中所使用的GDI+库(GdiPlus.dll)通过基于类的API提供对各种图形方式的访问。

GDI+库为WMF图像文件分配内存的方式中存在一个整数溢出漏洞。在通过GDI+ API解析WMF文件时,会调用WmfEnumState::ProcessRecord()处理每个记录。如果是0x0538(PolyPolygon)记录类型的话会调用WmfEnumState::PolyPolygon()。

...
.text:4ECD7C69 loc_4ECD7C69: ; CODE XREF: WmfEnumState::ProcessRecord(EmfPlusRecordType,uint,uchar const *)+BC
.text:4ECD7C69 mov ecx, 10538h
.text:4ECD7C6E cmp eax, ecx
.text:4ECD7C70 jg loc_4ECD7D8B
.text:4ECD7C76 jz loc_4ECD7D7F
...
.text:4ECD7D7F loc_4ECD7D7F: ; CODE XREF: WmfEnumState::ProcessRecord(EmfPlusRecordType,uint,uchar const *)+288
.text:4ECD7D7F mov ecx, esi
.text:4ECD7D81 call ?PolyPolygon@WmfEnumState@@QAEXXZ ; WmfEnumState::PolyPolygon(void)

::PolyPolygon()中检索一个指向PolyPolygon记录内容的指针并读取前第一个16位参数。该参数说明所指定的polygon数目。

.text:4ECD5E2A ; public: void __thiscall WmfEnumState::PolyPolygon(void)
.text:4ECD5E2A ?PolyPolygon@WmfEnumState@@QAEXXZ proc near
.text:4ECD5E2A ; CODE XREF: WmfEnumState::ProcessRecord(EmfPlusRecordType,uint,uchar const *)+393
.text:4ECD5E2A
.text:4ECD5E2A var_8 = dword ptr -8
.text:4ECD5E2A iTotalPoints = dword ptr -4
.text:4ECD5E2A
.text:4ECD5E2A mov edi, edi
.text:4ECD5E2C push ebp
.text:4ECD5E2D mov ebp, esp
.text:4ECD5E2F push ecx
.text:4ECD5E30 push ecx
.text:4ECD5E31 and [ebp+iTotalPoints], 0
.text:4ECD5E35 push esi
.text:4ECD5E36 mov esi, ecx
.text:4ECD5E38 mov eax, [esi+5Ch] ; pointer to record parameters
.text:4ECD5E3B push edi
.text:4ECD5E3C movzx edi, [eax+PolyPolygon.NumberOfPolygons]
.text:4ECD5E3F test edi, edi
.text:4ECD5E41 jbe short loc_4ECD5E53 ; zero polygons?

如果polygon的数量为非0的话,就会由一个循环读取这个数量的16位字,每一个字都指定了该polygon中的点数,总和就是所有polygon中的总点数。

.text:4ECD5E43 add eax, 2 ; skip to array aPointsPerPolygon
.text:4ECD5E46 mov ecx, edi
.text:4ECD5E48
.text:4ECD5E48 @loop_read_aPointsPerPolygon: ; CODE XREF: WmfEnumState::PolyPolygon(void)+27
.text:4ECD5E48 movzx edx, word ptr [eax] ; PointsPerPolygon
.text:4ECD5E4B add [ebp+iTotalPoints], edx
.text:4ECD5E4E inc eax
.text:4ECD5E4F inc eax
.text:4ECD5E50 dec ecx
.text:4ECD5E51 jnz short @loop_read_aPointsPerPolygon

接下来会计算存储点(两个均为32位的值)加上polygon点计数数组(一个32位值)所需的大小,而这些运算可能出现整数溢出。所生成的结果传送给了::CreateRecordToModify()以分配新的空记录。

.text:4ECD5E53 mov eax, [ebp+iTotalPoints]
.text:4ECD5E56 lea eax, [edi+eax*2] ; num polygons + 2 * num points
.text:4ECD5E59 shl eax, 2 ; *4
.text:4ECD5E5C push eax
.text:4ECD5E5D mov ecx, esi
.text:4ECD5E5F call ?CreateRecordToModify@MfEnumState@@IAEHH@Z ; MfEnumState::CreateRecordToModify(int)

::CreateRecordToModify()将对其传送的大小处理为有符整数,如果值为负数的话,会使用记录头的WMF记录的大小。

.text:4ECD5406 ; protected: int __thiscall MfEnumState::CreateRecordToModify(int)
.text:4ECD5406 ?CreateRecordToModify@MfEnumState@@IAEHH@Z proc near
.text:4ECD5406 ; CODE XREF: EmfEnumState::CreateCopyOfCurrentRecord(void)+1D
.text:4ECD5406 ; EmfEnumState::CreateModifiedDib(tagBITMAPINFOHEADER *,uchar *,uint &,ulong)+85 ...
.text:4ECD5406
.text:4ECD5406 iSize = dword ptr 8
.text:4ECD5406
.text:4ECD5406 mov edi, edi
.text:4ECD5408 push ebp
.text:4ECD5409 mov ebp, esp
.text:4ECD540B cmp [ebp+iSize], 0
.text:4ECD540F push esi
.text:4ECD5410 mov esi, ecx
.text:4ECD5412 jg short loc_4ECD541C ; positive, non-zero size?
.text:4ECD5414 mov eax, [esi]
.text:4ECD5416 call dword ptr [eax+0Ch] ; gdiplus.4ECD59D4 - WmfEnumState::GetCurrentRecordSize()
.text:4ECD5419 mov [ebp+iSize], eax ; use the size taken from the WMF record header

如果大小小于2048字节,会返回到预分配缓冲区的指针,否则使用HeapAlloc()分配缓冲区。如果计算的请求大小为负值计算溢出,就可能分配不充分的缓冲区。

之后将WMF文件数据拷贝到了新分配的结构中。首先,一个循环从每个polygon读取16位的点计数,通过添加0将其扩展到32位,写入到新的缓冲区。如果分配了不充分的缓冲区,写入数据就会超过缓冲区的末尾。

.text:4ECD5E68 mov ecx, [esi+98h] ; pointer to new Record
.text:4ECD5E6E lea edx, [ecx+edi*4] ; pointer into new Record past aPointsPerPolygon
.text:4ECD5E71 xor eax, eax
.text:4ECD5E73 test edi, edi
.text:4ECD5E75 push ebx
.text:4ECD5E76 mov [ebp+lpPoints], edx
.text:4ECD5E79 jbe short loc_4ECD5E8B ; zero polygons?
.text:4ECD5E7B
.text:4ECD5E7B @loop_copy_aPointsPerPolygon: ; CODE XREF: WmfEnumState::PolyPolygon(void)+5F
.text:4ECD5E7B mov ebx, [esi+5Ch] ; pointer to source record
.text:4ECD5E7E movzx ebx, word ptr [ebx+eax*2+2] ; entry in aPointsPerPolygon array
.text:4ECD5E83 mov [ecx+eax*4], ebx ; write to destination record
.text:4ECD5E86 inc eax
.text:4ECD5E87 cmp eax, edi
.text:4ECD5E89 jb short @loop_copy_aPointsPerPolygon ; more polygons?

接下来另一个循环将所有实际的点拷贝到新的结构,每个点都由两个16位值组成,在写之前都扩展到32位。如果分配了不充分的缓冲区,这个循环会再一次溢出缓冲区。

.text:4ECD5E8B mov ebx, [ebp+iTotalPoints]
.text:4ECD5E8E test ebx, ebx
.text:4ECD5E90 mov eax, [esi+5Ch] ; pointer to source record
.text:4ECD5E93 lea eax, [eax+edi*2+2] ; start of points array
.text:4ECD5E97 jbe short loc_4ECD5EB3 ; zero points?
.text:4ECD5E99 mov [ebp+iTotalPoints], ebx
.text:4ECD5E9C
.text:4ECD5E9C @loop_copy_points: ; CODE XREF: WmfEnumState::PolyPolygon(void)+87
.text:4ECD5E9C movsx ebx, word ptr [eax]
.text:4ECD5E9F mov [edx], ebx
.text:4ECD5EA1 movsx ebx, word ptr [eax+2]
.text:4ECD5EA5 mov [edx+4], ebx
.text:4ECD5EA8 add edx, 8 ; skip to next point in destination
.text:4ECD5EAB add eax, 4 ; skip to next point in source
.text:4ECD5EAE dec [ebp+iTotalPoints]
.text:4ECD5EB1 jnz short @loop_copy_points ; more points?

成功利用此漏洞的攻击者可完全控制受影响的系统。攻击者可随后安装程序;查看、更改或删除数据;或者创建拥有完全用户权限的新帐户。那些帐户被配置为拥有较少系统用户权限的用户比具有管理用户权限的用户受到的影响要小。

<*来源:Assurent Secure Technologies
  
  链接:http://secunia.com/advisories/31675/
        http://marc.info/?l=full-disclosure&m=122109742720458&q=p3
        http://www.microsoft.com/technet/security/bulletin/ms08-052.mspx?pf=true
        http://www.us-cert.gov/cas/techalerts/TA08-253A.html
*>

建议:
临时解决方法:

* 限制对gdiplus.dll的访问。
    
    1. 从提升的管理员命令提示符处运行下列命令:

for /F "tokens=*" %G IN ('dir /b /s %windir%\winsxs\gdiplus.dll') DO cacls %G /E /P everyone:N
for /F "tokens=*" %G IN ('dir /b /s ^"%programfiles%\microsoft office\gdiplus.dll^"') DO cacls "%G" /E /P everyone:N
for /F "tokens=*" %G IN ('dir /b /s ^"%programfiles^(x86^)%\microsoft office\gdiplus.dll^"') DO cacls "%G" /E /P everyone:N

    2. 重新启动

* 注销vgx.dll。
    
    1. 依次单击“开始”、“运行”,键入 "%SystemRoot%\System32\regsvr32.exe" -u "%CommonProgramFiles%\Microsoft Shared\VGX\vgx.dll",然后单击“确定”。
    2. 此时将出现一个对话框,确认注销过程已成功完成。单击“确定”关闭对话框。

* 阻止在Internet Explorer中运行COM对象。
    
    请将以下文本粘贴于记事本等文本编辑器中,然后使用.reg文件扩展名保存文件。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\ActiveX Compatibility\{FA91DF8D-53AB-455D-AB20-F2F023E498D3}]

"Compatibility Flags"=dword:00000400

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\ActiveX Compatibility\{FA91DF8D-53AB-455D-AB20-F2F023E498D3}]

"Compatibility Flags"=dword:00000400

    您可以通过双击此.reg文件将其应用到各个系统。您还可以使用组策略跨域应用该文件。

厂商补丁:

Microsoft
---------
Microsoft已经为此发布了一个安全公告(MS08-052)以及相应补丁:
MS08-052:Vulnerabilities in GDI+ Could Allow Remote Code Execution (954593)
链接:http://www.microsoft.com/technet/security/bulletin/ms08-052.mspx?pf=true

浏览次数:6424
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障