Inside Kerberos – 3: SIDHistory
In this blog we will be exploring SID History, and it follows on from Part 1 which gave an overview of Kerberos, and Part 2 which was all about SIDs.
The attribute sid-history has been there right since Windows 2000 and is used to store all of the SIDs that an object has had. What? I hear you ask? Surely a SID is immutable!? Yes that’s true a SID is immutable, but in order to support movement of objects between domains there has to be a reference to the old SID for authorization to not break everywhere. The sid-history attribute is what allows this to happen.
How are SIDs added to sid-history?
Adding SIDs to the sid-history attribute is a highly privileged function as you can imagine. However it is safe to assume that pretty much anyone who can get administrative rights on a Domain Controller can also add SIDs to sid-history. For objects moving between domains within a single forest, the SID from the old domain is automatically added to the object in the new domain. For inter-forest migrations the function DsAddSidHistory is typically used directly or indirectly.
How do I prepare for sid-history migration?
Various 3rd party tools undertake sid-history migration as part of their migration tool, and they all have the same baseline requirements:
Source Domain
- Service Account with Administrators or Domain Admins membership
- Empty Domain Local group called NETBIOS$$$, where NETBIOS is the NETBIOS name of the domain
- TcpIpClientSupport has to be enabled on the PDC role holder (even for later Windows Server versions)
- Account Management auditing must be enabled for both Success and Failure on Domain Controllers
- Directory Services Access auditing must be enabled for both Success and Failure on Domain Controllers
Target Domain
- Service Account with Domain Admins membership
- Account Management auditing must be enabled for both Success and Failure on Domain Controllers
- Directory Services Access auditing must be enabled for both Success and Failure on Domain Controllers
Any time the DsAddSidHistory call is made, then in the source domain the user or group whose SIDs are being exfiltrated will be added and removed as a member of the $$$ group and so the auditing ensures that this is traceable.
Can I add any SIDs to any sid-history attribute?
Using the official tools there are rules that are enforced which include:
- The SID can’t be from the local domain
- The SID must come from a compatible object
- User SID can be added to a User
- Domain Local Group SID can be added to a Domain Local Group
- Domain Global/Universal Group SID can be added to a Domain Global/Universal Group SID
- The SID can’t already exist as a SID or sid-history entry on another object
How do I stop SIDs being exfiltrated via dsAddSidHistory?
The easiest way to stop this is to create the $$$ group and add an explicit deny on it for addition and removal of members to anyone. It is of course possible that a hacker notices this and finds a way to remove this restriction, but it’s an easy safe guard to have in place.
How do domains protect themselves from sid-history manipulation?
A domain can be part of a variety of different trust types
- WithinForest: (parent/child and shortcut trusts) trusting domain allows all SIDs
- WithinForest Quarantined: (parent/child trusts that have been explicitly marked as quarantined); trusting domain only allows the Enterprise Domain Controllers SID and any described by the Trusted Domain Object
- CrossForest: (Cross Forest trust that has been explicitly marked as NOT SidFiltered) trusting forest allows all SIDs except those for any domains in its own forest
- CrossForest SidFiltered: (Cross Forest trust); trusting forest allows only SIDs belonging to domains from the trusted forest
- External: (External Domain trust that has been explicitly marked as NOT quarantined) trusting domain allows all SIDs except those for its own domain
- External Quarantined: (External Domain trust) trusting domain allows only SIDs belonging to the trusted domain
- Privileged Identity Management: (PIM trust) trusting domain allows all SIDs
SIDs are categorized into types (see Filtering and Claims Information for all the detail)
- AlwaysFilter: Don’t allow these to cross any trust boundary
- ForestSpecific: Don’t allow these to cross any forest trust boundary nor any quarantined WithinForest trust
- EDC: Enterprise Domain Controllers is filtered out for CrossForest, CrossForest SidFiltered, External, External Quarantined, and PrivilegedIdentityManagement trust boundaries
- DomainSpecific: Don’t allow these to cross and domain trust boundary
- NeverFilter: Never filter these SIDs
By default CrossForest trusts are SidFiltered and External trusts are Quarantined, and you can use netdom to turn that feature off. Migration scenarios often require SIDFiltering/Quarantine to be off so that the injected Sid-History (which is always from another domain/forest) is allowed to cross the trust boundary.
How many SIDs can I add into sid-history?
There is no set limit on the number of entries a sid-history attribute can have, however there are two known limitations. One is the maximum size of the Kerberos ticket of 64 KB and the other is a hard limit inside the Local Security Authority (LSA) of 1024 Group SIDs. Both of these limits will be explored more in the next few parts in the Kerberos series
Let’s move onto looking at Kerberos Tickets