Skip to content

Commit 514dbdf

Browse files
committed
Fix SDDL SID alias table missing ten aliases Windows resolves (Fixes #133)
SDDLToSID was populated from the MS-DTYP 2.5.1.1 sid-token table and was missing three of its rows, so SDDL using them failed to parse in both ACE trustee position and inside SID(...) in a conditional expression: AC S-1-15-2-1 All Application Packages UD S-1-5-84-0-0-0-0-0 User Mode Drivers WR S-1-5-33 Write Restricted Code AC in particular appears in the default DACL of many Windows objects, so descriptors collected from real systems failed rather than degrading. Seven further aliases are resolved by Windows but absent from the MS-DTYP table. Their values were read from the 67-entry alias table in sechost.dll (Windows Server 2025) at .data RVA 0x99f30, whose record layout is alias at +0x02, RID at +0x18 and a SID-prefix template selector at +0x1c. The template decode was validated against 19 aliases with independently known SIDs before being trusted on these: AS S-1-18-1 Authentication Authority Asserted Identity SS S-1-18-2 Service Asserted Identity HO S-1-5-32-584 BUILTIN\\User Mode Hardware Operators SH S-1-5-32-585 BUILTIN\\OpenSSH Users AP S-1-5-21-0-0-0-525 Protected Users KA S-1-5-21-0-0-0-526 Key Admins EK S-1-5-21-0-0-0-527 Enterprise Key Admins Domain-relative entries follow the existing placeholder-domain convention in this map. EK resolves against the forest root domain on Windows rather than the local domain; that distinction is not representable while the domain is a placeholder and is noted in the map comment.
1 parent d0fb571 commit 514dbdf

2 files changed

Lines changed: 93 additions & 15 deletions

File tree

sddl/sid/sid.go

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,28 @@ package sid
55

66
var SDDLToSID = map[string]string{
77
// Well-known SIDs
8-
"WD": "S-1-1-0", // Everyone
9-
"CO": "S-1-3-0", // Creator Owner
10-
"CG": "S-1-3-1", // Creator Group
11-
"OW": "S-1-3-4", // Owner Rights
12-
"NU": "S-1-5-2", // Network
13-
"IU": "S-1-5-4", // Interactive
14-
"SU": "S-1-5-6", // Service
15-
"AN": "S-1-5-7", // Anonymous
16-
"ED": "S-1-5-9", // Enterprise Domain Controllers
17-
"PS": "S-1-5-10", // Principal Self
18-
"AU": "S-1-5-11", // Authenticated Users
19-
"RC": "S-1-5-12", // Restricted Code
20-
"SY": "S-1-5-18", // Local System
21-
"LS": "S-1-5-19", // Local Service
22-
"NS": "S-1-5-20", // Network Service
8+
"WD": "S-1-1-0", // Everyone
9+
"CO": "S-1-3-0", // Creator Owner
10+
"CG": "S-1-3-1", // Creator Group
11+
"OW": "S-1-3-4", // Owner Rights
12+
"NU": "S-1-5-2", // Network
13+
"IU": "S-1-5-4", // Interactive
14+
"SU": "S-1-5-6", // Service
15+
"AN": "S-1-5-7", // Anonymous
16+
"ED": "S-1-5-9", // Enterprise Domain Controllers
17+
"PS": "S-1-5-10", // Principal Self
18+
"AU": "S-1-5-11", // Authenticated Users
19+
"RC": "S-1-5-12", // Restricted Code
20+
"SY": "S-1-5-18", // Local System
21+
"LS": "S-1-5-19", // Local Service
22+
"NS": "S-1-5-20", // Network Service
23+
"WR": "S-1-5-33", // Write Restricted Code
24+
"UD": "S-1-5-84-0-0-0-0-0", // User Mode Drivers
25+
26+
// Application-package and asserted-identity authorities
27+
"AC": "S-1-15-2-1", // All Application Packages
28+
"AS": "S-1-18-1", // Authentication Authority Asserted Identity
29+
"SS": "S-1-18-2", // Service Asserted Identity
2330

2431
// BUILTIN groups
2532
"BA": "S-1-5-32-544", // BUILTIN\Administrators
@@ -46,6 +53,8 @@ var SDDLToSID = map[string]string{
4653
"HA": "S-1-5-32-578", // BUILTIN\Hyper-V Administrators
4754
"AA": "S-1-5-32-579", // BUILTIN\Access Control Assistance Operators
4855
"RM": "S-1-5-32-580", // BUILTIN\Remote Management Users
56+
"HO": "S-1-5-32-584", // BUILTIN\User Mode Hardware Operators
57+
"SH": "S-1-5-32-585", // BUILTIN\OpenSSH Users
4958

5059
// Domain-relative SIDs (using placeholder domain 0-0-0)
5160
"LA": "S-1-5-21-0-0-0-500", // Domain Administrator Account
@@ -62,6 +71,9 @@ var SDDLToSID = map[string]string{
6271
"RO": "S-1-5-21-0-0-0-498", // Enterprise Read-Only Domain Controllers (SDDL_ENTERPRISE_RO_DCs)
6372
"CN": "S-1-5-21-0-0-0-522", // Cloneable Domain Controllers
6473
"RS": "S-1-5-21-0-0-0-553", // RAS Servers Group
74+
"AP": "S-1-5-21-0-0-0-525", // Protected Users
75+
"KA": "S-1-5-21-0-0-0-526", // Key Admins
76+
"EK": "S-1-5-21-0-0-0-527", // Enterprise Key Admins (forest root domain)
6577

6678
// Mandatory integrity levels
6779
"LW": "S-1-16-4096", // Low Integrity Level

sddl/sid/sid_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,69 @@ func TestSDDLAlias_RO(t *testing.T) {
3232
t.Errorf("S-1-5-21-0-0-0-521 must not map to \"RO\" (it is the non-aliased Read-Only Domain Controllers group)")
3333
}
3434
}
35+
36+
// msdtypSidTokens is the complete sid-token list from MS-DTYP 2.5.1.1. Every one
37+
// of these MUST resolve; "AC", "UD" and "WR" were previously absent.
38+
var msdtypSidTokens = []string{
39+
"DA", "DG", "DU", "ED", "DD", "DC", "BA", "BG", "BU", "LA", "LG", "AO", "BO",
40+
"PO", "SO", "AU", "PS", "CO", "CG", "SY", "PU", "WD", "RE", "IU", "NU", "SU",
41+
"RC", "WR", "AN", "SA", "CA", "RS", "EA", "PA", "RU", "LS", "NS", "RD", "NO",
42+
"MU", "LU", "IS", "CY", "OW", "ER", "RO", "CD", "AC", "RA", "ES", "MS", "UD",
43+
"HA", "CN", "AA", "RM", "LW", "ME", "MP", "HI", "SI",
44+
}
45+
46+
// TestSDDLAliases_MSDTYPCoverage checks that every alias in the MS-DTYP
47+
// sid-token table resolves to a SID.
48+
func TestSDDLAliases_MSDTYPCoverage(t *testing.T) {
49+
for _, alias := range msdtypSidTokens {
50+
if got, ok := SDDLToSID[alias]; !ok || got == "" {
51+
t.Errorf("SDDLToSID[%q] missing; MS-DTYP 2.5.1.1 defines it as a sid-token", alias)
52+
}
53+
}
54+
}
55+
56+
// TestSDDLAliases_WindowsExtras pins the aliases Windows resolves that the
57+
// MS-DTYP sid-token table does not list. Values were read from the alias table
58+
// in sechost.dll (Windows Server 2025), .data RVA 0x99f30.
59+
func TestSDDLAliases_WindowsExtras(t *testing.T) {
60+
want := map[string]string{
61+
// Documented by MS-DTYP but previously missing here.
62+
"AC": "S-1-15-2-1",
63+
"UD": "S-1-5-84-0-0-0-0-0",
64+
"WR": "S-1-5-33",
65+
// Not in the MS-DTYP sid-token table.
66+
"AS": "S-1-18-1",
67+
"SS": "S-1-18-2",
68+
"HO": "S-1-5-32-584",
69+
"SH": "S-1-5-32-585",
70+
"AP": "S-1-5-21-0-0-0-525",
71+
"KA": "S-1-5-21-0-0-0-526",
72+
"EK": "S-1-5-21-0-0-0-527",
73+
}
74+
for alias, wantSID := range want {
75+
got, ok := SDDLToSID[alias]
76+
if !ok {
77+
t.Errorf("SDDLToSID[%q] missing, want %q", alias, wantSID)
78+
continue
79+
}
80+
if got != wantSID {
81+
t.Errorf("SDDLToSID[%q] = %q, want %q", alias, got, wantSID)
82+
}
83+
if back := SIDToSDDL[wantSID]; back != alias {
84+
t.Errorf("SIDToSDDL[%q] = %q, want %q", wantSID, back, alias)
85+
}
86+
}
87+
}
88+
89+
// TestSDDLAliases_NoDuplicateSIDs guards the derived reverse map: two aliases
90+
// sharing a SID would make SIDToSDDL depend on map iteration order.
91+
func TestSDDLAliases_NoDuplicateSIDs(t *testing.T) {
92+
seen := make(map[string]string, len(SDDLToSID))
93+
for alias, sidStr := range SDDLToSID {
94+
if other, dup := seen[sidStr]; dup {
95+
t.Errorf("aliases %q and %q both map to %q; SIDToSDDL[%q] is nondeterministic",
96+
other, alias, sidStr, sidStr)
97+
}
98+
seen[sidStr] = alias
99+
}
100+
}

0 commit comments

Comments
 (0)