Inside Kerberos – 2: SIDs
In Part 1 we set the scene in regards to how Kerberos works at a high level, so let’s now get down and dirty with Security Identifiers (SIDs)
What is a Security Identifier (SID)?
From MSDN: “A security identifier (SID) is a unique value of variable length used to identify a trustee. Each account has a unique SID issued by an authority, such as a Windows domain controller, and stored in a security database. Each time a user logs on, the system retrieves the SID for that user from the database and places it in the access token for that user. The system uses the SID in the access token to identify the user in all subsequent interactions with Windows security. When a SID has been used as the unique identifier for a user or group, it cannot ever be used again to identify another user or group.”
SIDs were created for the Windows NT Operating System to help identify a user, group, computer, etc. to make it easier to store permissions or rights. SIDs are immutable (although as we’ll see they can be added to objects in other domains or forests) via SID History.
What does a SID look like?
The common way to write a SID is in the form S-1-5-21-xxx, or S-R-I-S… Where the first S is a literal to identify that this is a SID, the R is the revision number, and so far there has only been revision 1, the I is the identifier authority, and then the last S is the subauthority which can theoretically be repeated up to 15 times, although for Windows it’s repeated only 5 times. So for a standard Windows computer or domain SID it would look like S-1-5-21-aaaaaaa-bbbbbbb-ccccccc-ddddddd. Internally within Windows a SID is stored as a variable array of 32 bit integers, typically for a total of 28 bytes. The first integer stores the revision, the count of number of sub-authorities, and the identifier authority. This is then followed by however many sub-authorities are in this SID. These sub-authority integers are stored in little-endian format meaning that the least significant byte is stored first, and explains why we have to do a complex transformation to get from the integers to the more common s-1-5-21-* format.
Where does the 5 come from in the third part?
The Identifier Authorities are set by Microsoft and the most recent additional is number 12 to indicate Azure Active Directory. The common ones include:
- 0: Null SID
- 1: World SID
- 2: Local SID
- 3: Creator SID
- 4: Non Unique SID
- 5: Windows NT SID
- 9: Resource Manager SID
- 11: Microsoft Account Authority SID
- 12: Azure Active Directory SID
- 16: Mandatory Label
Why is the first sub-authority set to 21 in the Windows NT SID?
The first sub-authority shows the purpose of the SID, and there are a whole host of pre-defined choices. 21 just happens to be the one for ‘NT NON UNIQUE’, i.e. it’s a domain SID and you need the next 3 sub-authorities to see the domain we’re in before you can use that plus the last sub-authority to guarantee uniqueness.
- 4: INTERACTIVE
- 9: Domain Controllers
- 11: Authenticated Users
- 17: NT SERVICE
- 21: NT AUTHORITY
- 32: BUILTIN
How are the three computer sub-authorities calculated?
I can’t actually find anything that describes exactly how the three computer parts of a SID are generated. They used to say that the SID for a computer needed to be unique, however in 2009 Mark Russinovich announced the retirement of the Sysinternals tool newsid, saying that it was not needed and that a duplicate machine SID introduced no problems.
Now to be very clear. Mark is talking here about Computer SIDs. Yes the Computer SID of the first Domain Controller in a Domain becomes the Domain SID, however Mark is NOT talking about that. A Computer SID also adds a last sub-authority just like the Domain SID which we generally call a Relative ID (RID) (although strictly speaking a RID is any sub-authority field since they’re all relative to the pieces before it). The RID is used to identify any security principal on the computer (or in the domain in case of a domain SID). The key thing to remember is that when a machine joins the domain then its SID within the domain takes on the Domain SID plus a RID as handed out by a Domain Controller. The Computer SID remains on the computer and is still used locally but never traverses that local boundary.
How are SIDs different from GUIDs and why have both?
A GUID is a Globally Unique ID and is a 128 bit value, and it stays with the AD object even if it is moved between domains inside a forest boundary. It is used within the Windows OS to identify objects but they weren’t used back in the Windows NT days, which only used SIDs, and so for backward compatibility SIDs have stayed with us (and they serve us pretty well really) I didn’t realise before that a GUID is based on RFC 4122 which describes in detail how a GUID is generated. Suffices to say that every computer can generate around 16 guaranteed unique GUIDs every 100 nanoseconds… That’s a lot of GUIDs… You can see in Windows that it uses algorithm 4 now which was improved as people found out that the node element of a GUID was their MAC address and so could e traced back to a computer… To verify the version number get a guid and notice that the 13th character in the standard string representation is always 4
How can the Relative ID (RID) be unique in a domain?
This of course used to be easy in Windows NT days, since the Primary Domain Controller (PDC) was the only Domain Controller (DC) that could create anything, so the RIDs were controlled by one computer. In Windows 2000 the DCs became multi-master, meaning that they can all create/update/delete objects at the same time! So how can a RID be unique then?
One of the DCs holds the Flexible Single Master Operation (FSMO) role of RID Master. i.e. the one DC that tells other DCs what they can and can’t issue. Other DCs request a block of RIDs (500 by default) from the RID Master holder to allow those DCs to create new objects atomically. Once they have consumed half of that block then they will request a standby block from the RID Master holder.
How many RIDs can there be in a domain?
A RID is a sub-authority in a SID, which we said is a 32bit integer. So that’s a total of 4 billion numbers, however only 30 bits are used making the total around 1 billion RIDs in a domain. This may seem like a lot, but loads of factors go into SID usage, including the occasional Microsoft bug (Windows Server 2008 R2 consumes a pool every 30 seconds) Funny enough after that bug Windows Server 2012 added a safety feature called the RID ceiling which stops issuing any further RIDs once the Global RID Pool gets to 90% utilized. If that happens event id 16657 will be written to the Directory-Services-SAM event log and no further RIDs will be issued until an administrator manually removes the ceiling (be sure you understand why the ceiling was reached though!)
What happens when the Global RID Pool has been exhausted?
If the Global RID pool is depleted then there can be no additional new objects in the domain, and yes that is as bad as it sounds… You can enable bit 31 in case of emergency but that truly is for emergency only as applications (including Domain Controllers pre Windows Server 2012) may not be compatible with these extra large RIDs. You are really looking at needing a Domain Migration at this point.
How can I monitor for RID Pool depletion?
Windows Server 2012 added RID consumption information to the Directory-Services-SAM log by way of event 16658. This is written every time the RID pool is 10% more utilized than the last time it wrote the log entry. i.e. the first time it’s written at 10%, the next time it is 10% of the remaining 90%, then 10% of the remaining 81%, etc. In other words the events will become more prevalent the closer you get to depletion.
How will a domain migration help me with RID depletion?
When you migrate objects to a new domain you of course only migrate objects that are still there (i.e. anything deleted isn’t migrated) SO this consolidates the RIDs used to a much smaller number, which allows you to grow again. Of course you have lots of rights and resources relying on the SIDs from the old domain… luckily the sidHistory attribute comes to the rescue… which will be discussed in part 3