Larry Osterman's WebLog

Confessions of an Old Fogey
Blog - Title

What is this thing called, SID?

What is this thing called, SID?

Rate This
  • Comments 24

One of the core data structures in the NT security infrastructure is the security identifier, or SID.

NT uses two data types to represent the SID, a PSID, which is just an alias for VOID *, and a SID, which is a more complicated structure (declared in winnt.h).

The contents of a SID can actually be rather fascinating.  Here’s the basic SID structure:

typedef struct _SID {
   BYTE  Revision;
   BYTE  SubAuthorityCount;
   SID_IDENTIFIER_AUTHORITY IdentifierAuthority;

Not a lot there, but some fascinating stuff none the less.  First let’s consider the Revision.  That’s always set to 1, for existing versions of NT.  There may be a future version of NT that defines other values, but not yet.

The next interesting field in a version 1 SID is the IdentifierAuthority.  The IdentifierAuthority is an array of 6 bytes, which describes which system “owns” the SID.  Essentially the IdentifierAuthority defines the meaning of the fields in the SubAuthority array, which is an array of DWORDs that is SubAuthorityCount in length (SubAuthorityCount can be any number between 1 and SID_MAX_SUB_AUTHORITIES (15 currently).  NT’s access check logic and SID validation logic treats the sub authority array as an opaque data structure, which can allow a resource manager to define their own semantics for the contents of the SubAuthority (this is strongly NOT recommended btw).

The “good stuff” in the SID (the stuff that makes a SID unique) lives in the SubAuthority array in the SID.  Each entry in the SubAuthority array is known as a RID (for Relative ID), more on this later. 

NT defines a string representation of the SID by constructing a string S-<Revision>-<IdentifierAuthority>-<SubAuthority0>-<SubAuthority1>-…-<SubAuthority<SubAuthorityCount>>.  For the purposes of constructing a string sid, the IdentifierAuthority is treated as a 48bit number.  You can convert between a binary SID and back by using the ConvertSidToStringSid and ConvertStringSidToSid APIs.

NT defines 6 IdentifierAuthorities, they are:

#define SECURITY_NULL_SID_AUTHORITY         {0,0,0,0,0,0}
#define SECURITY_WORLD_SID_AUTHORITY        {0,0,0,0,0,1}
#define SECURITY_LOCAL_SID_AUTHORITY        {0,0,0,0,0,2}
#define SECURITY_CREATOR_SID_AUTHORITY      {0,0,0,0,0,3}
#define SECURITY_NON_UNIQUE_AUTHORITY       {0,0,0,0,0,4}
#define SECURITY_NT_AUTHORITY               {0,0,0,0,0,5}

Taken in turn, they are:

·         SECURITY_NULL_SID_AUTHORITY: The “NULL” Sid authority is used to hold the “null” account SID, or S-1-0-0. 

·         SECURITY_WORLD_SID_AUTHORITY: The “World” Sid authority is used for the “Everyone” group, there’s only one SID in that group, S-1-1-0.

·         SECURITY_LOCAL_SID_AUTHORITY: The “Local” Sid authority is used for the “Local” group, again, there’s only one SID in that group, S-1-2-0.

·         SECURITY_CREATOR_SID_AUTHORITY: This Sid authority is responsible for the CREATOR_OWNER, CREATOR_GROUP, CREATOR_OWNER_SERVER and CREATOR_GROUP_SERVER well known SIDs, S-1-3-0, S-1-3-1, S-1-3-2 and S-1-3-3.
The SIDs under the CREATOR_SID_AUTHORITY are sort-of “meta-SIDs”.  Basically, when ACL inheritance is run, any ACEs that are owned by the SECURITY_CREATOR_SID_AUTHORITY are replaced (duplicated if the ACEs are inheritable) by ACEs that reflect the relevant principal that is performing the inheritance.  So a CREATOR_OWNER ACE will be replaced by the owner SID from the token of the user that’s performing the inheritance.


·         SECURITY_RESOURCE_MANAGER_AUTHORITY:  The “resource manager” authority is a catch-all that’s used for 3rd party resource managers. 

·         SECURITY_NT_AUTHORITY: The big kahuna.  This describes accounts that are managed by the NT security subsystem.

There are literally dozens of well known SIDs under the SECURITY_NT_AUTHORITY sub authority.  They range from NETWORK (S-1-5-2), a group added to the token of all users connected to the machine via a network, to S-1-5-5-X-Y, which is the SID for all authenticated NT users (X and Y will be replaced by values specific to your per-machine logon instance).

Each domain controller allocates RIDs for that domain, each principal created gets its own RID.  In general, for NT principals, the SID for each user in a domain will be identical, except for the last RID (that’s why it’s a “relative” ID – the value in SubAuthority[n] is relative to SubAuthority[n-1]).  In Windows NT (before Win2000), RID allocation was trivial – user accounts could only be created at the primary domain controller (there was only one  PDC, with multiple backup domain controllers) so the PDC could manage the list of RIDs that was allocated easily.  For Windows 2000 and later, user accounts can be created on any domain controller, so the RID allocation algorithm is somewhat more complicated.

Clearly a great deal of effort is made to ensure uniqueness of SIDs, if SIDs did not uniquely identify a user, then “bad things” would happen.

If you look in WINNT.H, you can find definitions for many of the RIDs for the builtin NT accounts, to form a SID for one of those accounts, you’d initialize a SID with the SECURITY_NT_AUTHORITY, and set the first SubAuthority to the RID of the desired account.  The good news is that because this is an extremely tedious process, the NT security guys defined an API (in Windows XP and later) named CreateWellKnownSid which can be used to create any of the “standard” SIDs.

Tomorrow: Some fun things you can do with a SID.


  • I'm using pview from Platform SDK (Program Files\Microsoft SDK\Bin\winnt). It is definitely more recent than NT4 - in fact, the version number is 5.2.3790.0 which is Win2K3.

    NT4 version probably doesn't show restricting SIDs anyway as I believe this feature was introduced in Win2K.

    I believe that the reason why "protect my computer" feature doesn't get more coverage is because it's not really secure. For example, I don't think it can prevent malicious code from sending window messages to other programs running as the user (a "shatter"-style attack).

    I still occasionally run IE in restricted mode but I definitely don't count on it as my only protection.
  • Apparantly as been promising to talk about this for a while.

    I sent him a message to remind him.

  • The best published description of restricted tokens that I've read is in Keith Brown's "Programming Windows Security". He doesn't cover the "protect my computer" option, though, because his book predated Windows XP, which is where that option was introduced. Solomon and Russinovich's upcoming "Windows Internals" book will have great info on it.

    I am planning a post on the "protect my computer" option, focusing more on the effects perceived by the end user than about how the underlying access checks actually work. Real Soon Now.

    It takes more than a couple of paragraphs to accurately describe how an access check is performed against a non-restricted SID, when you take into account deny-only and disabled SIDs. The important part is that an access check compares the union of the user's identity and the list of groups the user is a member of against the ACL of interest. With a restricted token, the access check performs two passes. The first compares the union of the user's identity and the groups against the ACL; the second test compares only the SIDs in the token's "restricting SIDs" list against the ACL. The result of the access check is essentially the intersection of the results. If the first pass grants you "full control" and the second pass grants you "read only", then you get "read only". If either test fails to grant you any access, you get no access. Although it is legal for the restricting SIDs list to include the user account's SID, the restricted token created by "protect my computer" does not. Therefore, if you're running with a "protect my computer" restricted token, you do not get access to anything that is ACLed for you only. The object needs to grant access to something else that allows the second pass to succeed. The reason that most of HKCU gives you read-only access is because "RESTRICTED" is granted read-only. (Like the example above: first pass gives you "full", second pass gives you "read", you get "read".) The NTFS permissions on your profile folder hierarchy does not grant RESTRICTED anything, so you can't access your profile folder when running with a "protect my computer" restricted token. (The reason you CAN access HKCU, which lives in a file in your profile, is because you're not accessing it directly through NTFS - if I'm not mistaken your HKCU hive is loaded by code running as System.)

    As Pavel indicated, "restricting SIDs" and "deny-only SIDs" are completely different. "Restricting SIDs" are really misnamed, since the more SIDs you add to the list in a restricted token, the more you're granting access, not denying access.

    I'll try to get that thing posted - sorry for the delay!
  • It's posted.
  • What does it mean to
  • Security Developer Center: Columns: Browsing the Web and Reading E-mail Safely as an Administrator Part 1 ">Part 2 I got the heads up to this pair of MSDN articles by Microsoft Security Engineering Michael Howard off the activedir list and...
  • It's a complicated mix.
  • Inherited permissions are established at creation.
Page 2 of 2 (24 items) 12