AD CS hardening: closing ESC1-ESC8 misconfigurations
Harden Active Directory Certificate Services against ESC1-ESC8 misconfigurations with template controls, EPA, and enrollment monitoring.
Active Directory Certificate Services is Tier 0 infrastructure, on par with domain controllers, because a certificate the CA issues can authenticate as any account the requester names — sidestepping domain controller defenses entirely. The ESC1 through ESC8 misconfiguration classes documented by the security research community describe distinct ways an over-permissive CA hands out certificates it shouldn't. This guide covers each class at a defensive level — what the misconfiguration looks like and how to close it — plus verification commands and the monitoring to catch abuse attempts.
Why AD CS is Tier 0
A CA's job is to bind an identity to a public key. If a low-privileged user can request a certificate for a Domain Admin — or for any account with a Client Authentication EKU — they can use that certificate to authenticate as that account via PKINIT, without ever knowing its password and without touching a domain controller's authentication stack directly. The CA server itself, and the private key of the CA's own root or issuing certificate, must be treated with the same tiering discipline as a domain controller: no browsing from the CA, no non-PKI-admin logons, dedicated hardened administrative workstations for CA management.
The ESC1-ESC8 classes, defensively
These are described conceptually — the misconfiguration and its fix — not as exploitation steps.
ESC1: Enrollee supplies subject + client authentication EKU
A certificate template that lets the requester specify an arbitrary Subject Alternative Name (SAN), combined with an EKU that permits client authentication (Client Authentication, Smart Card Logon, or similar), lets any enrollee-eligible user request a certificate impersonating another account, including privileged ones.
Fix: audit every template for the enrollee-supplies-subject flag. Remove it unless there is a specific, documented business need (some auto-enrollment scenarios legitimately need it — pair those with tightly restricted enrollment permissions instead).
# List templates and flag enrollee-supplies-subject
Get-ADObject -SearchBase (Get-ADRootDSE).ConfigurationNamingContext `
-LDAPFilter "(objectClass=pKICertificateTemplate)" -Properties msPKI-Certificate-Name-Flag, pKIExtendedKeyUsage |
Select-Object Name, msPKI-Certificate-Name-Flag, pKIExtendedKeyUsagemsPKI-Certificate-Name-Flag is a bitmask: templates with bit 0x1 (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT) set are the risky ones. Cross-reference against pKIExtendedKeyUsage OIDs for client authentication (1.3.6.1.5.5.7.3.2) or smart card logon (1.3.6.1.4.1.311.20.2.2).
ESC2: Any-purpose or no-EKU templates
A template with no EKU restriction, or the Any Purpose EKU, can be abused the same way as ESC1 once combined with subject control or a vulnerable enrollment agent. Remove Any Purpose and no-EKU templates from general enrollment; scope them narrowly or retire them.
ESC3: Vulnerable certificate request agent
Enrollment Agent templates let the holder request certificates on behalf of other users. An overly broad Enrollment Agent template (issued to a wide group, without restricting which templates/users the agent can enroll for) becomes an impersonation path. Restrict Enrollment Agent issuance and pair it with the CA's "Certificate Managers Restrictions" (per-agent, per-template, per-target-user restrictions).
ESC4: Weak template access control
If a low-privileged group holds Write/WriteDacl/WriteOwner rights on a sensitive template's AD object, they can rewrite it to introduce ESC1-style flags themselves. Audit template ACLs, not just template settings.
$templates = Get-ADObject -SearchBase (Get-ADRootDSE).ConfigurationNamingContext `
-LDAPFilter "(objectClass=pKICertificateTemplate)"
foreach ($t in $templates) {
(Get-Acl -Path "AD:\$($t.DistinguishedName)").Access |
Where-Object { $_.ActiveDirectoryRights -match "WriteProperty|WriteDacl|WriteOwner|GenericAll" } |
Select-Object @{n='Template';e={$t.Name}}, IdentityReference, ActiveDirectoryRights
}ESC5: Weak PKI object access control
Same principle as ESC4 but applied to the CA object, the NTAuthCertificates object, or the Certificate Templates container/CA container itself. Anyone with write access to these AD objects can add a rogue CA to the forest's trusted issuers.
ESC6: EDITF_ATTRIBUTESUBJECTALTNAME2
This CA-wide flag allows a SAN to be supplied in the request for any template, regardless of the template's own subject flags — effectively turning every enabled template into an ESC1 risk. Check and remove it:
certutil -config "<CAHostName>\<CAName>" -getreg policy\EditFlagsLook for EDITF_ATTRIBUTESUBJECTALTNAME2 in the output. Remove it:
certutil -config "<CAHostName>\<CAName>" -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2
net stop certsvc; net start certsvcESC7: Vulnerable CA access control
Overly broad CA-level permissions (Manage CA, Manage Certificates) granted to non-PKI-admin groups let holders approve pending requests or modify CA-level settings, including issuing certificates that would otherwise be denied. Review with certutil -getreg CA\Security or the CA MMC snap-in's Security tab, and restrict to the PKI admin group only.
ESC8: NTLM relay to CA web enrollment
The CA's HTTP/HTTPS web enrollment endpoint (certsrv, or CES/CEP for auto-enrollment) accepts NTLM authentication over a channel that, without Extended Protection for Authentication (EPA), can be relayed from a coerced or intercepted NTLM authentication elsewhere on the network — yielding a certificate for whatever identity was relayed. This is the AD CS-specific instance of the broader NTLM relay problem covered in Stop NTLM Relay.
Fix: enforce HTTPS on all web enrollment endpoints and enable Extended Protection for Authentication in IIS on the CertSrv/CES/CEP virtual directories. If web enrollment isn't in active use, disable the role service entirely.
# Require SSL and enable EPA on the CertSrv virtual directory (run on the CA/enrollment web server).
# These sections are locked at server level, so write them to applicationHost.config with -Location.
Import-Module WebAdministration
$loc = 'Default Web Site/CertSrv'
Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Location $loc `
-Filter 'system.webServer/security/access' -Name sslFlags -Value 'Ssl'
Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Location $loc `
-Filter 'system.webServer/security/authentication/windowsAuthentication' `
-Name 'extendedProtection.tokenChecking' -Value 'Require'General remediations checklist
| Control | Action |
|---|---|
| Manager approval | Require manager approval on templates with sensitive EKUs: tick "CA certificate manager approval" on the template's Issuance Requirements tab (sets CT_FLAG_PEND_ALL_REQUESTS, 0x2, in msPKI-Enrollment-Flag) |
| SAN flag | Remove CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT from templates that don't need it |
| Enrollment rights | Restrict Enroll/AutoEnroll permissions to the smallest group that needs them; remove Domain Users / Authenticated Users where present on sensitive templates |
| Web enrollment | Enforce HTTPS + EPA, or disable if unused |
| Monitoring | Enable CA auditing and review issued-certificate logs |
Monitoring and detection
Enable CA auditing so every issuance, denial, and template change is logged:
certutil -setreg CA\AuditFilter 127
auditpol /set /subcategory:"Certification Services" /success:enable /failure:enableReview the Security event log on the CA for event ID 4886 (request submitted), 4887 (certificate issued), 4888 (denied), and 4899 (template modified). Baseline expected requesters per template and alert on issuance to unexpected accounts or unexpected SANs:
Get-WinEvent -LogName Security | Where-Object { $_.Id -in 4886,4887,4888,4899 } |
Select-Object TimeCreated, Id, MessageAlso periodically export template configuration for drift detection:
certutil -v -Template "<TemplateName>" > template-audit.txtWhat it breaks
- Removing SAN flags / tightening enrollment: any workflow that relies on self-service certificate requests with custom subjects (some VPN client provisioning, IoT/device enrollment scripts) will need to be re-pointed at a dedicated, tightly scoped template instead.
- Manager approval: turns auto-enrollment into a pending-request workflow for affected templates, adding latency for end users until an approver acts — scope it to sensitive templates only, not the whole CA.
- EPA on web enrollment: breaks clients or load balancers that terminate TLS before IIS in a way that strips the channel-binding token; validate your TLS termination path before enabling.
- Disabling web enrollment: breaks any process still depending on the legacy
certsrvpages or CES/CEP for auto-enrollment over HTTP — migrate those to Group Policy autoenrollment first.
See also Domain controller hardening and Kerberos hardening for adjacent Tier 0 controls, and ESC1 for a deeper look at that specific misconfiguration class.
Frequently asked questions
Why is AD CS considered Tier 0?
A compromised certificate authority can issue a certificate that authenticates as any user, including Domain Admins, without touching the domain controller directly. Anyone who can request such a certificate — or who controls the CA server itself — has a path to full domain compromise, which is the definition of Tier 0.
What is the quickest ESC1 fix?
Audit every certificate template with Client Authentication or Smart Card Logon EKU for the enrollee-supplies-subject flag combined with broad enrollment permissions. Remove the flag or restrict enrollment to a tightly scoped group, whichever preserves the legitimate workflow.
Do I need Extended Protection for Authentication on every CA?
Yes, on any CA exposing HTTP or HTTPS web enrollment endpoints (CES/CEP, the legacy web enrollment pages). EPA binds the NTLM/Kerberos authentication to the TLS channel, closing the relay path used in ESC8. If web enrollment isn't used, disable it instead.
AD CS hardening: closing ESC1-ESC8 misconfigurations