Attackers who find GenericAll, WriteDACL or WriteOwner on a privileged object can grant themselves control, then reset passwords, add group members or enable roasting. The grant is a write to nTSecurityDescriptor, which directory-service change auditing records in full. Watching those writes on sensitive objects turns a quiet permission edge into a loud alert.
Signals at a Glance
| Signal | Where | ATT&CK |
|---|---|---|
| nTSecurityDescriptor change on a privileged user, group, OU or the domain root | DC Security 5136 | T1222 |
| New ACE granting GenericAll, WriteDACL or WriteOwner to a non-admin SID | 5136 AttributeValue | T1222 |
| Change to the AdminSDHolder object | DC Security 5136 | T1098 |
| WRITE_DAC (0x40000) access on a directory object | DC Security 4662 | T1222 |
| Unexpected group membership change that follows an ACL edit | DC Security 4728, 4732, 4756 | T1098 |
Reading the Descriptor
Event ID 5136 for nTSecurityDescriptor contains the descriptor as an SDDL string, in separate events for the removed and the added value. Parse the ACEs and flag allow-entries that grant full control, DACL write or ownership write to a non-privileged SID. Scope this to the objects that matter, because ACL changes elsewhere are constant:
let sensitive = dynamic(["CN=Domain Admins","CN=Enterprise Admins","CN=Administrators",
"CN=AdminSDHolder","CN=Schema Admins"]); // tune/validate
SecurityEvent
| where EventID == 5136 and AttributeLDAPDisplayName == "nTSecurityDescriptor"
| where OperationType == "%%14674" // value added
| where ObjectDN has_any (sensitive) or ObjectClass in~ ("domainDNS","organizationalUnit")
| where AttributeValue matches regex @"\(A;[^;]*;(GA|WD|WO|GW|0x[0-9a-fA-F]*)[^;]*;[^;]*;[^;]*;S-1-5-21-"
| project TimeGenerated, SubjectUserName, ObjectDN, ObjectClass, AttributeValue
// tune/validate: GA = generic all, WD = write DACL, WO = write owner. Exclude your
// identity-management and Exchange/Entra Connect service accounts by SubjectUserName.
If the descriptor edit used a direct permission request rather than a change, Event ID 4662 with the WRITE_DAC access mask records the attempt even where 5136 coverage is thin. Scope it to protected objects:
title: WRITE_DAC Access On Sensitive Directory Object
status: experimental
logsource:
product: windows
service: security
detection:
selection:
EventID: 4662
AccessMask|contains: '0x40000'
ObjectServer: 'DS'
filter_system:
SubjectUserName|endswith: '$'
condition: selection and not filter_system
level: medium
# tune/validate: add a scope for protected-object GUIDs; without one this is noisy.
Response and Prevention
- Alert on any change to AdminSDHolder; it is propagated to protected accounts and groups within about an hour.
- Review ACLs on the domain root, Domain Admins, AdminSDHolder and the Domain Controllers OU on a schedule using BloodHound or ADACLScanner output.
- When an alert fires, diff the descriptor, revert the ACE, and check for the follow-on action: password reset, group change or SPN write.
- Restrict who can modify permissions at all, and remove delegated rights from accounts used day to day.
Use the SigmaHQ and Elastic AD ACL rules, Splunk ESCU directory-permission analytics, BloodHound documentation for the abusable edges and Microsoft and Trimarc AD hardening guidance for protected objects. Baseline your own environment — Exchange, identity-sync and PAM products write ACEs routinely and need named exceptions.
Build Detections That Fire
Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.
- Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
- Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
- 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Stay ahead of emerging threats. Get notified when we publish new intelligence reports and advisories.
Subscribe to Alerts