Closed GoogleCodeExporter closed 9 years ago
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.
Original comment by mattt...@google.com
on 2 Sep 2015 at 5:56
Reporting timeline:
June 5th 2015: Me -> MSRC Initial Report
June 5th 2015: MSRC -> Me Automatically assigned MSRC case number 30381
June 9th 2015: MSRC -> Me Microsoft requests additional clarification
June 9th 2015: Me -> MSRC Clarification above given.
Aug 27th 2015: Me -> MSRC 7 days before deadline; querying if Microsoft will
need a deadline extension after 80 days with no-response or feedback from MSRC.
Sep 2nd 2015: Me -> MSRC 2 days before deadline; re-querying if Microsoft
will need a deadline extension after no response or feedback from MSRC.
Original comment by mattt...@google.com
on 2 Sep 2015 at 6:02
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.
Original comment by haw...@google.com
on 9 Sep 2015 at 12:47
Original issue reported on code.google.com by
mattt...@google.com
on 9 Jun 2015 at 1:43