Active Directory Certificate Services (ADCS) is present in the overwhelming majority of enterprise Windows environments and is almost universally misconfigured in at least one of the ways documented by SpecterOps in the landmark 2021 research that introduced the ESC taxonomy. As of 2026, sixteen ESC (Escalation via Certificate Services) techniques have been formally catalogued — and the three most exploited (ESC1, ESC4, ESC8) remain achievable in most environments that haven’t specifically remediated them.
Detection is achievable. The challenge is that ADCS logging is disabled or under-configured on most deployments, and the relevant event IDs are not in the default SIEM onboarding checklist. This guide covers what to enable and what to look for.
The ESC Techniques Most Commonly Exploited
ESC1 — Enrollee-Supplied Subject Alternative Name. Certificate templates with the CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT flag allow the requesting user to specify an arbitrary SAN (Subject Alternative Name) in the CSR. If the template is marked for client authentication and is enrollable by standard domain users, any user can request a certificate claiming to be any identity — including Domain Admin. The resulting certificate authenticates to Kerberos as the impersonated account.
ESC4 — Weak Template ACLs. Low-privileged users hold Write ACLs on a certificate template, allowing them to modify the template’s configuration — enabling ESC1 conditions on a template that previously didn’t have them.
ESC8 — NTLM Relay to AD CS HTTP Endpoints. The AD CS Web Enrollment endpoint (/certsrv) accepts NTLM authentication and is not protected against relay attacks by default. A coercion technique (SpoolSS, DFSCoerce, PetitPotam) tricks a domain controller into authenticating to an attacker-controlled host, which relays that authentication to the CA’s web enrollment endpoint to obtain a certificate for the DC account. This provides LDAP access equivalent to DCSync.
Enabling the Right Logging
Before detection is possible, you need to enable ADCS audit logging.
On the CA server, run:
certutil -setreg policy\EditFlags +EDITF_AUDITCERTTEMPLATELOAD
Restart-Service certsvc
Then enable auditing via Group Policy or locally:
Computer Configuration → Windows Settings → Security Settings → Local Policies → Audit Policy
→ Audit object access: Success, Failure
The relevant Windows Security Event IDs:
| Event ID | Description |
|---|---|
| 4886 | Certificate Services received a certificate request |
| 4887 | Certificate Services approved and issued a certificate |
| 4888 | Certificate Services denied a certificate request |
| 4889 | Certificate Services set the status of a certificate request to pending |
| 4768 | Kerberos TGT requested (used for PKINIT auth after cert issuance) |
| 4870 | Certificate Services revoked a certificate |
The critical detection chain for ESC1: 4886 (request received) → 4887 (certificate issued) → 4768 with PA-DATA type PKINIT within a short window. If the certificate’s SAN does not match the requesting account, this is a high-confidence indicator.
Sigma Rules
ESC1: SAN Mismatch on Certificate Issuance
title: ADCS Certificate Issued with SAN Not Matching Requester
id: 7a8d3e91-4f2b-4c8a-b3d1-6e5f7a9c2b4d
status: stable
description: Detects certificate issuance where the Subject Alternative Name field
does not match the requester account — indicative of ESC1 or ESC4 exploitation
where an attacker supplies a SAN for a higher-privileged identity.
references:
- https://specterops.io/assets/resources/Certified_Pre-Owned.pdf
author: SOC Analyst Hub
date: 2026/06/01
tags:
- attack.privilege_escalation
- attack.t1649
logsource:
product: windows
service: security
detection:
selection:
EventID: 4887
filter_san_match:
# SAN matches the requester CN — normal operation
CertificateSubjectAltName|contains: '%SubjectUserName%'
condition: selection and not filter_san_match
fields:
- SubjectUserName
- CertificateSubjectAltName
- CertificateTemplateName
- CallerComputerName
falsepositives:
- Service accounts requesting certs for service SPNs
- Enrollment agents legitimately issuing certs on behalf of users
level: high
ESC8: NTLM Authentication to AD CS Web Enrollment
title: NTLM Authentication to AD CS certsrv Endpoint
id: 2c7f4a85-9e3d-4b1c-a8f2-5d6e8b0c9f3a
status: experimental
description: Detects NTLM authentication events to the AD CS HTTP enrollment
endpoint. Legitimate certificate enrollment should use Kerberos; NTLM auth
to certsrv is characteristic of relay attacks (ESC8).
author: SOC Analyst Hub
date: 2026/06/01
tags:
- attack.privilege_escalation
- attack.t1649
- attack.lateral_movement
- attack.t1550.002
logsource:
product: windows
service: iis
detection:
selection:
cs-uri-stem|contains: '/certsrv/'
cs-auth-type: 'NTLM'
filter_normal_sources:
c-ip|startswith:
- '10.'
- '192.168.'
- '172.'
condition: selection
# Remove filter to see all; keep to reduce noise in trusted networks
falsepositives:
- Legacy enrollment tooling configured for NTLM
- Misconfigured enrollment agents
level: high
KQL Hunting Query (Microsoft Sentinel)
This query correlates certificate request events with subsequent PKINIT authentication attempts to detect the complete ESC1 attack chain:
// ADCS ESC1 Detection: Cert issued with mismatched SAN, followed by PKINIT auth
let CertIssuanceWindow = 30m;
let SuspiciousIssuance = SecurityEvent
| where EventID == 4887
| extend
Requester = extract(@"Requester:\s+(.+?)\r", 1, EventData),
SAN = extract(@"Subject Alternative Name:\s+(.+?)\r", 1, EventData),
Template = extract(@"Certificate Template Name:\s+(.+?)\r", 1, EventData)
| where isnotempty(SAN)
| where not(SAN contains Requester)
| project TimeGenerated, Requester, SAN, Template, Computer;
let PKINITAuth = SecurityEvent
| where EventID == 4768
| extend AuthPackage = extract(@"Pre-Authentication Type:\s+(\d+)", 1, EventData)
| where AuthPackage == "16" // PKINIT
| project PKINITTime = TimeGenerated, PKINITUser = Account, PKINITSource = IpAddress;
SuspiciousIssuance
| join kind=inner (PKINITAuth) on $left.SAN == $right.PKINITUser
| where PKINITTime between (TimeGenerated .. (TimeGenerated + CertIssuanceWindow))
| project
CertIssuedAt = TimeGenerated,
PKINITAuthAt = PKINITTime,
Requester,
ImpersonatedAccount = SAN,
Template,
AuthSourceIP = PKINITSource
| order by CertIssuedAt desc
Enumeration Tooling to Monitor For
Tools commonly used to enumerate and exploit ADCS misconfigurations leave process execution and network artefacts:
Certipy: Python tool that enumerates certificate templates via LDAP and automates ESC1-ESC13 exploitation. Key indicator: LDAP queries against the pKICertificateTemplate object class from non-CA systems or engineering workstations. Look for certutil.exe or certipy process creation.
Certify.exe (SpecterOps): .NET binary. Execution from unusual paths or by non-admin users is suspicious. Hash-based detections are viable since it’s not a living-off-the-land binary.
certutil.exe misuse: Native Windows binary. Monitor for certutil.exe -dump, certutil.exe -url, or certutil.exe -addstore executed by non-admin accounts, particularly from PowerShell or cmd.
Remediation Guidance (Passing to Defenders)
For each ESC:
- ESC1: Audit templates with
CT_FLAG_ENROLLEE_SUPPLIES_SUBJECTand mark them as requiring manager approval, or remove the flag entirely. - ESC4: Review ACLs on all certificate templates. No standard user or group should hold GenericWrite, WriteDacl, or WriteOwner on any template.
- ESC8: Enable HTTPS on the Web Enrollment endpoint and configure it for Kerberos-only authentication (disable NTLM). Or disable the Web Enrollment role entirely if not required — most environments use autoenrollment over LDAP rather than the HTTP endpoint.
Microsoft’s PKIAudit module (released as part of MSRC advisory guidance) automates baseline enumeration of ESC1-ESC8 conditions and should be part of any Active Directory health check.