Microsoft windows double dereference in ntenumeratekey elevation of privilege Vulnerability / Exploit
/
/
/
Exploits / Vulnerability Discovered : 2018-09-19 |
Type : dos |
Platform : windows
This exploit / vulnerability Microsoft windows double dereference in ntenumeratekey elevation of privilege is for educational purposes only and if it is used you will do on your own risk!
[+] Code ...
Windows: Double Dereference in NtEnumerateKey Elevation of Privilege
Platform: Windows 10 1803 (not vulnerable in earlier versions)
Class: Elevation of Privilege
Summary: A number of registry system calls do not correctly handle pre-defined keys resulting in a double dereference which can lead to EoP.
Description:
The registry contains a couple of predefined keys, to generate performance information. These actually exist in the the machine hive under \Registry\Machine\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib. When these keys are opened the kernel returns a status code of STATUS_PREDEFINED_KEY, but it also returns a handle to the key.
The kernel doesn’t allow these keys to be used for many operations such as enumeration of subkeys and values, so these system calls check before the key is used and returns STATUS_INVALID_HANDLE. The code for this in NtEnumerateKey looks like the following:
status = ObReferenceObjectByHandle(Handle, KEY_ENUMERATE, CmKeyObjectType, &Object);
if ( status >= 0 && Object->Type != 'ky02' ) {
status = STATUS_INVALID_HANDLE;
ObfDereferenceObject(Object); <-- Dereference object,
}
if (status < 0) {
goto EXIT_LABEL;
}
This code in itself is fine, but in 1803 at the exit label we find the following additional code:
if (Object)
ObfDereferenceObject(Object);
This results in the object being dereferenced twice. Due the way the object reference counting works this will not be noticed until the key handle is closed, which results in a REFERENCE_BY_POINTER bugcheck being generated. This might only be a local DoS if the issue was caught earlier, but because the caller can do other things with the corrupted object we can potentially turn this into a UaF and from there elevate privileges. For example the provided PoC passes the handle to NtDuplicateObject which results in the kernel modifying a free pool allocation.
I’d recommend ensuring you check all similar functions such as NtEnumerateValueKey as there seems to be a common issue, perhaps it’s a macro or template which is generating the bad code.
The following is an example dump from a crash, at the end the !pool command is used on the object address to demonstrate the memory allocation was freed before being modified.
Use !analyze -v to get detailed debugging information.
REFERENCE_BY_POINTER (18)
Arguments:
Arg1: 0000000000000000, Object type of the object whose reference count is being lowered
Arg2: ffff8e0db3a0f7a0, Object whose reference count is being lowered
Arg3: 0000000000000002, Reserved
Arg4: ffffffffffffffff, Reserved
The reference count of an object is illegal for the current state of the object.
Each time a driver uses a pointer to an object the driver calls a kernel routine
to increment the reference count of the object. When the driver is done with the
pointer the driver calls another kernel routine to decrement the reference count.
Drivers must match calls to the increment and decrement routines. This bugcheck
can occur because an object's reference count goes to zero while there are still
open handles to the object, in which case the fourth parameter indicates the number
of opened handles. It may also occur when the objects reference count drops below zero
whether or not there are open handles to the object, and in that case the fourth parameter
contains the actual value of the pointer references count.
I’ve provided a PoC as a C# project. This only demonstrates the issue and proves that it would be possible to force this issue into a UaF even with the mitigations on reference counting.
1) Compile the C# project. It will need to grab the NtApiDotNet from NuGet to work.
2) Run the PoC on an machine with Windows 10 1803, I’ve only tested x64.
3) The OS should crash, inspect it in a kernel debugger or from the crash dump.
Expected Result:
The OS ignores the pre-defined key as expected.
Observed Result:
The object’s reference count is corrupted.
Proof of Concept:
https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/45436.zip
Microsoft windows double dereference in ntenumeratekey elevation of privilege