The HTTP server implemented in
HTTP.SYS handles authentication in a system thread which bypasses PAC verification leading to EoP.
There was a recent issue (CVE-2022-35756) that was fixed in Kerberos relating to the handling of PAC verification of User 2 User Kerberos tickets. This allows a user to modify a ticket's PAC to give themselves elevated privileges on the local machine. While this shored up the scenarios where PAC verification is disabled there's still the default which allows the system user (or any caller with
SeTcbPrivilege) to bypass PAC verification.
Therefore one approach to restore the modified ticket attack would be to get a system process to call
AcceptSecurityContext with an AP-REQ the user has modified. There are two issues with this approach however:
- The credential handle would likely be for the system logon session and so wouldn't accept either a ticket encrypted to the user's password or U2U.
- The token wouldn't be accessible and the limits of the attack would depend on what the system process does with the authentication.
Through inspection the HTTP kernel driver solves all the necessary problems. First it calls
AcceptSecurityContext in a background system thread in the kernel which ensures it runs with
SeTcbPrivilege. Second, when configuring kernel authentication there's a flag,
HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL, which makes the driver call
AcquireCredentialsHandle while impersonating the user setting up the HTTP server. This results in the user's keys being used for the security context. And finally, the HTTP server will provide a handle to the access token back to the user so that it can be impersonated.
Therefore to perform the attack you can do the following:
- Setup a HTTP server with kernel authentication enabled and the
HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIALflag set. This can be done as a non-admin user by choosing a localhost listen prefix such as http://localhost:12345/abc.
- Build/modify a ticket for the user's key to add additional groups such as Domain Admins.
- Send the AP-REQ to the local HTTP server using the Authorization header.
- Extract the access token from the
HTTP_REQUEST_AUTH_INFOstructure returned with the request context and use that to elevate privileges.
Proof of Concept:
I’ve provided a PoC as a C# project. You need to get and build a copy of my
NtApiDotNet library to build the project (https://github.com/googleprojectzero/sandbox-attacksurface-analysis-tools). Note that there's a bug in the loopback library of Windows 10 which means the POC will get an access token with a session ID of 0 which would mean the token can't be impersonated. This doesn't happen if U2U is used instead, therefore to verify that this is a working exploit it's best to run on Windows 11.
- Compile the C# project, put a copy of
NtApiDotNet.dllin the project's directory before building. Make sure you compile it for 64-bit otherwise the server authentication doesn't work correctly.
- Run the POC on a domain joined machine passing the password for the current domain user. This isn't completely necessary as you could use U2U but this for demo purposes only.
- The POC should print out the groups for the token.
The authentication fails.
The authentication succeeds and the token has the Domain Administrator's group.