New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.
Starred by 4 users
Status: WontFix
Owner:
Email to this user bounced
Closed: Sep 2015
Cc:



Sign in to add a comment
Kernel-mode type-confusion vulnerability via NtUserSetInformationThread/UserThreadCsrApiPort
Reported by matttait@google.com, Jun 9 2015 Back to list
The Windows Kernel is subject to a kernel-mode type-confusion vulnerability inside win32k!NtUserSetInformationThread due to referencing a user-mode handle via ObReferenceObjectByHandle with a "NULL" type specified (it should instead be using *LpcPortObjectType to protect against this vulnerability).

This vulnerability can be triggered from inside CSRSS via the syscall win32k!NtUserSetInformationThread with ThreadInformationClass set to "UserThreadCsrApiPort" and the parameter of the syscall set to a HANDLE that is not an LPC object.

This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically
become visible to the public.

 
Additional information provided to Microsoft; Jun 9th:

This vulnerability allows a process running within user-mode to corrupt kernel-mode structures and allow an attacker to take full control of the operating system. Specifically, this vulnerability allows an attacker to run code in Ring-0 on Windows x64 without obtaining a driver-signing certificate, or submitting code to the Windows Hardware Certification service.

This issue is primarily to highlight that there are a number of places where the Windows kernel unsafely passes "NULL" as the "ObType" parameter to the "nt!ObReferenceObjectByHandle" function call - expecting that the result of the call to be a kernel-pointer to a specific type - rather than securely calling nt!ObReferenceObjectByHandle with a fixed "ObType" parameter corresponding to the expected object's type. 

There are only a small number of such issue, they are easy to fix, and they have zero application-compatibility risk.

Exploitation of this category of vulnerability is as follows:

Firstly, the attacker creates a handle to any object that is not an LPC type.

Secondly, the attacker calls NtUserSetInformationThread / UserThreadCsrApiPort from within CSRSS passing this handle as the parameter
NtUserSetInformationThread( hCurrentThread, UserThreadCsrApiPort, &handle, sizeof(handle) );

win32k!NtUserSetInformation begins by first verifying that the caller of the syscall is CSRSS. In this case, we are, so the call continues.

CSRSS runs with high user-mode permissions, but it is not a kernel-mode driver, and does not run with the full set of permissions that Ring-0 code has. For example, an Administrator on Windows 7 x64 cannot load code within Ring-0 that is not in a signed driver, but can inject code into CSRSS. For this reason, in order to maintain the "signed driver" requirement, the kernel should not trust parameters sent by CSRSS.

This is precisely the reason why during the syscall, win32k!NtUserSetInformation validates the length and pointer fields inside the user-mode parameters using ProbeForRead. Win32k!NtUserSetInformation captures the parameters to the syscall and sends them to win32k!xxxSetInformationThread.

win32k!xxxSetInformationThread can perform a variety of different functions depending on the "class" parameter to the syscall. In this case, we specified "UserThreadCsrApiPort", and so win32!xxxSetInformationThread calls win32k!SetCsrApiPortHandle.

win32k!SetCsrApiPortHandle now tries to resolve the parameter to a kernel object via the ObReferenceObjectByHandle function call. Crucially, the kernel lazily passes "NULL" as the "ObType" parameter, rather than "*LpcPortObjectType", which means that the kernel merely checks that the provided handle is valid, not that it is valid and pointing to an ALPC port.

This results in a kernel-mode type-confusion vulnerability in the case where usermode provides a valid handle to the syscall, but where the handle is not not a PLPCP_PORT_OBJECT. In this case, the kernel resolves the handle to the not-ALPC object, and this pointer is then implicitly cast to an ALPC kernel object leading to type-confusion in the kernel.

The pointer to this "confused object" is stored in the global variable win32k!CsrApiPort. When the kernel next tries to write data via this ALPC port (for example, via win32k!xxxActivateDebugger), kernel-mode memory corruption occurs.

The vulnerability exists on all supported versions of Windows, including Windows7, Windows 8.1 and Windows 10.

Thankfully this bug is extremely easy to fix with zero app-compat or performance considerations: since CsrApiPort can only ever safely be a handle to a LPC port, the the memory-corruption issue can be immediately resolved by making the ObReferenceObjectByHandle explicitly request an "LpcPortObjectType" via the ObType parameter. This will cause the function to abort any request to set the CsrApiPort to a non-LPC object and eliminating the potential for kernel-mode type confusion.

Comment 2 Deleted
Project Member Comment 3 by hawkes@google.com, Sep 9 2015
Labels: -Restrict-View-Commit
Status: WontFix
Looks like this won't get fixed in a bulletin, but may be addressed in a future version (based on a mail from MSRC on Sep 2). 

Note that this issue is a kernel driver signing bypass from Administrator privileges, i.e. it would typically be used as the final stage in an exploit chain that would already have given Administrator access, rather than as a standalone exploit.
Sign in to add a comment