ACL ABUSE
DACL
GENERICALL
ADMINSDHOLDER
DetectionBlue TeamSOCOctober 12, 2026•9 min read

Detecting AD ACL and DACL Abuse: GenericAll, WriteDACL and Ownership

Most Active Directory privilege escalation paths are permission edges, not exploits. Adding one ACE can turn a normal user into a path to Domain Admin.

Scroll

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

SignalWhereATT&CK
nTSecurityDescriptor change on a privileged user, group, OU or the domain rootDC Security 5136T1222
New ACE granting GenericAll, WriteDACL or WriteOwner to a non-admin SID5136 AttributeValueT1222
Change to the AdminSDHolder objectDC Security 5136T1098
WRITE_DAC (0x40000) access on a directory objectDC Security 4662T1222
Unexpected group membership change that follows an ACL editDC Security 4728, 4732, 4756T1098

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

Vetted sources

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 EngineeringManaged Detection & ResponseThreat HuntingIncident ResponsePurple Teaming
  • 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.
Written by: Mjolnir Threat Research (MTAC)  |  Published: October 12, 2026  |  Last reviewed: October 12, 2026