Windows: Object Manager Pathological Lookup EoP
Platform: Windows 10, not tested Windows 8.1 or 7.
Class: Elevation of Privilege
Summary:
When performing an object name lookup it’s possible exercise the worst case lookup time for the object leading to a single lookup taking multiple minutes. This can prevent a process being terminated on logout which can be used to get access to other user sessions, especially on a terminal server leading to EoP.
Description:
When the kernel is looking up an object name (say through calling NtOpenEvent) the thread doing the call cannot be terminated (well it can but it doesn’t honour the request until it returns) nor will the process be correctly rundown. It’s possible to craft a lookup request which is pathological leading to the absolute worse case performance, this causes the thread/process effectively to be unkillable even across log outs. For example by making an object manager path with around 16000 path components (we don’t need this many directories as we can use shadow directories to reduce it to two) combined with the maximum 64 symbolic link reparse events and making the directory object hash table lookup worst case through collisions you can make a single lookup, even on a 2.8GHz Xeon take approximately 19 minutes to complete but only around 11 seconds to set up.
We can abuse this to do tricks similar to https://googleprojectzero.blogspot.co.uk/2016/01/raising-dead.html where you get an effective UaF of a token’s session ID by causing the long lookup, log out then back in again, then reopening the original process and extracting its token. It will also maintain handles across logout (this problem wouldn’t be so bad if the handles were closed in the process) so you can use this to store access to session directories and the like which can be rewritten and access gained to another user’s objects.
Note that I’ve heard rumours that you might change some behaviour in Windows which will block cross session exploitation in this fashion. If so this issue might be mitigated.
Proof of Concept:
I’ve provided a PoC as a C# source code file. You need to compile it first.
1) Compile the C# source code file.
2) Execute poc, after some seconds the session should automatically log out. Log back in as the user.
3) Use a tool such as process explorer to find the poc executable still running in the original session. It will also still have its handles accessible.
Expected Result:
The process performing the lookup is terminated.
Observed Result:
The process is still executing the lookup and the user can inspect the process and extract handles and tokens.
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.