The problem with most Active Directory detections isn't that they're wrong — it's that they're brittle. A golden ticket alert that fires on RC4 encryption type but not AES is half a detection. A DCSync rule that matches only on the word "DCSync" in a tool name will miss any attacker who writes their own replication client. I've spent years building and tuning AD detections, and the consistent lesson is that durability comes from detecting behavior at multiple layers, not from chasing artifacts that attackers can trivially change.
This post covers three high-value AD persistence techniques I see most often in engagements and threat intelligence: golden tickets, DCSync, and AdminSDHolder abuse. For each one, I'll explain the mechanism, show why naive detections fail, and provide Splunk queries that are harder to evade.
Golden Ticket (T1558.001)
A golden ticket is a forged Kerberos TGT (Ticket-Granting Ticket) signed with the KRBTGT account's NTLM hash. Because the TGT is encrypted with a key only the KDC should know, a domain controller will treat a forged ticket as legitimate — even if it grants access to resources that don't exist, or uses a username that was deleted years ago. Attackers who have compromised the KRBTGT hash can re-enter an environment at will even after a full credential reset, as long as the KRBTGT isn't rotated (which most organizations avoid because of the operational disruption).
Why the simple detection fails
Most guidance points to Event ID 4769 (Kerberos service ticket request) with TicketEncryptionType = 0x17 (RC4-HMAC). The logic: legitimate environments that enforce AES should never see RC4 tickets, so RC4 is suspicious. But attackers know this. Modern tooling like Mimikatz and Rubeus can request AES-encrypted golden tickets. Filtering on encryption type alone is a losing game.
Resilient detection approach
A more durable signal comes from the ticket lifetime and the account metadata. Legitimate TGTs are constrained by domain policy — typically 10 hours, with 7-day renewal. Attackers often set golden ticket lifetimes to 10 years because the tools default to it, or because they want to avoid having to regenerate them. Additionally, a valid TGT from a non-existent account, or a TGT with a SID that doesn't match the account's actual SID history, is a clear anomaly.
| Splunk — Golden Ticket anomaly detection |
index=wineventlog EventCode=4769
| eval ticket_lifetime_hours = (TicketExpirationTime - TicketRequestTime) / 3600
| where ticket_lifetime_hours > 24
OR TicketEncryptionType = "0x17"
OR (Status = "0x0" AND NOT [
search index=wineventlog EventCode=4768
| fields TargetUserName
] )
| eval risk_score = case(
ticket_lifetime_hours > 8760, 100, /* 1 year+ = critical */
ticket_lifetime_hours > 24, 75,
TicketEncryptionType="0x17", 60,
true(), 40
)
| stats max(risk_score) as max_risk, values(ServiceName) as services,
dc(ServiceName) as svc_count, count by TargetUserName, IpAddress
| where max_risk >= 60 OR (svc_count > 10 AND max_risk >= 40)
| sort - max_risk
DCSync (T1003.006)
DCSync abuses the Active Directory Replication Service to request password hashes for any account, including KRBTGT and all domain admin accounts. It doesn't require running code on a domain controller — any account with the Replicating Directory Changes and Replicating Directory Changes All permissions (or Replicating Directory Changes In Filtered Set for RODC scenarios) can perform the attack remotely using tools like Mimikatz's lsadump::dcsync or Impacket's secretsdump.py.
The event to watch
The telltale log is Event ID 4662 on domain controllers — an operation was performed on an Active Directory object. DCSync generates a 4662 with the object type GUID for domain objects (19195a5b-6da0-11d0-afd3-00c04fd930c9) and the access right GUIDs for Replicating Directory Changes (1131f6aa-9c07-11d1-f79f-00c04fc2dcd2) and Replicating Directory Changes All (1131f6ad-9c07-11d1-f79f-00c04fc2dcd2).
| Splunk — DCSync detection via Event 4662 |
index=wineventlog EventCode=4662
Properties="*1131f6aa*" OR Properties="*1131f6ad*"
| eval is_replication_guid =
if(match(Properties,
"1131f6aa-9c07-11d1-f79f-00c04fc2dcd2|1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"),
1, 0)
| where is_replication_guid = 1
| lookup domain_controllers.csv hostname AS SubjectUserName OUTPUT is_dc
| where isnull(is_dc) OR is_dc != "true"
| stats count, earliest(_time) as first_seen, latest(_time) as last_seen,
values(ObjectName) as objects_accessed
by SubjectUserName, SubjectLogonId, IpAddress
| where count > 0
| eval alert = "DCSync: non-DC performing directory replication from " . IpAddress
| sort - count
The lookup against a known DC list is essential. Legitimate DCs replicate constantly — without filtering them, you'll drown in noise. Build your DC list from SCCM, DNS, or a Splunk lookup table maintained by your identity team.
Evasion and layered detection
Attackers can reduce 4662 noise by replicating only specific attributes (NTLM hashes via unicodePwd) rather than full object dumps, making the volume anomaly harder to spot. Layer in network detection: DCSync uses MS-DRSR over RPC (port 135 + high dynamic ports). A non-DC host originating MS-DRSR traffic to a DC is high-fidelity signal regardless of what AD logs show.
AdminSDHolder Abuse (T1098)
AdminSDHolder is an Active Directory container that serves as a permission template for protected groups — Domain Admins, Enterprise Admins, Schema Admins, and others. Every hour (by default), the SDProp process runs and forces the ACL on every protected account to match the AdminSDHolder template. The intended purpose is to prevent ACL drift on privileged accounts. The abusable property: if an attacker modifies the AdminSDHolder ACL to grant a low-privileged account control rights, SDProp will propagate that access to every protected group member automatically within an hour — and will continue to re-apply it even if a defender removes it from the individual accounts.
Detection
Watch for ACL modifications on the AdminSDHolder object itself. This is Event ID 4662 again, but with the specific Distinguished Name of the AdminSDHolder container and write/modify DACL access rights:
| Splunk — AdminSDHolder ACL modification |
index=wineventlog EventCode=4662
ObjectName="*AdminSDHolder*"
AccessMask="0x40000" OR AccessMask="0x20000" /* WRITE_DAC | WRITE_OWNER */
| lookup privileged_accounts.csv account AS SubjectUserName OUTPUT is_admin
| where isnull(is_admin) OR is_admin != "true"
| table _time, SubjectUserName, SubjectLogonId, IpAddress,
ObjectName, AccessMask, Properties
| eval alert_text = "Non-privileged account modified AdminSDHolder ACL: "
. SubjectUserName . " from " . IpAddress
| sort - _time
You should also monitor for the results of SDProp propagation: if a low-privileged account suddenly has ACEs granting it control over Domain Admins members, that's a secondary indicator even if you missed the initial AdminSDHolder modification. Event ID 4670 (permissions on an object were changed) on Domain Admins group members, where the new ACE grants rights to an unexpected account, is worth alerting on.
Building for Durability
Across all three techniques, the pattern that makes detections resilient is the same: detect the behavior, not the tool. Golden ticket detection based on encryption type is detecting Mimikatz's defaults, not the attack. DCSync detection based on the string "dcsync" in a process name is detecting a naming convention. AdminSDHolder detection based on specific tool signatures is detecting the known tools.
Behavioral detections — ticket lifetime anomalies, replication from non-DCs, unexpected ACL modifications to protected containers — detect the technique regardless of the tooling. They're also harder to tune away through configuration changes, because the behavior itself is the signal.
The other durability principle: every detection should have a documented evasion case and a secondary layer that covers it. If an attacker knows your golden ticket rule fires on RC4, they'll use AES. Your rule should fire on both, or on something they can't change — like the absence of a preceding 4768. Document the evasion surface for every detection you ship. It forces clarity about what you're actually detecting and where the gaps are.