On Windows, the buffer for redirected logon context does not protect against spoofing resulting in arbitrary code execution in the LSA leading to local elevation of privilege.
advisory-info.txt
Windows: Kerberos Redirected Logon Buffer EoP
Platform: Windows Server 2022
Class: Elevation of Privilege
Security Boundary: User
Summary:
The buffer for redirected logon context doesn't protect against spoofing resulting in arbitrary code execution in the LSA leading to local EoP.
Note: This is distinct from the previous issue I reported (case 70653). That was manipulating the redirected logon credentials buffer, this instead manipulated the buffer used to track the context between CredSSP and the final authentication. The previous issue might be exploitable remotely whereas this is local only as you need to be able to encrypt the buffers.
Description: When a remote credential guard connection is made via CredSSP the TSSSP needs to store the credentials for later use by the logon process. This is done by encrypting the credentials using the CredProtect API into a string which can later be passed as the password to LsaLogonUser to complete the logon. The encrypted credentials contain the pointer to the TSSSP context and function pointers to callback functions to get the redirected credentials. The structure also contains a GUID, but that's static across versions of Windows.
If I had to guess, the developers assumed that because CredProtect encrypts using a per-logon-session key that a normal user couldn't encrypt their own buffer which would be accepted by the Kerberos package, as both TSSSP and Kerberos run in the SYSTEM logon session. Unfortunately that's not true, CredProtectEx API (and the underlying RtlEncryptMemory) API added a flag to encrypt the buffer for use by the SYSTEM logon session, the user can't decrypt the buffer but that doesn't matter. You do need to do a few tweaks to the buffer to get it accepted but that requires no privileges.
At a basic level this can be used to call an arbitrary function in LSASS by encrypting your own buffer and passing it to LsaLogonUser (or it's higher level equivalents) as the password. This doesn't require that Terminal Services is enabled on the machine, but it does need Remote Guard enabled otherwise the Kerberos package will ignore the buffer.
LSASS does have CFG/XFG enabled but you could call something like LoadLibrary or WinExec as you control the first parameter's pointer value. Getting memory addresses might not be that difficult as it seems LSASS leaks pointers all over the place, for example the TsPkgContext field in the MS-RDPEAR isolated credential request is just a heap address of the TS_CONTEXT pointer which contains the logon buffer, you could therefore probably use CredSSP itself to setup a suitable buffer and leak its address for any in-process data you need.
Fixing wise, the design of this is terrible and shouldn't have passed a basic security design review, but it is what it is. At least you probably should use a unique random value for the magic GUID so that it can't be trivially spoofed. However be careful, the encryption scheme just seems to be CBC with no per-encryption salt or cryptographic authentication which means that if you leave the GUID at the front it might be possible to copy the encrypted GUID from a real buffer (using CredSSP to generate it) then the rest can be corrupted in such a way to allow for exploitation.
Proof of Concept:
I've provided a PoC as a C++. This will just try and get LoadLibrary called with an arbitrary pointer. It's expected to crash LSASS, however, calling LoadLibrary is just to demonstrate it's possible. I've not put much effort into developing an end to end exploit as it isn't necessary.
1) Compile the C++ project.
2) Enable remote credential guard on the system using the registry from an admin prompt:
reg add HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa /v DisableRestrictedAdmin /d 0 /t REG_DWORD
3) Run the POC as a non-admin user.
Expected Result:
The logon should fail.
Observed Result:
The LSASS process crashes trying to dereference an invalid pointer.
This bug is subject to a 90-day disclosure deadline. If a fix for this
issue is made available to users before the end of the 90-day deadline,
this bug report will become public 30 days after the fix was made
available. Otherwise, this bug report will become public at the deadline.
The scheduled deadline is 2022-06-06.
Related CVE Numbers: CVE-2022-24545,CVE-2022-30165.
Found by: forshaw@google.com
Download: GS20220706153551.tgz (6 KB)
Source