Skip to content

Fix SDDL SID alias table missing ten aliases Windows resolves (Fixes #133) - #136

Merged
p0dalirius merged 1 commit into
mainfrom
bugfix-sddl-sid-alias-table
Jul 29, 2026
Merged

Fix SDDL SID alias table missing ten aliases Windows resolves (Fixes #133)#136
p0dalirius merged 1 commit into
mainfrom
bugfix-sddl-sid-alias-table

Conversation

@p0dalirius

Copy link
Copy Markdown
Collaborator

Linked Issue

Closes #133

Root Cause

SDDLToSID was transcribed from the MS-DTYP 2.5.1.1 sid-token table and three of its rows were omitted: AC, UD and WR. Because the map is the only alias source for both the ACE trustee path and the SID(...) operand path inside a conditional expression, any SDDL string using one of them failed to parse outright. AC (ALL APPLICATION PACKAGES) is present in the default DACL of many Windows files, registry keys and directory objects, so this affected descriptors collected from real systems rather than only hand-written ones.

Separately, the MS-DTYP table itself is out of date relative to Windows: seven aliases that the OS resolves have no row in it, so a map faithful to the spec is still incomplete against real input.

Fix Description

Ten entries added to SDDLToSID, grouped with the existing comment structure (well-known, BUILTIN, domain-relative), plus a new group for the application-package and asserted-identity authorities.

The three MS-DTYP omissions are straightforward. The seven undocumented values were not guessed: they were read out of the alias table Windows itself walks — sechost.dll (Windows Server 2025), .data RVA 0x99f30, 67 entries of stride 0x68, with the alias at record +0x02, the RID at +0x18 and a SID-prefix template selector at +0x1c. Before trusting that decode on the unknown aliases it was validated against 19 aliases whose SIDs are independently known (WD, SY, BA, AC, AU, AN, IU, LS, NS, CO, CG, OW, HI, ME, SI, LW, DA, SA, EA), with zero mismatches.

Domain-relative additions follow the placeholder-domain convention already used in this map (S-1-5-21-0-0-0-<rid>) rather than introducing a second representation.

One deliberate non-change: on Windows, EK resolves against the forest root domain, not the local domain (its table entry uses a different template selector, the same one as SA, EA and RO). That distinction cannot be represented while the domain portion is a placeholder, so it is recorded in a comment instead of encoded. It matters for any future change that resolves a real domain SID, because expanding a forest-root alias against the local domain yields a different, valid-looking principal instead of an error — a wrong answer rather than a failure.

How Verified

Runtime, before the fix — each alias inside a conditional expression:

SID(AC) ... REJECT  unknown SID "AC" in conditional expression
SID(UD) ... REJECT  unknown SID "UD" in conditional expression
SID(WR) ... REJECT  unknown SID "WR" in conditional expression
SID(AP), SID(KA), SID(EK), SID(AS), SID(SS), SID(HO), SID(SH)  — all REJECT

Runtime, after the fix — all ten resolve, in both operand and trustee position:

SID(AC)  accept -> (Member_of {SID(S-1-15-2-1)})
SID(UD)  accept -> (Member_of {SID(S-1-5-84-0-0-0-0-0)})
SID(WR)  accept -> (Member_of {SID(S-1-5-33)})
SID(AS)  accept -> (Member_of {SID(S-1-18-1)})
SID(HO)  accept -> (Member_of {SID(S-1-5-32-584)})
...
trustee  accept -> D:P(A;;FA;;;AC)(A;;FA;;;HO)

The trustee line also shows the derived reverse map resolving the new SIDs back to their aliases.

Repository suitego test ./... green; gofmt -l clean on both changed files; go vet reports nothing.

Test Coverage

Added — in sddl/sid/sid_test.go:

  • TestSDDLAliases_MSDTYPCoverage — asserts every one of the 61 sid-token entries from MS-DTYP 2.5.1.1 resolves. This is the regression guard for the actual bug and fails on AC, UD, WR without the fix.
  • TestSDDLAliases_WindowsExtras — pins all ten added aliases to their exact SIDs and checks the reverse mapping round-trips.
  • TestSDDLAliases_NoDuplicateSIDs — guards the derived SIDToSDDL: two aliases sharing a SID string would make the reverse map depend on Go map iteration order. It passes today and prevents a future addition from silently introducing that nondeterminism.

Scope of Change

  • Files changed: sddl/sid/sid.go, sddl/sid/sid_test.go
  • Submodule pointer updated: no
  • Behavioral changes outside the bug fix: none. Purely additive to a lookup table; no existing entry was altered and no code path changed.

Risk and Rollout

Additive only — the change can make previously failing input parse, and cannot change the result of input that already parsed. Safe to merge without staged rollout.

Notes

sddl/sddl_functions_test.go is flagged by gofmt -l on main already; it is untouched here to keep the diff to the fix.

Two properties of the Windows alias table found while sourcing these values are recorded in #133 and not acted on here: CY is duplicated in that table (two identical entries), and CN is absent from the 67-entry table, appearing only in a separate 15-entry domain-RID table at RVA 0x99910. CN is already present and correct in this map.

Filed alongside this from the same investigation: #134 (SDDL ACE types TL/FL unusable) and #135 (the two undocumented conditional-expression tokens 0xfc/@TOKEN. and 0xa3/&).

…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.
@p0dalirius
p0dalirius merged commit d5529f3 into main Jul 29, 2026
5 checks passed
@p0dalirius
p0dalirius deleted the bugfix-sddl-sid-alias-table branch July 29, 2026 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant