Nov 9 2022 | will schroeder

Certificates and Pwnage and Patches, Oh My!

Share

This post was written by Will Schroeder and Lee Christensen.

A lot has happened since we released the “Certified Pre-Ownedblog post and whitepaper in June of last year. While the paper details a LOT of tradecraft ranging from credential theft to domain persistence, the part that caught most people’s attention were the eight domain escalation primitives we detailed as ESC1-ESC8. A lot of organizations (and a lot of pentesters 😉 definitely realized how pervasive misconfigurations in Active Directory Certificate Service are and how easy it is now to enumerate and abuse these issues.

Nothing to see here, please move along

In summer of this year, Oliver Lyak discovered the “Certified” vulnerability (CVE-2022–26923) that allowed for Active Directory domain privilege escalation. In response, Microsoft released the KB5014754 patch which non-trivially alters how certificates are mapped to identities when used for authentication in Active Directory. Oliver’s other great post “Certipy 4.0: ESC9 & ESC10, BloodHound GUI, New Authentication and Request Methods — and more!” has some excellent detail on the patch, as well as two new escalations he discovered titled ESC9 and ESC10. Atanur Serkan Elmasoğlu also alerted us to some additional caveats for some of the escalations that we’ll cover, and Pablo Martínez and Kurosh Dabbagh detailed some additional ways to exploit ESC7 in their “AD CS: from ManageCA to RCE” post that we’ll briefly touch on as well. Oh, a ton of new tools from a number of researchers came out too!

With all of these changes, we wanted to revisit some of the offensive AD CS attacks, detail how the patch has affected some of the existing escalations, and clarify a few details that we were previously unclear on.

ESC9 and ESC10 Background

The KB5014754 patch introduced the concept of “strong” and “weak” user identity mappings, along with a new certificate extension that we’ll talk about shortly. Oliver does a much better job than we could detailing all of this, but as a summary, certificates can be mapped to an Active Directory principal either implicitly or explicitly. Implicit mappings concern using the subject alternative name (SAN) to map the certificate to a user identity. If you read the whitepaper or previous blog post, you’ll recall that SAN abuse was the crux of several of the escalation attacks.

Explicit mappings are a bit different and use the altSecurityIdentities property of a principal to map a certificate to an identity. Three of these (X509IssuerSerialNumber, X509SKI, and X509SHA1PublicKey) are now considered “strong” mappings, which means that, “…they are based on identifiers that you cannot reuse.” All other altSecurityIdentities and previous implicit mappings are now considered “weak”.

In order to facilitate strong identity mappings in all situations, for most certificate templates the CA will now insert a szOID_NTDS_CA_SECURITY_EXT (OID 1.3.6.1.4.1.311.25.2) extension value into the resulting certificate (more information on this processing logic can be found here). This extension contains the SID of the requesting user and is meant to be used if there are no existing strong mappings in the certificate:

The new szOID_NTDS_CA_SECURITY_EXT extension in an issued certificate.

The idea with this extension is a domain controller can compare the SID of the authenticating user (or the SID of the user account specified in the SAN) against the SID contained in szOID_NTDS_CA_SECURITY_EXT. This is used as a type of bootstrap “strong” identity mapping that we’ll talk about shortly, but how exactly this extension is used by the DC for Kerberos or SChannel authentication depends upon the value(s) of two registry keys.

The StrongCertificateBindingEnforcement value located at HKLMSYSTEMCurrentControlSetServicesKdc on domain controllers affects the behavior of certificate user mapping during Kerberos authentication. The key can currently be set to 0 (disabled), 1 (compatibility mode) or 2 (full enforcement mode). Since the patch, if this key is not present (the default behavior) the value is interpreted as 1 (compatibility mode). In this mode, “strong” altSecurityIdentities mappings or the presence of szOID_NTDS_CA_SECURITY_EXT are checked for and validated if present, but if a strong mapping is not present authentication can still proceed. According to the KB, “This registry key will be unsupported after installing updates for Windows released on May 9, 2023.” after which authentication will fail unless a strong mapping or the szOID_NTDS_CA_SECURITY_EXT is in the certificate being used for authentication.

Schannel certificate user mappings are a bit different. Schannel can use five different methods in descending order of preference for mapping a certificate to an identity during auth (see the “Schannel Registry Key” section here for more details). These mapping methods are controlled in the HKEY_LOCAL_MACHINESystemCurrentControlSetControlSecurityProvidersSchannel : CertificateMappingMethods subkey value and are as follows:

  1. 0x0010 — Kerberos service-for-user (S4U) explicit certificate mapping
  2. 0x0008 — Kerberos service-for-user (S4U) certificate mapping
  3. 0x0004 — User principal name (UPN/SAN) mapping
  4. 0x0002 — One-to-one mapping (also known as subject/issuer mapping)
  5. 0x0001 — Many-to-one mapping (also known as issuer certificate mapping)

Before the KB5014754 patch, the default value was 0x1F (all methods), meaning that if the Kerberos methods failed the “weaker” methods could still be used. With the patch, the default value is now 0x18, so only the Kerberos S4U mapping techniques occur. As such, Schannel’s default behavior during authentication now maps a certificate to a user account via Kerberos S4U which underneath leverages the szOID_NTDS_CA_SECURITY_EXT extension.

However, if the 0x4 UPN mapping flag is present, even if the Kerberos flags are also present, SAN mapping is possible. This will come into play in a serious way later in this post (spoiler: it results in pwnage).

The Death of our Beloved ESC6?

With the patch, ESC6 (the presence of the EDITF_ATTRIBUTESUBJECTALTNAME2 policy flag) has been broken. This is because while you can request an alternate subject name in the request for any template when this flag is set, the CA will automatically set the SID of the original requesting user in the szOID_NTDS_CA_SECURITY_EXT extension. When you attempt to use the resulting cert for authentication, you get a KDC_ERR_CERTIFICATE_MISMATCH error. If the StrongCertificateBindingEnforcement registry key is set to 0, then no strong certificate mapping checks are done and behavior is just as it was before, and ESC6 will work.

To be more precise, the behavior varies based on the exact settings of both the StrongCertificateBindingEnforcement and CertificateMappingMethods keys.

Is ESC6 exploitable?

The scenarios for exploitation of ESC6.

Re-arming ESC7

This patch also broke ESC7 (overly permissive ManageCA permissions), since the crux of that attack relied upon flipping the EDITF_ATTRIBUTESUBJECTALTNAME2 on a remote CA, allowing for execution of ESC6. However there is a workaround that will work until the May 9, 2023 flip over to full enforcement. With ManageCA permissions, using the same technique(s) as described in page 76 of the whitepaper to set the OID (1.3.6.1.4.1.311.25.2) of the szOID_NTDS_CA_SECURITY_EXT extension to the disabled extension list:

$ConfigReader.SetConfigEntry(“1.3.6.1.4.1.311.25.2”, “DisableExtensionList”, “PolicyModulesCertificateAuthority_MicrosoftDefault.Policy”)

This prevents the szOID_NTDS_CA_SECURITY_EXT SID from being added by the CA to any request, and can now again be chained with EDITF_ATTRIBUTESUBJECTALTNAME2 for abuse. However, since this is abusing the compatibility mode of the StrongCertificateBindingEnforcement that allows for authentication to proceed when NO strong mappings are present, it fails in the context of full enforcement mode and will stop working on May 9, 2023.

We originally tried to manually add the extension OID (as well as the SAN OID) to the EnableRequestExtensionList in an attempt to sneak by manually supplied szOID_NTDS_CA_SECURITY_EXT values for any request, but this didn’t work, which makes sense for how the system is designed.

There are other ways to abuse ManageCA rights for domain escalation that we missed during our original research. Two of them were discussed by Pablo Martínez and Kurosh Dabbagh in their “AD CS: from ManageCA to RCE” post from February of this year. These two methods involve a coerced authentication primitive via abusing CRL distribution points (CDPs), and using CDPs to deploy SYSTEM-running webshells to CA servers respectively. These approaches have their own set of preconditions, so definitely check their work out!

Modified ESC1 Abuse

The KB5014754 patch also changed the abuse of ESC1.

From an updated [MS-WCCE]: Windows Client Certificate Enrollment Protocol section 2.2.2.7.7.4, “The CA MUST consider this extension [szOID_NTDS_CA_SECURITY_EXT] from request attributes only when the CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT flag is set on the corresponding certificate template object.” That is, when requesting an “enrollee supplied subject” certificate the szOID_NTDS_CA_SECURITY_EXT is not set in the certificate by the CA by default. Rather, the requesting user is allowed to supply the szOID_NTDS_CA_SECURITY_EXT extension in the request.

In fact, once May 9, 2023 hits, all requesters will have to supply the szOID_NTDS_CA_SECURITY_EXT extension value as without that value (or a strong mapping) present in the resulting certificate, authentication against the DC will not work.

We have recently updated this in Certify with the /sidextension:<S-1-…> flag to support this. It uses code from Carl Sörqvist to build the extension properly and include it with a certificate request for a template with the CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT flag set.

Clarifying ESC3 and expanding ESC2

There were a few questions that we and others had over the last year concerning ESC3, the abuse of enrollment agent certificates.

Does the certificate enrollment agent certificate template still have to exist for issued enrollment agent certificates to enroll-on-behalf-of other users against other templates?

No, once a certificate with a Certificate Request Agent OID is issued by the CA, as long as that certificate is valid it can be used for enrollment agent purposes. Whether a certificate is considered valid depends upon the signature for the cert and its validity period- it has nothing to do with the presence or settings of the associated template after the certificate was issued.

Which principals need which rights on which template for enrollment agent abuse?

The attacker/admin principal needs enrollment rights on both the enrollment agent template, and the target template they’re enrolling in on-behalf-of another principal. The principal the attacker is enrolling on behalf of does not need enrollment rights on either template.

Are there some weird enrollment EKU scenarios?

Yes. Atanur pointed out to us that If the AnyPurpose EKU is present at the same time as the Certificate Request Agent in the EKUs, you can’t enroll-on-behalf-of other users in schema 2+ templates (more on schema version in the following section). Certificate Request Agent + any other EKU does appear to work in this situation.

Can you request a template as another user if authorized signatures is set to 0?

This one is a bit more complicated, and resulted in a few interesting details.

Certificate templates have schema versions. For our situation, we care if a template is version 1 or if it is version 2+. Version 2+ templates introduced the concept of issuance requirements, specifically authorized signatures for our case. If a certificate is version 2+ and the authorized signatures are set to 0, you will not be able to enroll on-behalf-of another user for the template.

Version 1 templates do not have a concept of issuance requirements that version 2+ introduced. This means that version 1 templates have no authorized signatures. Atanur first tipped us off to to an interesting result of this: some existing certificates besides ones with the Certificate Request Agent OID, specifically templates with the AnyPurpose and <null> (SubCA) EKU scenarios can be used to enroll-on-behalf-of other users against schema version 1 templates! However, this will not work for version 2+ templates, resulting in a “The X Certificate Template requires 1 signatures, but only 0 were accepted.” error as seen here:

So this expands the usefulness of ESC2, which originally did not have a clear weaponization. When you exploit ESC2, you obtain a certificate which does not have an EKU or has the Any Purpose EKU. Using this certificate, you can (as an enrollment agent) enroll as another user from any v1 schema template.

Thanks again to Atanur for bringing this particular caveat to our attention! Also thanks to Oliver Lyak who also described this behavior in his blog post.

Atanur also relayed to us that if a schema version 1 template has AnyPurpose/no EKU, and the template contains the CT_FLAG_SUBJECT_ALT_REQUIRE_UPN flag, the template can work as an enrollment agent certificate and as the target template for user authentication, meaning this one misconfigured template can be sufficient for escalation. And finally, he mentioned that AnyPurpose doesn’t appear to work for code signing.

CES and NDES

Most tooling has focused on using the AD CS’s DCOM/RPC endpoints for enrollment. Similarly, when abusing ESC8, most tools abuse AD CS servers with the Certification Authority Web Enrollment role installed, enabling certificate enrollment through a vintage ASP HTTP application. They were understandably targeted since they’re by far the most common in networks.

However, we wanted to highlight that HTTP-based certificate enrollment can also occur when the Certificate Enrollment Web Service (CES) or the Network Device Enrollment Service (NDES) roles are installed on a server. The former implements the MS-WSTEP SOAP-based protocol to request certificates, and the latter implements Simple Certificate Enrollment Protocol (SCEP). While not as common, we do see these roles installed in networks. As such, attackers can leverage these two protocols to request certificates, including when abusing ESC8.

The PSCertificateEnrollment repo is a great implementation reference for how these protocols work. In addition, we’ve supplied a half-baked Python script that generates a MS-WSTEP HTTP request body that requests a certificate, and we’ve confirmed it works when exploiting ESC8 when CES is configured to support Windows Integrated Authentication (at least prior to the KB5014754 update when we created the script).

Speaking of the CES and NDES HTTP endpoints, administrators can install these roles on servers separate from AD CS servers. During installation, administrators can configure them to run using a service account. These service accounts and the machines they run on must be treated as tier 0.

For CES, Microsoft recommends assigning the service account a SPN to support Kerberos authentication and to grant the service account constrained delegation rights to the HOST and RPCSS services on the CA server. This allows the CES service the ability to impersonate users when requesting certificates from the CA’s DCOM server. As such, if you compromise this account, you can obtain access to the CA server by some S4U2Pwnage.

For NDES, Microsoft recommends assigning the account a SPN to support Kerberos authentication. As part of the NDES server setup, an enrollment agent certificate is requested and then the NDES service uses the certificate to request a certificate on behalf of other users. If an attacker compromises the NDES server, then the attacker can request a certificate as any other user using the enrollment agent certificate (same abuse steps as ESC2).

In addition, if the NDES service account is compromised and the NDES service requests certificates from templates supporting client authentication, an attacker could escalate privileges by forging silver tickets to the NDES service. However, by default the NDES service requests certificates from the IPSec (Offline Request) template which doesn’t support client authentication EKUs. That being said, administrators can change the templates the NDES service uses by editing certain registry values on the NDES server.

Authentication Errors

After we released our research, several people (including operators on our own team) started reporting various PKINIT authentication errors when trying to authenticate with a resulting certificate via Rubeus. These can often be tough to troubleshoot in the field, as various settings on the domain controller itself can result in this error. The following list isn’t complete, but explains at least a few of the situations.

KDC_ERR_PADATA_TYPE_NOSUPP

…when a domain controller doesn’t have a certificate installed for smart cards…” is probably the most common reason for KDC_ERR_PADATA_TYPE_NOSUPP. If the DC doesn’t have a “Domain Controller”, “Domain Controller Authentication”, or another certificate with the Server Authentication EKU (OID 1.3.6.1.5.5.7.3.1) installed, the DC isn’t properly set up for PKINIT and authentication will fail.

Also, according to Microsoft, “This problem can happen because the wrong certification authority (CA) is being queried or the proper CA cannot be contacted in order to get Domain Controller or Domain Controller Authentication certificates for the domain controller.” At least in some cases we’ve been able to auth via PKINIT to a DC even when the CA is not reachable, so this situation may be hit and miss.

If you run into a situation where you can enroll in a vulnerable certificate template but the resulting certificate fails for Kerberos authentication, you can try authenticating to LDAP via SChannel using something like PassTheCert. You will only have LDAP access, but this should be enough if you have a certificate stating you’re a domain admin.

KDC_ERR_CLIENT_NOT_TRUSTED

This error typically occurs if a certificate does not chain to a root CA a DC trusts or it doesn’t chain to a CA in the NTAuthCertificates store. There is a particular “weird” situation where this can occur that Jon Cave brough to our attention.

Typically, DCs sync the CAs listed in the NTAuthCertificates AD object locally to their registry at the key HKEY_LOCAL_MACHINESOFTWAREMicrosoftEnterpriseCertificatesNTAuthCertificates. It appears (though we are not 100% on this) that sometimes the local NTAuth store on DCs may not mirror the NTAuth store in Active Directory, causing both Kerberos and SChannel certificate authentication to fail.

One way this can happen that Jon pointed out (though, there might be other ways) is if auto-enrollment is disabled via the group policy “Public Key Policies/Certificate Services Client — Auto-Enrollment Settings/Automatic certificate management = Disabled”. Setting this GPO ultimately causes a value of 0x8000 (32768) to be set in the registry key HKLMSoftwarePoliciesMicrosoftCryptographyAutoEnrollmentAEPolicy. This is definitely something we want to investigate more.

Denied by Policy Module

This error usually occurs when the authenticating user does not have enrollment rights to a template. One case we ran into this is when a user had AutoEnroll rights to a template but not Enroll rights. Based on our research, CAs don’t actually perform an authorization check to validate that a user has auto-enrollment rights; instead, they simply check if the user has enrollment rights (see the function CTemplatePolicy::AccessCheck in certpdef.dll). Auto-enrollment rights on a template seem to function only as a hint to Windows machines that they should perform automatic enrollment, but do not function as an authorization control. We’ve removed checking for AutoEnroll rights from Certify and increased the verbosity of the error messages to make this error easier to understand.

ACE-ing Enrollment Permissions

While looking into AutoEnrollment rights, we noted that spec states that there’s two types of ACEs that control both Enrollment and AutoEnrollment rights in templates’ DACLs:

  • ACEs with a type of ACCESS_ALLOWED_OBJECT_ACE_TYPE — ACEs with this type conform to the ACCESS_ALLOWED_OBJECT_ACE structure. This type of ACE allows one to specify extended rights (a.k.a., control rights) in an ACE and is what is normally analyzed when evaluating AD permissions. For Enrollment and AutoEnrollment rights this corresponds with ACEs having an ObjectType GUID of 0e10c968–78fb-11d2–90d4–00c04f79dc55 and a05b8cc2–17bc-4802-a710-e7c15ab866a2, respectively.
  • ACEs with a type of ACCESS_ALLOWED_ACE_TYPE — ACEs with this type conform to the ACCESS_ALLOWED_ACE structure. This simpler ACE structure specifies access rights to a whole object. The spec states the an access mask with the 13th bit set (0xC) will grant Enroll or AutoEnroll permissions:

We were previously unaware that ACE ACCESS_ALLOWED_ACE ACEs granted access previously. However, in our testing, anytime we tried to set an ACCESS_ALLOWED_ACE in the DACL of a certificate template’s AD object, AD would just ignore the ACE. Our reversing/debugging of template access checking functions also seems to confirm this. 😢 If you have better luck, please let us know!

Toolsets and Follow-On Research!

Since we first released our research, a lot of tools and follow-on research have been published. We just wanted to call out some of the work people have done that we’ve run across (sorry if we missed anyone!):

Again, we’re sure we missed some additional work, but we’re very excited at the amount of interest and tools that have been developed around AD CS abuse!

Conclusion

Before last year, misconfigurations in AD CS often flew under the radar for many organizations, but the cataloging of escalation primitives, release of weaponized tooling, and the awesome expanded research by Oliver Lyak means that this is now a well defined and practiced class of attacks.

With the patch for Certified, Microsoft has (for the first time in a long time) modified how AD CS functions, which has some side effects for established escalation primitives. While some of the primitives will die off in May of 2023 when full enforcement mode becomes the default, there still are plenty of chances for organizations to misconfigure their AD CS deployments. It is still vitally important for companies to understand this class of attacks and figure out how to fix these issues before attackers exploit them.


Certificates and Pwnage and Patches, Oh My! was originally published in Posts By SpecterOps Team Members on Medium, where people are continuing the conversation by highlighting and responding to this story.