In May, Microsoft has fixed a bug that allowed normal users to impersonate Domain Controllers. This bug allowed non-privileged users to obtain a logon certificate issued to a domain controller, because users can write to the Active Directory attribute dnsHostName
of a computer they have joined to the domain. If a machine can enroll for a certificate with naming attributes coming from AD (common 802.1x certificate config), and if this name was change to that of a domain controller, the client computer effectively ‘becomes a domain controller account’ when logging on with that certificate.
Microsoft did neither change write permissions to that attribute nor change anything related to the domain join process. They went for demanding a ‘stronger’ mapping between certificates and user / computer objects. As I’ve demonstrated on this blog again and again and again, a user principal name (or for a computer: a fully qualified DNS host name) in a certificate has been sufficient to allow for logging on with that certificate. This applies to – for example – smart card logon, 802.1x network logon using Microsoft NPS as a radius server, or logging on to web applications on IIS with AD cert mapping enabled.
But Applying the May 2022 security update to an AD-integrated (Enterprise) Windows Certification Authority (ADCS), the CA will add a new certificate extension to every certificate whose naming attributes are built from AD attributes. The new attribute has an object ID not (yet?) resolved into a friendly name, and its value contain the security identifier (SID) of the account requesting the certificate. (There are also other string mapping options, such as adding a Serial Number of a certificate manually, as a name mapping in AD, see the MS support article for details.)
A domain controller with May updates applied will check that SID attribute when a user or machine logs on with a mapped certificate. For now, also the old certificates – without SID – are still considered valid, but a warning is logged in the system event log. Next year in May, so-called Full Enforcement mode will be turned on, and logon certificates without SID will not be considered good enough. So, the big impact of this updates is: If you use certificates for logon of AD users or computers: Renew all logon certificates before November 2023 (E.g. by using the Re-enroll all certificate holders
function of a certificate template). (Edit: The deadline has been moved from May to November 2023, the MS KB article was updated in December 2022)
But there is an interesting ‘side effect’. Maybe it explains in part why Microsoft chose to fix the bug in this way (pure speculation) – instead of changing the domain join process or permissions on computer objects:
The flag EDITF_ATTRIBUTESUBJECTALTNAME2
has also been defused, sort of!
This flag allows to add custom Subject Alternatives Names (such as UPN or DNS name) to *any* certificate, even those configured for names coming from Active Directory. Unfortunately, the flag had been quite popular among web server administrators. Without this flag, you need to resort to a more involved post-processing of requests in the queue or maybe third-party tools. I proposed to use certutil -extensions recently, as a replacement for the flag.
With May 2022 updates applied *and* flag EDITF_ATTRIBUTESUBJECTALTNAME2
active, you can still maliciously add a UPN via the /certsrv web application to a template that ‘should actually be auto-enrolled’. The ‘evil’ UPN is replacing the UPN of the true requester. But the CA is now adding the new extension for the SID, which prevents the requester from impersonating an administrator!
Demo:
Create a key a key pair and certificate request using (e.g.) openssl, certmgr.msc, certreq. I used the Certificates MMC certmgr.msc to create a custom PKCS10 request file, added a silly non-standard Common Name but no SAN. The resulting request looks like this:
C:\TEST>certutil no-upn.req.txt PKCS10 Certificate Request: Version: 1 Subject: CN=No UPN in the CSR Name Hash(sha1): 2a474f6c9532bd563ae142717477f64de056abc4 Name Hash(md5): 371ef17a1b2f856cdb5814ac09c1bb8c Public Key Algorithm: Algorithm ObjectId: 1.2.840.113549.1.1.1 RSA (RSA_SIGN) Algorithm Parameters: 05 00 Public Key Length: 2048 bits Public Key: UnusedBits = 0 0000 30 82 01 0a 02 82 01 01 00 cf cb d9 07 24 d0 0f 0010 b9 f8 79 13 47 a1 3f 8c 4f 33 c0 28 be 8e c3 62 0020 53 cb 43 a2 fc 01 df d3 59 0e a7 72 1d ad 86 c3 0030 c8 9f 5e cc 31 1b ad a2 56 d2 f5 5e c2 67 80 96 0040 35 79 54 a1 3d db a8 ce 22 5b 2a 6b 2f 80 e2 b5 0050 20 cd aa d4 a8 0d 38 7a 98 8e 9c d0 cc 9b 9e 90 0060 c5 50 4c cf 49 e3 77 84 56 8b e7 fb 8b 6f 89 2a 0070 ba bc f8 ec e7 ce b6 bd d9 f5 04 ab 84 2d 00 ea 0080 c5 05 7a e6 36 0c 5c 3f c5 c6 c3 2c a2 7d a9 f3 0090 36 3e d6 91 01 f5 ab 37 08 24 c0 6b 19 1b ef 24 00a0 58 6e a1 96 ce f6 98 52 78 2d 0f a8 65 f9 f9 f0 00b0 99 7a fc 92 ee 1d 13 ac 06 d7 18 88 c2 2c 85 da 00c0 31 c9 d4 80 cf 88 a4 aa b1 9f 04 6f 00 ed 62 ff 00d0 d4 9d a8 d7 cb 59 ab ea fb a3 91 51 42 22 10 97 00e0 b8 23 1f b8 28 e5 f5 bb 9e e4 66 2c a4 e6 53 be 00f0 8e 5f ae 94 29 68 8a d1 c0 48 6e 55 fa 47 6d dc 0100 ce 3c c9 42 66 7b 89 62 35 02 03 01 00 01 Request Attributes: 4 4 attributes: Attribute[0]: 1.3.6.1.4.1.311.13.2.3 (OS Version) Value[0][0], Length = e 10.0.20348.2 Attribute[1]: 1.2.840.113549.1.9.14 (Certificate Extensions) Value[1][0], Length = 21 Certificate Extensions: 1 2.5.29.14: Flags = 0, Length = 16 Subject Key Identifier f76611403821353e1d37a3c0961715c91bfde569 Attribute[2]: 1.3.6.1.4.1.311.21.20 (Client Information) Value[2][0], Length = 2c Client Id: = 5 ClientIdDefaultRequest -- 5 User: PANIC\webadmin Machine: virus.pan.ic Process: MMC.EXE Attribute[3]: 1.3.6.1.4.1.311.13.2.2 (Enrollment CSP) Value[3][0], Length = 58 CSP Provider Info KeySpec = 0 Provider = Microsoft Software Key Storage Provider Signature: UnusedBits=0 Signature Algorithm: Algorithm ObjectId: 1.2.840.113549.1.1.11 sha256RSA Algorithm Parameters: 05 00 Signature: UnusedBits=0 0000 8a 3a 77 56 27 fe 26 e2 06 44 df 2f c1 f4 8c 75 0010 2d 89 cd 9d fd 1c 1c 8d d3 23 48 66 27 16 1b 72 0020 c4 af c8 e3 00 5f dc c2 7c 7a b2 d6 21 1e 4f 27 0030 ce 55 c6 86 f3 6f c9 94 97 f3 7e 2e 91 0c 7b 88 0040 61 24 b4 ca c9 12 01 e1 76 54 c9 55 ae de 37 6d 0050 c9 70 40 b1 3e ea 1f 3b dc 76 54 d9 3f 65 da 2f 0060 69 21 77 80 b5 e6 ee 0c 10 c6 84 c6 05 87 bc 07 0070 28 fd ee a2 58 c9 ac 6a 3b e9 b5 37 2b b1 56 99 0080 ec da 3f 1d e3 57 4e d4 c4 53 6c cd a4 38 55 bf 0090 3d 20 37 20 f7 b1 2d c7 6a 0d 73 61 a2 63 99 76 00a0 63 7e 3d 3a 7c ca ce 77 9a db 02 a1 96 2a 3d 61 00b0 e0 6a b9 d5 58 1a a5 a1 93 c0 f5 04 70 61 5f 1b 00c0 5d 1e 51 27 03 53 64 0f a4 d2 53 3a 28 0f 02 84 00d0 3d c5 4d 8f 84 b9 85 d9 60 79 24 89 12 67 e8 07 00e0 aa a2 5a 94 64 a1 99 e4 dc 88 d5 50 80 6f b8 da 00f0 a6 92 99 a7 e2 db 20 30 0f 4c bf 2d dd c1 81 42 Signature matches Public Key Key Id Hash(rfc-sha1): f76611403821353e1d37a3c0961715c91bfde569 Key Id Hash(sha1): 38783664c43762c48af5e3eb523ae28f10d31066 Key Id Hash(bcrypt-sha1): 5cbf84779f3ea073acdbfbcdbfca6a6ed7d2d1c4 Key Id Hash(bcrypt-sha256): a46d156a0a04f87292c5d34de3c723b7e704149c4f291285907cbf16db29183c CertUtil: -dump command completed successfully.
Windows also adds a request attribute that denotes the requesting user (PANIC\webadmin) – but this is not what is important for the checks that follow. This webadmin user does not have any special AD permissions.
The user submits this certificate signing request (CSR) as a request for a User template – a standard template that makes the CA pull attributes from AD. I am picking this old (v1) template, as it belongs to the set of templates automatically published if you install a next-next-finish CA. A typical certificate intended to be auto-enrolled would be a v2 template created by copying (e.g.) this template. Even though the ‘intended’ way of enrollment is auto-enrollment or ‘next-next-finish’ MMC enrollment (without changing any attributes), nothing prevents a user from creating key pair and request (CSR) offline – and submitting the CSR file manually.
The ‘evil webadmin’ adds a UPN using enrollment app /certsrv. The UPN is added to the attributes form field as SAN:upn=administrator@[domain]
.
When issuing the certificate the CA …
1) … overwrites the silly CN with the one of the requester (Web Admin):
2) … adds the malicious UPN instead of the true one (webadmin@pan.ic):
3) … adds the new SID attribute
Checking the SID – yes, that’s webadmin’s!
C:\TEST>whoami /all USER INFORMATION ---------------- User Name SID ============== ============================================ panic\webadmin S-1-5-21-1468012755-800561317-457473099-1104 ...
Now the user tries to logon with this certificate – and logon fails because the SID does not match the UPN. For a quick logon test I use the ASP application I showed in my post about IIS certificate mapping. I get the certificate prompt, pick this certificate – and get HTTP Error 401.2 - Unauthorized
.
This usually means that I have an error in the mapping config :-) But this time the DC will tell us exactly what happened. Event 41 is recorded at the DC, in the system event log:
The Key Distribution Center (KDC) encountered a user certificate that was valid but contained a different SID than the user to which it mapped. As a result, the request involving the certificate failed. See https://go.microsoft.com/fwlink/?linkid=2189925 to learn more.
User: Administrator User SID: S-1-5-21-1468012755-800561317-457473099-500 Certificate Subject: @@@CN=Web Admin, OU=Let's Hack, DC=pan, DC=ic Certificate Issuer: Panic CA Certificate Serial Number: 4B00000023F6445390D0D6D4EE000000000023 Certificate Thumbprint: 47F6F9BAB4AD3F0EB93F35F4D95B964FD39B20B0 Certificate SID: S-1-5-21-1468012755-800561317-457473099-1104
So that’s what I mean by having defused the flag!
Note that you can still ‘hack a UPN’ if you have enroll access to a template not configured for names coming from Active Directory. The CA does not embed a SID attribute into such certificates, and they look like any ‘old’ logon certificate issued before May 2022. logon is still possible now in compatibility mode – for now! But this will change in one year latest!
Recorded event 39 in this case:
The Key Distribution Center (KDC) encountered a user certificate that was valid but could not be mapped to a user in a secure way (such as via explicit mapping, key trust mapping, or a SID). Such certificates should either be replaced or mapped directly to the user via explicit mapping.
So, it’s recommended turn off the SAN flag even though the update has been applied.
I would handle the May update like this:
- Check that all CAs have been patched by checking the SID attribute is added to logon certificates with names from AD now.
- Watch out for the Kerberos errors in the system event log of DCs. If you see warnings, then certificates are used to logon, and certificates with validity periods greater that a year will not be accepted in the future.
- Re-enroll all certificate holders to replace all logon certificates.
- If Kerberos warnings have ceased, turn on Full Enforcement before Microsoft does.