安全研究

安全漏洞
Microsoft Windows SMB WRITE_ANDX处理拒绝服务漏洞(MS09-001)

发布日期:2008-09-15
更新日期:2009-01-13

受影响系统:
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 Windows 2000SP4
描述:
BUGTRAQ  ID: 31179
CVE(CAN) ID: CVE-2008-4114

Windows是微软发布的非常流行的操作系统。

Windows的srv.sys驱动处理畸形WRITE_ANDX SMB报文的方式存在内核拒绝服务漏洞,如果未经认证的远程攻击者能够向使用命名管道端点的接口发送WRITE_ANDX报文的话,就可以触发这个漏洞。

Srv.sys是用于处理SMB报文的驱动。报文被解析后,会通过合适的驱动路由。以下是srv.sys解析报文某些重要字段的方式:

Módulo: srv.sys     Vista SP1
PAGE:00048583                 movzx   ecx, word ptr [ebx+17h]     ; Packet. DataOffset
PAGE:00048587                 mov     [ebp+var_50], ecx
PAGE:0004858A                 mov     eax, [esi+78h]          ; Packet
PAGE:0004858D                 add     eax, ecx            ; Packet.Data[]
PAGE:0004858F                 mov     [ebp+VirtualAddress], eax
PAGE:00048592                 mov     eax, [esi+6Ch]
PAGE:00048595                 mov     eax, [eax+10h]
PAGE:00048598                 sub     eax, ecx                    ; Real packet len - DataOffset PAGE:0004859A                 movzx   edi, word ptr [ebx+15h]    ;
Packet.DataLen PAGE:0004859E                 cmp     edi, eax
PAGE:000485A0                 jb      short loc_485A4
PAGE:000485A2                 mov     edi, eax

在这部份代码中,驱动应添加检查,以防在偏移与报文真实大小不一致时仍然继续。之后srv.sys构建(或重新使用)FILESYSTE_CONTROL IRP(0xD),其IOCTL为0x119FF8(FSCTL_PIPE_INTERNAL_WRITE, METHOD_BUFFERED),然后通过调用IofCallDriver将这个IRP发送给正确的驱动。IRP包含有报文,但如果考虑到报文的内部字段,这并不意味IRP在内存使用方面保持一致。

Módulo: srv.sys     Vista SP1
PAGE:00048C90                 push    ebx             ; int
PAGE:00048C91                 push    ebx             ; int
PAGE:00048C92                 push    ebx             ; int
PAGE:00048C93                 push    ebx             ; int
PAGE:00048C94                 push    edi             ; int
PAGE:00048C95                 push    [ebp+VirtualAddress] ; int
PAGE:00048C98                 push    119FF8h         ; int
PAGE:00048C9D                 push    0Dh             ; char
PAGE:00048C9F                 push    esi             ; int
PAGE:00048CA0                 mov     eax, [ebp+FileInformation]
PAGE:00048CA3                 push    dword ptr [eax+38h] ; FileObject
PAGE:00048CA6                 push    dword ptr [esi+80h] ; Irp
PAGE:00048CAC                 call    _SrvBuildIoControlRequest@44 ; SrvBuildIoControlRequest(x,x,x,x,x,x,x,x,x,x,x)
PAGE:00048D23                 mov     edx, [esi+80h]
PAGE:00048D29                 mov     ecx, [ebp+var_44]
PAGE:00048D2C                 call    ds:__imp_@IofCallDriver@8 ; IofCallDriver

这个IRP由npfs!NpCommonFileSystemControl处理。

Módulo: npfs.sys     Vista SP1

PAGE:0001885C loc_1885C:                  ; CODE XREF: NpCommonFileSystemControl(x,x)+E7 j
PAGE:0001885C                 cmp     eax, 119FF8h
PAGE:00018861                 jz      short loc_18896
PAGE:00018896 loc_18896:            ; CODE XREF: NpCommonFileSystemControl(x,x)+139 j
PAGE:00018896                 lea     eax, [ebp+var_C]
PAGE:00018899                 push    eax
PAGE:0001889A                 push    edx
PAGE:0001889B                 push    [ebp+Irp]
PAGE:0001889E                 call    _NpInternalWrite@12 ; NpInternalWrite(x,x,x)

在这个例程中,到达npfs!NpWriteDataQueue可能触发bug。

Npfs从列表获得包含有某些与连接相关的尚未完成IRP的项。

Módulo: npfs.sys     Vista SP1

PAGE:0001A187                 push    esi
PAGE:0001A188                 push    [ebp+arg_0]
PAGE:0001A18B                 call    _NpGetNextRealDataQueueEntry@8 ; NpGetNextRealDataQueueEntry(x,x)

驱动对检索到的项执行检查。由于这个检查,无法在memcpy调用中触发溢出:

Módulo: npfs.sys     Vista SP1

loc_1A1F6:                              ; CODE XREF: NpWriteDataQueue(x,x,x,x,x,x,x,x,x,x)+92 j

PAGE:0001A1F6                 mov     ecx, [ebx]      ; Packet.DataLen
PAGE:0001A1F8                 cmp     ecx, edi        ;  Entry.BufferLen ( 0x400 )
PAGE:0001A1FA                 jnb     short loc_1A1FE
PAGE:0001A1FC                 mov     edi, ecx
PAGE:0001A1FE
PAGE:0001A1FE loc_1A1FE:                              ; CODE XREF: NpWriteDataQueue(x,x,x,x,x,x,x,x,x,x)+A0 j
PAGE:0001A1FE                 cmp     dword ptr [eax+10h], 1
PAGE:0001A202                 jz      short loc_1A22D
PAGE:0001A204                 test    edi, edi
PAGE:0001A206                 jbe     short loc_1A22D
PAGE:0001A208                 push    5246704Eh       ; Tag
PAGE:0001A20D                 push    edi             ; NumberOfBytes
PAGE:0001A20E                 push    0               ; PoolType
PAGE:0001A210                 call    ds:__imp__ExAllocatePoolWithTag@12 ; ExAllocatePoolWithTag(x,x,x)

换句话说,对于任何memcpy可能拷贝的字节数,都会动态分配相同数量的字节数。因此,无法强制溢出的情况。

最后是触发bug的代码段:

PAGE:0001A23E                 push    edi             ; size_t
PAGE:0001A23F                 mov     eax, [ebp+arg_8] ; &Packet + Packet.DataOffset
PAGE:0001A242                 sub     eax, [ebx]      ;  (&Packet + Packet.DataOffset) – Packet.DataLength
PAGE:0001A244                 add     eax, [ebp+arg_C] ; &Packet + (Current)Packet.DataLength
PAGE:0001A247                 push eax             ; void *  
PAGE:0001A248                 push    [ebp+P]         ; void *
PAGE:0001A24B                 call    _memcpy

计算memcpy的参数读取SMB报文的数据字段,所生成的地址为memcpy的src参数,可能指向不确定的内存。在出现这个漏洞时,这个指针包含的地址超出了srv.sys所保留的NonPaged池缓冲区的末尾。如果这个不确定的内存无效的话,系统会BugCheck,触发内核级的拒绝服务。

<*来源:Ruben Santamarta (ruben@reversemode.com
  
  链接:http://marc.info/?l=bugtraq&m=122150111708026&w=2
        http://secunia.com/advisories/31883/
        http://www.microsoft.com/technet/security/bulletin/ms09-001.mspx?pf=true
        http://www.us-cert.gov/cas/techalerts/TA09-013A.html
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

http://www.milw0rm.com/exploits/6463

建议:
厂商补丁:

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

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