<<< Date Index >>>     <<< Thread Index >>>

[Reversemode Advisory] Microsoft Windows Ndistapi.sys IRQL escalation



MICROSOFT WINDOWS
Ndistapi.sys IRQL escalation

Rubén Santamarta <ruben (at) reversemode (dot) com> [Email concealed]
        
Affected products:
 Microsoft Windows XP SP2
 Microsoft Windows 2003 Server SP1


Introduction
-------------

NDISTAPI.sys is a kernel-mode component that exposes connectionless
miniport drivers to the TAPI device space. NDISTAPI accepts call setup
and teardown requests from the TAPI service provider and directs such
requests through NDISWAN to the correct miniport driver to set up,
monitor, and tear down lines and calls.

Flaw
-----

 “\Device\NdisTapi”  is exposed to unprivileged users. Hence, any
user-mode application can write data to this device.

Let's see:

Ndistapi.sys
Windows XP SP2

_; __stdcall NdisTapiDispatch(x, x)
.text:000115E8 _NdisTapiDispatch@8 proc near           ; DATA XREF:
DriverEntry(x,x)+13E#o
.text:000115E8
.text:000115E8 arg_4           = dword ptr  0Ch
.text:000115E8
.text:000115E8                 push    ebp
.text:000115E9                 mov     ebp, esp
.text:000115EB                 push    ebx
.text:000115EC                 push    esi
.text:000115ED                 mov     esi, [ebp+arg_4]
.text:000115F0                 mov     eax, [esi+60h]
.text:000115F3                 movzx   ecx, byte ptr [eax]
.text:000115F6                 sub     ecx, 0
.text:000115F9                 mov     edx, [esi+0Ch]
.text:000115FC                 mov     ebx, [eax+4]
.text:000115FF                 push    edi
.text:00011600                 mov     edi, [eax+8]
.text:00011603                 jz      short loc_1167E
.text:00011605                 dec     ecx
.text:00011606                 dec     ecx
.text:00011607                 jz      short loc_11674
.text:00011609                 sub     ecx, 0Ch
.text:0001160C                 jnz     loc_11697
.text:00011612                 mov     eax, [eax+0Ch]
.text:00011615                 cmp     eax, 8FFF23C0h  ;IOCTL
.text:0001161A                 jz      short loc_11669 ;DoIoctlConnectWork()
.text:0001161C                 cmp     eax, 8FFF23C8h
.text:00011621                 jz      short loc_1165C
{...}
.text:00010B16 ; __stdcall DoIoctlConnectWork(x, x, x, x)
.text:00010B16 _DoIoctlConnectWork@16 proc near        ; CODE XREF:
NdisTapiDispatch(x,x)+85#p
.text:00010B16
.text:00010B16 arg_0           = dword ptr  4
.text:00010B16 arg_4           = dword ptr  8
.text:00010B16 arg_8           = dword ptr  0Ch
.text:00010B16 arg_C           = dword ptr  10h
.text:00010B16
.text:00010B16                 mov     ecx, _DeviceExtension
.text:00010B1C                 push    edi
.text:00010B1D                 mov     edi,
ds:__imp_@KfAcquireSpinLock@4 ; KfAcquireSpinLock(x)
.text:00010B23                 add     ecx, 4Ch
.text:00010B26                 call    edi ; KfAcquireSpinLock(x) ;<=
FLAW KfAcquireSpinLock(x)
.text:00010B28                 cmp     [esp+4+arg_8], 8  ;InputBuffer length
.text:00010B2D                 mov     dl, al
.text:00010B2F                 jb      loc_10BC5
.text:00010B35                 cmp     [esp+4+arg_C], 4  ;OutputBuffer
length
.text:00010B3A                 jb      loc_10BC5
.text:00010B40                 mov     ecx, _DeviceExtension
.text:00010B46                 cmp     dword ptr [ecx+4], 1
.text:00010B4A                 push    ebx
.text:00010B4B                 mov     ebx, [esp+8+arg_4]
.text:00010B4F                 push    esi
.text:00010B50                 mov     esi,
ds:__imp_@KfReleaseSpinLock@8 ; KfReleaseSpinLock(x,x)
.text:00010B56                 jnz     short loc_10B8D
.text:00010B58                 mov     dword ptr [ecx+4], 2
.text:00010B5F                 mov     ecx, _DeviceExtension
.text:00010B65                 mov     eax, [ebx]
.text:00010B67                 mov     [ecx+10h], eax
.text:00010B6A                 mov     ecx, _DeviceExtension
.text:00010B70                 add     ecx, 4Ch
.text:00010B73                 call    esi ; KfReleaseSpinLock(x,x) ;
KfReleaseSpinLock(x,x)

[---]

.text:00010BC5
.text:00010BC5 loc_10BC5:
.text:00010BC5
.text:00010BC5                 mov     eax, 0C0000023h  ; ERROR CODE
.text:00010BCA                 xor     ecx, ecx
.text:00010BCC
.text:00010BCC loc_10BCC:
.text:00010BCC                 mov     edx, [esp+4+arg_0]
.text:00010BD0                 mov     [edx+18h], eax
.text:00010BD3                 mov     [edx+1Ch], ecx
.text:00010BD6                 pop     edi
.text:00010BD7                 retn    10h              ; Return


As we can see, this routine raises IRQL to DISPATCH level acquiring an
spinlock before checking the lengths. After that,if the sizes supplied
are invalid, the routine returns without releasing the acquired spinlock
so the IRQL is still at DISPATCH level for that thread, even after
returning to Ring3.

The final result is an user-mode thread running at DISPATCH level so the
system can crash unexpectly since at DISPATCH level  paged memory cannot
be accesed, obviously in user-mode the  most of memory is paged so the
kernel will bugcheck due to IRQL_LESS_THAN_NOT_EQUAL  whenever our
thread performs  an operation which involves accessing paged memory.

Impact
-------

Windows Kernel assumes that a user-mode thread cannot be running at
DISPATCH level so it considers the IRQL as a discriminant in various
operations.
I.e  reversing MmAccessFault.

Ntoskrnl.exe
Windows XP SP2

.text:00411DAC                 mov     edi, edi
.text:00411DAE                 push    ebp
.text:00411DAF                 mov     ebp, esp
.text:00411DB1                 sub     esp, 24h
.text:00411DB4                 and     [ebp+VirtualAddress], 0
.text:00411DB8                 push    ebx
.text:00411DB9                 push    esi
.text:00411DBA                 push    edi
.text:00411DBB                 mov     eax, large fs:124h
.text:00411DC1                 mov     ebx, [eax+44h]
.text:00411DC4                 mov     [ebp+var_24], ebx
.text:00411DC7                 call    ds:__imp__KeGetCurrentIrql@0 ;
KeGetCurrentIrql()
.text:00411DCD                 mov     edi, [ebp+BugCheckParameter1]
.text:00411DD0                 and     [ebp+var_C], 0
.text:00411DD4                 mov     esi, edi
.text:00411DD6                 shr     esi, 0Ah
.text:00411DD9                 shr     edi, 14h
.text:00411DDC                 and     esi, 3FFFFCh
.text:00411DE2                 and     edi, 0FFCh
.text:00411DE8                 sub     esi, 40000000h
.text:00411DEE                 sub     edi, 3FD00000h
.text:00411DF4                 cmp     al, 1
.text:00411DF6                 mov     [ebp+var_1], al
.text:00411DF9                 ja      loc_428DB7

A vector attack which  leads to a local privilege escalation has not
been identified yet but this possibility cannot be  completely
discarded. Security software can  be affected by malware exploiting this
flaw in imaginative ways.

Disclosure Timeline

10.20.2006 – Initial vendor notification
10.21.2006 – Initial vendor response. Case opened.
01.04.2007 – Vendor confirmed vulnerability. Service pack fix.
03.12.2007 – Vulnerability silently addressed on Windows 2003 SP2.

Exploits
No exploits are released. Ethical security companies can contact for
requesting samples : contact@xxxxxxxxxxxxxxx


References:
http://www.microsoft.com/downloads/details.aspx?familyid=95AC1610-C232-4644-B828-C55EEC605D55&displaylang=en
http://www.reversemode.com/index.php?option=com_remository&Itemid=2&func=fileinfo&id=47
(PDF)

--
Reversemode
Advanced Reverse Engineering Services
www.reversemode.com