Expand description
Active Directory ACL semantics.
windows-sddl turns a nTSecurityDescriptor blob into
ACEs. This crate answers the next question: what can the trustee actually do with it?
An ACE carrying WRITE_PROP plus object GUID 5b47d60f-… is not “write property” — it
is ControlPrimitive::AddKeyCredential, i.e. Shadow Credentials, i.e. account takeover
without touching the password.
use ad_acl::{grants, ControlPrimitive};
let sd = windows_sddl::parse(&raw_nt_security_descriptor).unwrap();
for g in grants(&sd) {
if g.primitive == ControlPrimitive::DcsyncGetChangesAll {
println!("{} can DCSync — {}", g.trustee, g.primitive.mitigation());
}
}Forest-specific attributes (LAPS, gMSA, dMSA) have per-forest schemaIDGUIDs and are
resolved at runtime — see SchemaMap and grants_with.
Only allow ACEs are interpreted; deny ACEs are skipped rather than subtracted, so the output is an over-approximation of effective access. That matches how attack-path tools reason (a deny ACE that is ordered after an allow does not remove the primitive), but it is not an effective-permissions engine.
Modules§
- catalog
- Fixed, forest-independent GUIDs that appear in AD object ACEs.
- names
- Attribute / class names this crate reacts to when they are present in the map.
Structs§
- Grant
- One trustee holding one primitive over the object the descriptor belongs to.
- Schema
Map lDAPDisplayName⇄schemaIDGUID, case-insensitive by name.
Enums§
- Control
Primitive - A concrete thing a trustee can do to an object, derived from one ACE.
- Source
- Where a grant came from.
Functions§
- classify
- Every primitive one allow-ACE grants. Deny ACEs yield nothing.
- classify_
with classify, additionally resolving forest-specific attributes throughschema.- grants
- Every grant a descriptor hands out: the owner, plus one entry per allow-ACE primitive.
- grants_
with grants, resolving forest-specific attributes throughschema.- is_
dcsync - True if the set of primitives held over the domain head amounts to DCSync.