说到安全标识符SID就要先说说安全主体(Security Principals),安全主体是一个能够对它分配权限的对象,例如,用户、组和计算机; 对于每一个Windows 200x域中的安全主体都有一个惟一的安全标识符SID。
那什么是安全标识符SID呢?安全标识符SID是一个值,这个值唯一地标识一个组织内的用户、组、计算机或服务。每一个帐户在被创建时会分配到一个安全标识符,Windows 200x域中通过安全标识符SID来实现访问控制机制。
那么访问控制机制又是如何实现的呢?对于网络的每个对象(例如一个文件),都有一组访问控制信息,该信息称为安全描述符(Security Descriptor),它控制用户和组允许使用的访问类型。安全描述符由以下三部分组成:所有者安全标识符,*访问控制列表(DACL)和安全访问控制列表(SACL)。*访问控制列表(DACL)通过用户(组)的SID确定哪些用户(组)被允许/拒绝访问当前对象。而安全访问控制列表(SACL)则控制如何审计用户(组)对当前对象的访问。
从以上的描述中,我们知道每一个Windows 200x域中的安全主体都有一个安全标识符SID,那这个安全标示符是有什么组成的呢?Windows 200x域中的每一个对象的SID都由当前域的SID加上一个相对标识符RID组成,例如以下是一个2003域中的用户对象:
其中S-1-5-21-3805389047-3781885256-3221930211为当前域的SID:
每一个域同样也被一个SID唯一标识,所以一个域被重命名后,它也无法与之前的域建立Trust信任关系。
在图一中我们看到,紧随域SID之后是一串相对标识符RID,每个 Windows 200x域控制器会被分配到一个RID池,每个RID池中分配有一定范围的RID值。当有一个对象被创建时,域控制器从自己当前的RID池中拿出下一个可以使用的RID分配给此对象,加上当前域的SID,便组成了此对象的唯一标示符SID。每一个AD域中都有一个负责RID的灵活单主机操作(FSMO)叫做RID主控(RID Master),它负责在其域中为每个域控制器颁发独立的RID池,并防止安全主体的SID重复。以下这篇KB中详细介绍了AD中与RID相关的所有属性:
http://support.microsoft.com/kb/305475/en-us
说了这么多SID,那么究竟我们应该怎么来查看一个对象的SID呢?微软提供了一个官方工具PSgetsid.exe,我们可以通过以下链接获取:
http://technet.microsoft.com/en-us/sysinternals/bb896649
通过PSgetsid.exe我们可以查看相应用户的SID:
同样,通过SID,我们可以查看对应的用户:
在以上例子中我们看到的SID都是以字符串形式展现在我们面前的,如S-1-5-21-3805389047-3781885256-3221930211-1601。但是SID是如何存储于AD域中的呢?其实真正的SID都是以十六进制数字形式存储的:
在某些应用程序的日志中我们有时会发现,所有的SID的显示形式都是一串数字,那么我们怎么才能将存储的十六进制数字转换为可以阅读的字符串形式呢?以下我们来看看这两种表达方式之间的对应关系:
首先,我们看下每个字段分别代表什么意思:
字符串
S
1
5
21-3805389047-3781885256-3221930211
1601
作用
该字符串是安全标识符
版本标识
标识符颁发机构
域或者本地计算机标识符
相对标识符
可能的标识符颁发机构有:
0 – Null
Authority
1 – World Authority
2 – Local Authority
3 – Creator Authority
4 – Non-unique Authority
5 – NT Authority
9 – Resource Manager Authority
接着,我们来看SID的数据结构是如何定义的:
////////////////////////////////////////////////////////////////////////
//
//
// Security Id (SID) //
// //
////////////////////////////////////////////////////////////////////////
//
//
// Pictorially the structureof an SID is as follows:
//
// 1 1 1 1 1 1
// 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//
+—————————————————————+
// |
SubAuthorityCount |Reserved1 (SBZ)| Revision |
//
+—————————————————————+
// | IdentifierAuthority[0] |
//
+—————————————————————+
// | IdentifierAuthority[1] |
// +—————————————————————+
// | IdentifierAuthority[2] |
//
+—————————————————————+
// | |
// +- – – – – – – – SubAuthority[] – – – – – – – – -+// |
|
//
+—————————————————————+
//
typedef struct _SID_IDENTIFIER_AUTHORITY{
BYTE Value[6];
} SID_IDENTIFIER_AUTHORITY,*PSID_IDENTIFIER_AUTHORITY;
typedef struct _SID {
BYTE Revision;
BYTE SubAuthorityCount;
SID_IDENTIFIER_AUTHORITYIdentifierAuthority;
[size_is(SubAuthorityCount)] DWORD SubAuthority[*];
} SID, *PISID;
#define SID_REVISION (1) // Current revision level
#define SECURITY_NT_AUTHORITY {0,0,0,0,0,5} // ntifs
以上信息具体可以参考如下链接:
http://msdn.microsoft.com/en-us/library/aa379597(v=VS.85).aspx
最后我们来分析下如何将存储的十六进制数与字符串进行转换:
01 —-> S-1
05 —-> 5
此处表示以下有5个小端字节序数。
00 00 00 00 00 05 —-> 5
此处表示标识符颁发机构为NT Authority。
以下为小端字节序:
15 00 00 00 —-> 0x00000015 —-> 21
F7 A0 D1 E2 —-> 0xE2D1A0F7 —->
3805389047
48 FD 6A E1 —-> 0xE16AFD48 —-> 3781885256
E3 C0 0A C0 —-> 0xC00AC0E3 —-> 3221930211
41 06 00 00 —-> 0x00000641 —-> 1601
将以上字符串连接起来为S-1-5-21-3805389047-3781885256-3221930211-1601。
通过这个方式,我们可以很轻松地在两种模式的SID间进行转换,加上PSgetsid.exe工具的帮助,快速找到所需的对象,从而更加有效地分析应用程序的日志。
每个域中都有一些常见的特殊用户,如Administrators组,Guest等,他们的安全标识符都是固定的,以下链接中列出了所有特殊用户的SID:
http://support.microsoft.com/kb/243330/en-us,在一些日常工作中,如果我们看到此类长度比较短的SID,我们便可以通过这个链接进行查询。