Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SDDL Parsing and Generation

The Security Descriptor Definition Language (SDDL) is the standard text format for Windows security descriptors: O:ownerG:groupD:dacl_flags(ACEs)S:sacl_flags(ACEs).

Parsing

#![allow(unused)]
fn main() {
use win_sd::{parse, SddlParser, Sid, AccessMask};

let sddl = "O:BAG:SYD:(D;;GA;;;AN)(A;;FA;;;BA)(A;;FR;;;WD)";
let sd = parse::<SddlParser>(sddl).unwrap();

assert_eq!(sd.owner(), Some(&Sid::administrators()));
assert_eq!(sd.group(), Some(&Sid::local_system()));
assert_eq!(sd.dacl().unwrap().ace_count(), 3);
}

Generating

#![allow(unused)]
fn main() {
use win_sd::{generate, SddlGenerator, SecurityDescriptorBuilder, AccessMask, Sid};

let sd = SecurityDescriptorBuilder::new()
    .owner(Sid::administrators())
    .group(Sid::local_system())
    .allow(Sid::everyone(), AccessMask::FILE_GENERIC_READ)
    .build();

let sddl = generate::<SddlGenerator>(&sd).unwrap();
assert_eq!(sddl, "O:BAG:SYD:(A;;FR;;;WD)");
}

SID aliases

Well-known SIDs are represented by two-letter aliases:

AliasSIDName
WDS-1-1-0Everyone
BAS-1-5-32-544BUILTIN\Administrators
BUS-1-5-32-545BUILTIN\Users
SYS-1-5-18LOCAL SYSTEM
ANS-1-5-7ANONYMOUS LOGON
AUS-1-5-11Authenticated Users
COS-1-3-0Creator Owner
LWS-1-16-4096Low Integrity
MES-1-16-8192Medium Integrity
HIS-1-16-12288High Integrity
SIS-1-16-16384System Integrity

BUILTIN and other well-known SIDs

AliasSIDName
BGS-1-5-32-546BUILTIN\Guests
LSS-1-5-19LOCAL SERVICE
NSS-1-5-20NETWORK SERVICE
CGS-1-3-1Creator Group
PSS-1-5-10Principal Self
EDS-1-5-9Enterprise DCs
OWS-1-3-4Owner Rights
IUS-1-5-4Interactive
NUS-1-5-5Network
SUS-1-5-6Service
RCS-1-5-12Restricted Code
WRS-1-5-33Write Restricted
NOS-1-5-32-556Network Configuration Operators
BOS-1-5-32-551Backup Operators
SOS-1-5-32-549Server Operators
POS-1-5-32-550Print Operators
AOS-1-5-32-548Account Operators
PUS-1-5-32-547Power Users
RES-1-5-32-552Replicator
RSS-1-5-32-553RAS and IAS Servers
RUS-1-5-32-554Pre-W2K Compatible
RDS-1-5-32-555Remote Desktop Users
MUS-1-5-32-558Performance Monitor Users
LUS-1-5-32-559Performance Log Users
ISS-1-5-32-568IIS_IUSRS
CYS-1-5-32-569Crypto Operators
CDS-1-5-32-574Certificate Service DCOM Access
RAS-1-5-32-575RDS Remote Access Servers
ESS-1-5-32-576RDS Endpoint Servers
RMS-1-5-32-577RDS Management Servers
ERS-1-5-32-573Event Log Readers
HAS-1-5-32-578Hyper-V Admins
AAS-1-5-32-579Access Control Assistance
ACS-1-15-2-1All Application Packages

Domain-relative aliases

Domain-relative aliases (DA, DU, DD, etc.) require a DomainContext:

#![allow(unused)]
fn main() {
use win_sd::{parse_with_domain, generate_with_domain, DomainContext, Sid};

let domain = DomainContext::new(
    Sid::from_authority(5, vec![21, 100, 200, 300]),
);

// DA resolves to S-1-5-21-100-200-300-512 (Domain Admins)
let sd = parse_with_domain("O:DAG:DUD:(A;;FA;;;DA)", &domain).unwrap();
let owner = sd.owner().unwrap();
assert_eq!(owner.rid(), Some(512));

// Generate uses aliases when a domain context is provided
let sddl = generate_with_domain(&sd, &domain).unwrap();
assert!(sddl.contains("DA"));
}
AliasRIDName
LA500Local Administrator
LG501Local Guest
DA512Domain Admins
DU513Domain Users
DG514Domain Guests
DC515Domain Computers
DD516Domain Controllers
CA517Cert Publishers
SA518Schema Admins
EA519Enterprise Admins
PA520Group Policy Creator Owners
RO521Read-Only Domain Controllers
CN522Cloneable Domain Controllers
AP525Protected Users
KA526Key Admins
EK527Enterprise Key Admins

Rights aliases

Access mask values use two-letter codes:

CodeValueMeaning
GA0x10000000GENERIC_ALL
GR0x80000000GENERIC_READ
GW0x40000000GENERIC_WRITE
GX0x20000000GENERIC_EXECUTE
FA0x001F01FFFILE_ALL_ACCESS
FR0x00120089FILE_GENERIC_READ
FW0x00120116FILE_GENERIC_WRITE
FX0x001200A0FILE_GENERIC_EXECUTE
KA0x000F003FKEY_ALL_ACCESS
KR0x00020019KEY_READ
KW0x00020006KEY_WRITE
KX0x00020019KEY_EXECUTE
CC0x00000001CREATE_CHILD (AD)
DC0x00000002DELETE_CHILD (AD)
LC0x00000004LIST_CHILDREN (AD)
SW0x00000008SELF_WRITE (AD)
RP0x00000010READ_PROP (AD)
WP0x00000020WRITE_PROP (AD)
DT0x00000040DELETE_TREE (AD)
LO0x00000080LIST_OBJECT (AD)
CR0x00000100CONTROL_ACCESS (AD)
RC0x00020000READ_CONTROL
SD0x00010000DELETE
WD0x00040000WRITE_DAC
WO0x00080000WRITE_OWNER
NW0x01NO_WRITE_UP (integrity)
NR0x02NO_READ_UP (integrity)
NX0x04NO_EXECUTE_UP (integrity)

ACL flags (the flags string right after D:/S:, before the first ACE): P (protected), AR (auto-inherit request), AI (auto-inherited).

Hex literals are also accepted: 0x001F01FF.

ACE flags

The second semicolon-separated field of an ACE string (e.g. the OICI in (A;OICI;GA;;;BA)) is a concatenation of two-letter inheritance/audit flag codes, corresponding to the AceFlags bits described in ACEs and Security Descriptors:

CodeFlagMeaning
OIOBJECT_INHERITNon-container children inherit
CICONTAINER_INHERITContainer children inherit
NPNO_PROPAGATE_INHERITStop propagation to grandchildren
IOINHERIT_ONLYDoes not apply to this object
IDINHERITED_ACEWas inherited from parent
SASUCCESSFUL_ACCESSAudit on success (SACL)
FAFAILED_ACCESSAudit on failure (SACL)

These codes may be freely combined, e.g. OICI sets both OBJECT_INHERIT and CONTAINER_INHERIT, and SAFA audits both successful and failed access attempts.