| ID | Technique | Tactic |
|---|---|---|
| T1562.010 | Downgrade Attack | Stealth |
Detection: Windows AD SPN Unicode Collision Injection
Description
The following analytic detects the addition or modification of a servicePrincipalName (SPN) containing invisible Unicode characters to an Active Directory computer object via Windows Security Event 5136. This is the key indicator of the KerberLoss attack (CVE-2026-25177), where an attacker with write access to a machine account's SPN attribute injects a collision SPN that contains a Zero Width or other invisible Unicode character (e.g. U+200C Zero Width Non-Joiner). LDAP's string preparation rules (RFC 4518) cause these characters to be ignored during uniqueness checking, allowing the write to succeed even when an identical SPN already exists on another machine account. The Kerberos KDC, however, does not apply the same normalisation — it finds two accounts with matching SPNs and returns KDC_ERR_S_PRINCIPAL_UNKNOWN, causing a Kerberos denial-of-service or forcing clients to fall back to NTLM downgrade.
Search
1`wineventlog_security`
2EventCode=5136
3AttributeValue=*
4AttributeLDAPDisplayName=servicePrincipalName
5OperationType IN (
6 "%%14674",
7 "%%14675"
8)
9
10
11| regex AttributeValue="[\x{034F}\x{200B}-\x{200F}\x{00AD}\x{1806}\x{FEFF}\x{FFFC}\x{2060}\x{206A}-\x{206F}\x{180B}-\x{180D}\x{FE00}-\x{FE0F}]"
12
13
14| eval matched_invisible_chars=mvappend(
15 if(match(AttributeValue, "\x{034F}"), "U+034F (Combining Grapheme Joiner)", null()),
16 if(match(AttributeValue, "\x{200B}"), "U+200B (Zero Width Space)", null()),
17 if(match(AttributeValue, "\x{200C}"), "U+200C (Zero Width Non-Joiner)", null()),
18 if(match(AttributeValue, "\x{200D}"), "U+200D (Zero Width Joiner)", null()),
19 if(match(AttributeValue, "\x{200E}"), "U+200E (Left-to-Right Mark)", null()),
20 if(match(AttributeValue, "\x{200F}"), "U+200F (Right-to-Left Mark)", null()),
21 if(match(AttributeValue, "\x{00AD}"), "U+00AD (Soft Hyphen)", null()),
22 if(match(AttributeValue, "\x{1806}"), "U+1806 (Mongolian Todo Soft Hyphen)", null()),
23 if(match(AttributeValue, "\x{FEFF}"), "U+FEFF (Zero Width No-Break Space)", null()),
24 if(match(AttributeValue, "\x{FFFC}"), "U+FFFC (Object Replacement Character)", null()),
25 if(match(AttributeValue, "\x{2060}"), "U+2060 (Word Joiner)", null()),
26 if(match(AttributeValue, "[\x{206A}-\x{206F}]"), "U+206A-206F (Deprecated Format Characters)", null()),
27 if(match(AttributeValue, "[\x{180B}-\x{180D}]"), "U+180B-180D (Variation Selectors)", null()),
28 if(match(AttributeValue, "[\x{FE00}-\x{FE0F}]"), "U+FE00-FE0F (Variation Selectors)", null()))
29
30
31| where isnotnull(matched_invisible_chars)
32
33| rename Computer as dest
34
35
36| stats count min(_time) as firstTime
37 max(_time) as lastTime
38 values(matched_invisible_chars) as matched_invisible_chars
39 by dest SubjectUserName SubjectDomainName ObjectDN ObjectClass AttributeValue
40
41
42| `security_content_ctime(firstTime)`
43
44| `security_content_ctime(lastTime)`
45
46| `windows_ad_spn_unicode_collision_injection_filter`
Data Source
| Name | Platform | Sourcetype | Source |
|---|---|---|---|
| Windows Event Log Security 5136 | 'XmlWinEventLog' |
'XmlWinEventLog:Security' |
Macros Used
| Name | Value |
|---|---|
| security_content_ctime | convert timeformat="%Y-%m-%dT%H:%M:%S" ctime($field$) |
| windows_ad_spn_unicode_collision_injection_filter | search * |
windows_ad_spn_unicode_collision_injection_filter is an empty macro by default. It allows the user to filter out any results (false positives) without editing the SPL.
Annotations
CVE
Default Configuration
This detection is configured by default in Splunk Enterprise Security to run with the following settings:
| Setting | Value |
|---|---|
| Disabled | true |
| Cron Schedule | 0 * * * * |
| Earliest Time | -70m@m |
| Latest Time | -10m@m |
| Schedule Window | auto |
| Creates Finding (Notable) | Yes |
| Rule Title | %name% |
| Rule Description | %description% |
| Notable Event Fields | user, dest |
| Creates Intermediate Finding (Risk Event) | No |
Implementation
To successfully implement this search, you need to be ingesting Domain Controller Security event logs. Enable the Advanced Security Audit policy DS Access > Audit Directory Service Changes for Success events. Additionally, a WriteProperty audit SACL must be configured on the computer object class (or the CN=Computers container with inheritance) to generate Event 5136 when servicePrincipalName is modified.
Known False Positives
Legitimate use of invisible Unicode characters in SPN values is not expected. This detection should have a very low false positive rate. Provisioning tools or scripts that incorrectly encode SPN strings from certain character sets may trigger this. Verify the SubjectUserName and ObjectDN to confirm intent.
Associated Analytic Story
Finding
| Title | Entity Field | Entity Type | Risk Score |
|---|---|---|---|
| User [$SubjectUserName$] injected an invisible-Unicode SPN [$matched_invisible_chars$] onto [$ObjectDN$] on $dest$ | SubjectUserName | user | 50 |
Threat Objects
| Field | Type |
|---|---|
| AttributeValue | user |
References
-
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-25177
-
https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-5136
Detection Testing
| Test Type | Status | Dataset | Source | Sourcetype |
|---|---|---|---|---|
| Validation | ✅ Passing | N/A | N/A | N/A |
| Unit | ✅ Passing | Dataset | XmlWinEventLog:Security |
XmlWinEventLog |
| Integration | ✅ Passing | Dataset | XmlWinEventLog:Security |
XmlWinEventLog |
Replay any dataset to Splunk Enterprise by using our replay.py tool or the UI.
Alternatively you can replay a dataset into a Splunk Attack Range
Source: GitHub |
Version: 1