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 IDDescription
4886Certificate Services received a certificate request
4887Certificate Services approved and issued a certificate
4888Certificate Services denied a certificate request
4889Certificate Services set the status of a certificate request to pending
4768Kerberos TGT requested (used for PKINIT auth after cert issuance)
4870Certificate 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_SUBJECT and 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.