MICROSOFT WINDOWS Ndistapi.sys IRQL escalation Rubén Santamarta [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@reversemode.com 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