Query Details
// =========================================================
// RULE-07 | AD-ADCS-Certificate-SAN-Mismatch
// Description : ADCS ESC1 / ESC8 Certificate Abuse —
// Event 4887 (Certificate Issued) where the
// Subject Alternative Name (SAN) in the
// certificate contains a UPN that DIFFERS from
// the requesting account, OR where the same
// account requests ≥3 certificates within 10
// minutes (burst enrollment pattern).
// ESC1 lets an attacker supply any SAN
// (e.g., administrator@domain) when requesting
// a certificate, effectively impersonating DA.
// Severity : High (SAN mismatch) → Critical (DA UPN in SAN
// or machine-account cert issued as DC name)
// Frequency : Every 15 minutes, look-back 15 minutes
// MITRE : T1649 — Steal or Forge Authentication Certs
// T1078 — Valid Accounts
// Tables : SecurityEvent
// =========================================================
let LookBack = 15m;
let BurstThreshold = 3; // ≥3 certs/10 min from 1 account = suspicious
// High-value SANs (if SAN contains these → Critical)
let SensitiveSANPatterns = dynamic([
"administrator", "domain admins", "enterprise admins",
"krbtgt", "dc$", "-dc@", "dc01", "dc02"
]);
// Event 4887: Certificate Issued — extract SAN from EventData
SecurityEvent
| where TimeGenerated > ago(LookBack)
| where EventID == 4887
| extend
RequesterAccount = SubjectUserName,
RequesterDomain = SubjectDomainName,
CertificateDetails = EventData
// Parse the Subject and Requester from raw EventData (XML-style)
| extend SubjectField = extract(@"<Data Name=""SubjectKeyIdentifier"">[^<]*</Data>", 0, EventData)
| extend TemplateName = extract(@"<Data Name=""CertificateTemplate"">(.*?)</Data>", 1, EventData)
| extend RequestAttributes= extract(@"<Data Name=""RequestAttributes"">(.*?)</Data>", 1, EventData)
// Look for SAN that doesn't match the requester
| extend SANValue = extract(@"(?i)(san|subjectaltname|upn)=([^;,]+)", 2, RequestAttributes)
| extend SANNormalized = tolower(SANValue)
| extend RequesterNorm = tolower(RequesterAccount)
| extend
SANMismatch = isnotempty(SANValue) and not(SANNormalized contains RequesterNorm),
SensitiveSAN = isnotempty(SANValue) and SANNormalized has_any (SensitiveSANPatterns)
// Burst enrollment detection
| summarize
TotalCerts = count(),
MismatchedCerts = countif(SANMismatch),
SensitiveSANCerts = countif(SensitiveSAN),
Templates = make_set(TemplateName, 10),
SANValues = make_set(SANValue, 10),
EarliestCert = min(TimeGenerated),
LatestCert = max(TimeGenerated)
by RequesterAccount, RequesterDomain, Computer
| where TotalCerts >= BurstThreshold
or MismatchedCerts >= 1
or SensitiveSANCerts >= 1
| extend
Severity = case(
SensitiveSANCerts >= 1, "Critical",
MismatchedCerts >= 1, "High",
TotalCerts >= BurstThreshold, "Medium",
"Low"
),
WhySuspicious = strcat(
iff(SensitiveSANCerts >= 1, "SensitiveSAN_DA_or_DC; ", ""),
iff(MismatchedCerts >= 1, "SAN_Mismatch_ESC1_Pattern; ", ""),
iff(TotalCerts >= BurstThreshold, "BurstEnrollment_>=3_certs; ", ""),
"Templates: ", strcat_array(Templates, ",")
)
| project
TimeGenerated = LatestCert,
Severity,
WhySuspicious,
RequesterAccount,
RequesterDomain,
Computer,
TotalCerts,
MismatchedCerts,
SensitiveSANCerts,
SANValues,
Templates
| order by SensitiveSANCerts desc, MismatchedCerts desc
This query is designed to detect suspicious activities related to the issuance of certificates in an Active Directory Certificate Services (ADCS) environment. Here's a simplified explanation of what it does:
Time Frame: It looks at security events from the last 15 minutes.
Event Focus: It specifically examines Event ID 4887, which indicates that a certificate has been issued.
Key Checks:
Severity Levels:
Output: The query summarizes the findings, providing details such as the account that requested the certificates, the domain, the computer involved, and the number of certificates issued. It also explains why the activity is considered suspicious.
Sorting: The results are ordered by the most critical findings, prioritizing sensitive SANs and mismatches.
Overall, this query helps identify potential certificate abuse or misconfigurations that could lead to unauthorized access or impersonation within a network.

David Alonso
Released: March 24, 2026
Tables
Keywords
Operators