|
|
Windows: VHDMP Incorrect Impersonation Handling EoP | ||
| Project Member Reported by forshaw@google.com, Aug 30 2016 | Back to list | ||
Windows: VHDMP Incorrect Impersonation Handling EoP Platform: Windows 10 and 8.1 versions. Class: Elevation of Privilege Summary: The VHDMP driver doesn’t correctly handle impersonation levels leading to the possibility of impersonating a privileged token when performing certain actions such as creating/modifying a VHD leading to EoP. Description: Note: I’ve not provided a PoC for this one, I felt it was worth providing details of the issue while you may still be working on the driver so that you didn’t need to do multiple security patches. However I’ve proven enough to myself that it’s an issue and will provide more detail than usual in this report to hopefully compensate. The reason for this is it’s a race condition which might be less than reproducible in different environments and many of the best ways to see the effects of the bug would be once other bugs such as 34806 are fixed. When the VHDMP device is opened the function VhdmpiCreateHandler is dispatched in response to the IRP_MJ_CREATE IRP. If the EA buffer is valid this ends up calling VhdmpiInitializeHandleContext to build a context structure for later use. One of the things this does is capture a VHD_SECURITY_CONTEXT using VhdmpiInitializeSecurityContextFromScope which ultimately just calls SeCaptureSubjectContext which captures the Client and Primary token’s of the current thread context. This in itself is a bad idea as in theory at least IRPs can be dispatched on different threads, while unlikely for a create IRP I’d assume it’s not impossible. If an attacker could find an easy way of doing this dispatch on another thread (ideally say a system thread) the rest of the call would be executed as if it was from system. But that’s not the real problem, which is how the driver uses that security context to impersonate the user at different times. For this it calls PsImpersonateClient (for example in VhdmpiBeginImpersonation, or VhdmpiCreateThread) passing an explicit impersonation level of SecurityDelegation. This is bad as a mismatch of the impersonation level to the impersonation level of the actual token object leads in certain circumstances to EoP. When a token is set using PsImpersonateClient it calls SeTokenCanImpersonate for the token passed in. If the current process token has SeImpersonatePrivilege enabled, or the token meets some set of criteria (such as being the same user, same authentication session etc.) then this check will pass. The rest of PsImpersonationClient will continue to set the token verbatim to the thread, setting the impersonation level as SecurityDelegation even if the token isn’t an impersonation token or the impersonation level of the token is less than SecurityDelegation. So how could this be exploited? Basically a normal user can get access to identification tokens fairly easily for privileged users. Whether it being exploiting DCOM to reflect an identification level token for SYSTEM, NTLM negotiation or Service4User abuse. Also if running as a split token administrator with UAC the administrator linked token is exposed via a system call. If the user can set the identification impersonation token on the thread calling VhdmpiCreateHandler from another thread so that the token gets set after the IO manager has captured the access state (necessary to bypass the initial SeAccessCheck which uses the IRP context, not the caller) but before the call to VhdmpiInitializeSecurityContextFromScope the token will be fixed into the security context for later use. Now when a file is opened the context is impersonated, if SeTokenCanImpersonate succeeds then the level of the token is elevated. As calls such as SeAccessCheck only verify the thread’s set impersonation level, not the level in the token object this leads to be able to open the file as the impersonated identity. For a split token admin on Win8.1 you can impersonate the admin token as long as you drop its integrity level (however Win10 doesn’t allow that anymore). Winning the race between the IO manager and the call to VhdmpiInitializeSecurityContextFromScope might not be as difficult as it sounds, for example you might be able to slow the initial IO access sufficiently that you’ve got a lot of time to set the impersonation token. However outside of the UAC case on Win8 you’d also need to repeatedly clear the thread impersonation token to ensure some initialization doesn’t fail. However once the code transitions to the system process any impersonation token will succeed as the System process has impersonation privilege. This means things like opening physical disks (even if the bug in that was fixed by enforcing an access check) would still be bypassed. On the fixing side I’d say that at the least the security context captured in VhdmpiInitializeSecurityContextFromScope should come from the IRP’s AccessState. This way the identity used to open the device object matches exactly with the one you do an SeAccessCheck for initially. This would pretty much fix the issue as is, but I’d also do a check on the impersonation level of the access context if the effective token is an impersonation token. There’s also code such as VhdmpiCopySecurityContext which impersonates the context, then recaptures using SeCaptureSubjectContext where there’s a risk of a race with the user setting a new thread access token. Also worth nothing I don’t know if this would allow a semi-privileged user to elevate a token access to Delegate level. For example if a local admin on a machine was able to convince a domain admin to connect to their machine at impersonation level, then forward that access via VHDMP to another machine. I don’t believe so due to how I understand delegation to work (as in the local machine can only delegate authentication to another machine if it already knows things like the password of the user/some sort of kerberos ticket). Certainly you’d assume that the trust of delegation has little to with the local machine as an admin could compromise it, which if the case I wonder whether you need to be setting SecurityDelegation level anyway? Proof of Concept: As said I’ve not provided a PoC, however if you really want me to I can try and come up with something. 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.
Project Member
Comment 1
by
forshaw@google.com,
Aug 31 2016
,
Nov 14 2016
,
Nov 15 2016
|
|||
| ► Sign in to add a comment | |||