(七)安全标识符(SID)

安全标识符

安全标识符(SID)是用于标识受托者的可变长度的唯一值。每个帐户都有一个由权威机构(例如Windows域控制器)颁发的唯一SID,并存储在安全数据库中。每次用户登录时,系统都会从数据库中检索该用户的SID,并将其放在该用户的访问令牌中。系统使用访问令牌中的SID在与Windows安全性的所有后续交互中识别用户。当SID用作用户或组的唯一标识符时,就不能再使用它来标识另一个用户或组。

查询自己的SID可以通过:whoami /user

查询其他用户的SID可以通过WMI命令查询:wmic useraccount where name="%username%" get sid

常见的SID列表:

  • S-1-5-18 (LocalSystem)

  • S-1-5-19 (LocalService)

  • S-1-5-20 (NetworkService)

  • S-1-5-32-544 (Administrators)

  • S-1-5-32-545 (Users)

  • S-1-5-32-550 (PrintOperators)

Windows安全在以下安全元素中使用SID:

  • 在安全描述符中标识对象和主要组的所有者

  • 在访问控制条目(ACE)中,标识允许,拒绝或审核访问的受托者

  • 在访问令牌中(AC Token),用于标识用户和该用户所属的组

除了分配给特定用户和组的唯一创建的,特定于域的SID外,还有一些知名的SID用于标识通用组和通用用户。例如,众所周知的SID(每个人和世界)标识包含所有用户的组。

大多数应用程序永远不需要使用SID。因为常见的SID的名称可能会有所不同,所以您应该使用函数从预定义的常量构建SID,而不要使用常见的SID的名称。例如,英文版本的Windows操作系统有一个众所周知的SID,名为“ BUILTIN\Administrators”,在国际版本的系统上可能具有不同的名称。

如果确实需要使用SID,请不要直接操作它们。而是使用以下功能。

函数

Description

使用指定数量的子权限分配和初始化SID

将SID转换为适合于显示、存储或传输的字符串格式。

将字符串格式的SID转换为有效的功能性SID

将源SID复制到缓冲区

测试两个SID前缀值是否相等。 SID前缀是除最后一个子权限值以外的整个SID

测试两个SID是否相等。它们必须完全匹配才能被视为相等

通过使用AllocateAndInitializeSid函数释放先前分配的SID。

检索SID的长度

检索指向SID标识符权限的指针

检索存储具有指定数量的子权限的SID所需的缓冲区大小

检索指向SID中指定的子机构的指针

检索SID中的子机构数.

初始化SID结构

通过验证修订号在已知范围内并且子授权机构的数量小于最大数量,来测试SID的有效性

检索与指定帐户名对应的SID

检索与指定的SID对应的帐户名

参考代码。示例使用OpenProcessToken和GetTokenInformation函数来获取访问令牌中的组成员身份。然后,它使用AllocateAndInitializeSid函数创建一个SID,该SID标识本地计算机管理员组的常见的SID。接下来,它使用EqualSid函数将知名SID与访问令牌中的组SID进行比较。如果令牌中存在SID,则该功能将检查SID属性以确定该令牌中SID是否已启用。

#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "advapi32.lib")

#define MAX_NAME 256

BOOL SearchTokenGroupsForSID (VOID) 
{
    DWORD i, dwSize = 0, dwResult = 0;
    HANDLE hToken;
    PTOKEN_GROUPS pGroupInfo;
    SID_NAME_USE SidType;
    char lpName[MAX_NAME];
    char lpDomain[MAX_NAME];
    PSID pSID = NULL;
    SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
       
    // Open a handle to the access token for the calling process.

    if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken )) 
    {
        printf( "OpenProcessToken Error %u\n", GetLastError() );
        return FALSE;
    }

    // Call GetTokenInformation to get the buffer size.

    if(!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize)) 
    {
        dwResult = GetLastError();
        if( dwResult != ERROR_INSUFFICIENT_BUFFER ) {
            printf( "GetTokenInformation Error %u\n", dwResult );
            return FALSE;
        }
    }

    // Allocate the buffer.

    pGroupInfo = (PTOKEN_GROUPS) GlobalAlloc( GPTR, dwSize );

    // Call GetTokenInformation again to get the group information.

    if(! GetTokenInformation(hToken, TokenGroups, pGroupInfo, 
                            dwSize, &dwSize ) ) 
    {
        printf( "GetTokenInformation Error %u\n", GetLastError() );
        return FALSE;
    }

    // Create a SID for the BUILTIN\Administrators group.

    if(! AllocateAndInitializeSid( &SIDAuth, 2,
                     SECURITY_BUILTIN_DOMAIN_RID,
                     DOMAIN_ALIAS_RID_ADMINS,
                     0, 0, 0, 0, 0, 0,
                     &pSID) ) 
    {
        printf( "AllocateAndInitializeSid Error %u\n", GetLastError() );
        return FALSE;
    }

    // Loop through the group SIDs looking for the administrator SID.

    for(i=0; i<pGroupInfo->GroupCount; i++) 
    {
        if ( EqualSid(pSID, pGroupInfo->Groups[i].Sid) ) 
        {

            // Lookup the account name and print it.

            dwSize = MAX_NAME;
            if( !LookupAccountSid( NULL, pGroupInfo->Groups[i].Sid,
                                  lpName, &dwSize, lpDomain, 
                                  &dwSize, &SidType ) ) 
            {
                dwResult = GetLastError();
                if( dwResult == ERROR_NONE_MAPPED )
                   strcpy_s (lpName, dwSize, "NONE_MAPPED" );
                else 
                {
                    printf("LookupAccountSid Error %u\n", GetLastError());
                    return FALSE;
                }
            }
            printf( "Current user is a member of the %s\\%s group\n", 
                    lpDomain, lpName );

            // Find out whether the SID is enabled in the token.
            if (pGroupInfo->Groups[i].Attributes & SE_GROUP_ENABLED)
                printf("The group SID is enabled.\n");
            else if (pGroupInfo->Groups[i].Attributes & 
                              SE_GROUP_USE_FOR_DENY_ONLY)
                printf("The group SID is a deny-only SID.\n");
            else 
                printf("The group SID is not enabled.\n");
        }
    }

    if (pSID)
        FreeSid(pSID);
    if ( pGroupInfo )
        GlobalFree( pGroupInfo );
    return TRUE;
}

SID组成

SID值由SID结构信息和唯一标识受托者组成。

SID由以下组件组成:

  • SID 版本

  • 一个48位的标识符授权值,用于标识发布SID的授权(一般用来代指颁发机构)

  • 可变数量的子机构或相对标识符(RID)值,用于相对于发布SID的机构唯一地标识受托人

标识符授权值和子权限值的组合确保即使两个不同的SID颁发机构发布相同的RID值组合,也不会有两个SID相同。每个SID颁发机构仅发出一次给定的RID。

SID以二进制格式存储在SID结构中。要显示SID,可以调用ConvertSidToStringSid函数将二进制SID转换为字符串格式。要将SID字符串转换回有效的功能性SID,调用ConvertStringSidToSid函数。

这些函数对SID使用以下标准化的字符串符号,这使得可视化其组件更加简单:

S-R-I-S

在这种表示法中,文字字符“ S”将一系列数字标识为SID,R是SID版本号,I是标识符授权值,S…是一个或多个子授权值。

下面示例使用此表示法来显示本地Administrators组的常见的相对于域的SID:

S-1-5-32-544

在此示例中,SID具有以下组件。括号中的常量是Winnt.h中定义的众所周知的标识符权限和RID值:

  • 修订级别1

  • 标识符授权值为5(SECURITY_NT_AUTHORITY

  • 第一子授权值32(SECURITY_BUILTIN_DOMAIN_RID

  • 第二个子权限值544(DOMAIN_ALIAS_RID_ADMINS

常见的SID

常见的安全标识符(SID)用来标识通用组和通用用户。例如,有一些知名的SID可以标识以下组和用户:

  • Everyone,这是一个包括所有用户的组。

  • CREATOR_OWNER,在可继承ACE中用作占位符。继承ACE后,系统将CREATOR_OWNER SID替换为对象创建者的SID。

  • 本地计算机上内置域的Administrators组。

有通用的知名SID,这些ID在使用此安全模型的所有安全系统上都有意义,包括Windows以外的其他操作系统。此外,还有一些常见的SID仅在Windows系统上有意义。

Windows API为众所周知的标识符授权和相对标识符(RID)值定义了一组常量。您可以使用这些常量来创建众所周知的SID。下面的示例结合了SECURITY_WORLD_SID_AUTHORITY和SECURITY_WORLD_RID常数,以显示代表所有用户(所有人或世界)的特殊组的通用众所周知的SID:

S-1-1-0

本示例对SID使用字符串表示法,其中S将字符串标识为SID,前1是SID的修订级别,其余两位数字是SECURITY_WORLD_SID_AUTHORITYSECURITY_WORLD_RID常数。

您可以使用AllocateAndInitializeSid函数通过将标识符授权值与最多八个子授权值组合来构建SID。例如,要确定已登录的用户是否为特定知名组的成员,请调用AllocateAndInitializeSid为该知名组构建一个SID,然后使用EqualSid函数将该SID与该用户中的组SID进行比较。

以下是一些通用的众所周知的SID。

known SID

String value

Identifies

Null SID

S-1-0-0

没有成员的群组。当SID值未知时,通常使用此方法。

World

S-1-1-0

包括所有用户的组。

Local

S-1-2-0

在本地(物理上)登录到系统的终端上登录的用户。

Creator Owner ID

S-1-3-0

由创建新对象的用户的安全标识符替换的安全标识符。此SID在可继承ACE中使用。

Creator Group ID

S-1-3-1

将由创建新对象的用户的主要组SID替换的安全标识符。在可继承ACE中使用此SID。

下表列出了预定义的标识符授权常量。前四个值与通用的众所周知的SID一起使用。最后一个值与Windows众所周知的SID一起使用。

Identifier authority

Value

String value

SECURITY_NULL_SID_AUTHORITY

0

S-1-0

SECURITY_WORLD_SID_AUTHORITY

1

S-1-1

SECURITY_LOCAL_SID_AUTHORITY

2

S-1-2

SECURITY_CREATOR_SID_AUTHORITY

3

S-1-3

SECURITY_NT_AUTHORITY

5

S-1-5

以下RID值与通用的众所周知的SID一起使用。标识符授权列显示标识符授权的前缀,您可以将其与RID结合使用以创建通用的知名SID

Relative identifier authority

Value

String value

SECURITY_NULL_RID

0

S-1-0

SECURITY_WORLD_RID

0

S-1-1

SECURITY_LOCAL_RID

0

S-1-2

SECURITY_LOCAL_LOGON_RID

1

S-1-2

SECURITY_CREATOR_OWNER_RID

0

S-1-3

SECURITY_CREATOR_GROUP_RID

1

S-1-3

SECURITY_NT_AUTHORITY(S-1-5)预定义的标识符授权产生的SID不是通用的,但仅在Windows安装上才有意义。您可以将以下RID值与SECURITY_NT_AUTHORITY一起使用以创建众所周知的SID。

常量

字符串

识别

SECURITY_DIALUP_RID

S-1-5-1

使用拨号调制解调器登录终端的用户。这是一个组身份

SECURITY_NETWORK_RID

S-1-5-2

跨网络登录的用户。这是在通过网络登录时添加到进程令牌中的组标识符。相应的登录类型为LOGON32_LOGON_NETWORK。

SECURITY_BATCH_RID

S-1-5-3

使用批处理队列工具登录的用户。这是在作为批处理作业记录时添加到进程令牌中的组标识符。相应的登录类型为LOGON32_LOGON_BATCH

SECURITY_INTERACTIVE_RID

S-1-5-4

登录进行交互操作的用户。这是在以交互方式登录时添加到进程令牌中的组标识符。相应的登录类型为LOGON32_LOGON_INTERACTIVE。

SECURITY_LOGON_IDS_RID

S-1-5-5-X-Y

登录会话。这用于确保只有给定登录会话中的进程才能访问该会话的窗口站对象。对于每个登录会话,这些SID的X和Y值都不同。值SECURITY_LOGON_IDS_RID_COUNT是此标识符(5-X-Y)中RID的数量。

SECURITY_SERVICE_RID

S-1-5-6

授权作为服务登录的帐户。这是在作为服务登录时添加到进程令牌中的组标识符。相应的登录类型为LOGON32_LOGON_SERVICE

SECURITY_ANONYMOUS_LOGON_RID

S-1-5-7

匿名登录,或空会话登录

SECURITY_PROXY_RID

S-1-5-8

代理.

SECURITY_ENTERPRISE_CONTROLLERS_RID

S-1-5-9

企业控制器.

SECURITY_PRINCIPAL_SELF_RID

S-1-5-10

可以在用户或组对象的ACL中使用PRINCIPAL_SELF安全标识符。在访问检查期间,系统将SID替换为对象的SID。PRINCIPAL_SELF SID对于指定适用于继承该ACE的用户或组对象的可继承ACE很有用。这是在架构的默认安全描述中表示创建的对象的SID的唯一方法。

SECURITY_AUTHENTICATED_USER_RID

S-1-5-11

经过身份验证的用户。

SECURITY_RESTRICTED_CODE_RID

S-1-5-12

Restricted code.

SECURITY_TERMINAL_SERVER_RID

S-1-5-13

Terminal Services. Automatically added to the security token of a user who logs on to a terminal server.

SECURITY_LOCAL_SYSTEM_RID

S-1-5-18

操作系统使用的特殊帐户。

SECURITY_NT_NON_UNIQUE

S-1-5-21

SIDS are not unique.

SECURITY_BUILTIN_DOMAIN_RID

S-1-5-32

The built-in system domain.

SECURITY_WRITE_RESTRICTED_CODE_RID

S-1-5-33

Write restricted code.

以下RID与每个域有关。

RID

Value

Identifies

DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP

0x0000023E

可以使用分布式组件对象模型(DCOM)连接到证书颁发机构的用户组。

DOMAIN_USER_RID_ADMIN

0x000001F4

域中的管理用户帐户。

DOMAIN_USER_RID_GUEST

0x000001F5

域中的来宾用户帐户。没有帐户的用户可以自动登录到该帐户。

DOMAIN_GROUP_RID_ADMINS

0x00000200

域管理员组。该帐户仅存在于运行服务器操作系统的系统上。

DOMAIN_GROUP_RID_USERS

0x00000201

包含域中所有用户帐户的组。所有用户都将自动添加到该组中。

DOMAIN_GROUP_RID_GUESTS

0x00000202

域中的来宾组帐户。

DOMAIN_GROUP_RID_COMPUTERS

0x00000203

域计算机的组。域中的所有计算机都是该组的成员。

DOMAIN_GROUP_RID_CONTROLLERS

0x00000204

域控制器的组。域中的所有DC都是该组的成员。

DOMAIN_GROUP_RID_CERT_ADMINS

0x00000205

证书发布者组。运行证书服务的计算机是该组的成员

DOMAIN_GROUP_RID_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS

0x000001F2

企业只读域控制器组。

DOMAIN_GROUP_RID_SCHEMA_ADMINS

0x00000206

模式管理员组。该组的成员可以修改Active Directory架构。

DOMAIN_GROUP_RID_ENTERPRISE_ADMINS

0x00000207

企业管理员组。该组的成员具有对Active Directory林中所有域的完全访问权限。企业管理员负责林级操作,例如添加或删除新域。

DOMAIN_GROUP_RID_POLICY_ADMINS

0x00000208

策略管理员组。

DOMAIN_GROUP_RID_READONLY_CONTROLLERS

0x00000209

只读域控制器组。

DOMAIN_GROUP_RID_CLONEABLE_CONTROLLERS

0x0000020A

可克隆域控制器的组

DOMAIN_GROUP_RID_CDC_RESERVED

0x0000020C

保留的CDC组

DOMAIN_GROUP_RID_PROTECTED_USERS

0x0000020D

受保护的用户组。

DOMAIN_GROUP_RID_KEY_ADMINS

0x0000020E

关键管理员组

DOMAIN_GROUP_RID_ENTERPRISE_KEY_ADMINS

0x0000020F

企业密钥管理员组

以下RID用于指定强制完整性级别。

RID

Value

Identifies

SECURITY_MANDATORY_UNTRUSTED_RID

0x00000000

Untrusted.

SECURITY_MANDATORY_LOW_RID

0x00001000

Low integrity.

SECURITY_MANDATORY_MEDIUM_RID

0x00002000

Medium integrity.

SECURITY_MANDATORY_MEDIUM_PLUS_RID

SECURITY_MANDATORY_MEDIUM_RID + 0x100

Medium high integrity.

SECURITY_MANDATORY_HIGH_RID

0X00003000

High integrity.

SECURITY_MANDATORY_SYSTEM_RID

0x00004000

System integrity.

SECURITY_MANDATORY_PROTECTED_PROCESS_RID

0x00005000

Protected process.

下表提供了相对域RID的示例,您可以使用它们来为本地组(别名)形成众所周知的SID。有关本地和全局组的更多信息,请参见本地组功能和组功能。

RID

Value

String Value

Identifies

DOMAIN_ALIAS_RID_ADMINS

0x00000220

S-1-5-32-544

用于管理域的本地组。

DOMAIN_ALIAS_RID_USERS

0x00000221

S-1-5-32-545

代表域中所有用户的本地组

DOMAIN_ALIAS_RID_GUESTS

0x00000222

S-1-5-32-546

代表域来宾的本地组。

DOMAIN_ALIAS_RID_POWER_USERS

0x00000223

S-1-5-32-547

一个本地组,用于代表希望将系统视为其个人计算机而不是多个用户的工作站的用户或一组用户。

DOMAIN_ALIAS_RID_ACCOUNT_OPS

0x00000224

S-1-5-32-548

仅在运行服务器操作系统的系统上存在的本地组。此本地组允许控制非管理员帐户。

DOMAIN_ALIAS_RID_SYSTEM_OPS

0x00000225

S-1-5-32-549

仅在运行服务器操作系统的系统上存在的本地组。该本地组执行系统管理功能,不包括安全功能。它建立网络共享,控制打印机,解锁工作站并执行其他操作。

DOMAIN_ALIAS_RID_PRINT_OPS

0x00000226

S-1-5-32-550

仅在运行服务器操作系统的系统上存在的本地组。此本地组控制打印机和打印队列。

DOMAIN_ALIAS_RID_BACKUP_OPS

0x00000227

S-1-5-32-551

一个用于控制文件备份和还原特权的分配本地组。

DOMAIN_ALIAS_RID_REPLICATOR

0x00000228

S-1-5-32-552

一个本地组,负责将安全数据库从主域控制器复制到备份域控制器。这些帐户仅由系统使用。

DOMAIN_ALIAS_RID_RAS_SERVERS

0x00000229

S-1-5-32-553

代表RAS和IAS服务器的本地组。该组允许访问用户对象的各种属性。

DOMAIN_ALIAS_RID_PREW2KCOMPACCESS

0x0000022A

S-1-5-32-554

仅在运行Windows 2000 Server的系统上存在的本地组。有关更多信息,请参见允许匿名访问。

DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS

0x0000022B

S-1-5-32-555

代表所有远程桌面用户的本地组。

DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS

0x0000022C

S-1-5-32-556

代表网络配置的本地组。

DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS

0x0000022D

S-1-5-32-557

代表任何林信任用户的本地组。

DOMAIN_ALIAS_RID_MONITORING_USERS

0x0000022E

S-1-5-32-558

代表所有受监视用户的本地组。

DOMAIN_ALIAS_RID_LOGGING_USERS

0x0000022F

S-1-5-32-559

负责记录用户的本地组。

DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS

0x00000230

S-1-5-32-560

代表所有授权访问的本地组。

DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS

0x00000231

S-1-5-32-561

仅在运行允许终端服务和远程访问的服务器操作系统的系统上存在的本地组。

DOMAIN_ALIAS_RID_DCOM_USERS

0x00000232

S-1-5-32-562

一个本地组,代表可以使用分布式组件对象模型(DCOM)的用户。

DOMAIN_ALIAS_RID_IUSERS

0X00000238

S-1-5-32-568

代表Internet用户的本地组。

DOMAIN_ALIAS_RID_CRYPTO_OPERATORS

0x00000239

S-1-5-32-569

一个本地组,代表对密码运算符的访问。

DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP

0x0000023B

S-1-5-32-571

表示可以缓存的主体的本地组。

DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP

0x0000023C

S-1-5-32-572

表示无法缓存的主体的本地组。

DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP

0x0000023D

S-1-5-32-573

代表事件日志读取器的本地组。

DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP

0x0000023E

S-1-5-32-574

可以使用分布式组件对象模型(DCOM)连接到证书颁发机构的本地用户组。

DOMAIN_ALIAS_RID_RDS_REMOTE_ACCESS_SERVERS

0x0000023F

S-1-5-32-575

代表RDS远程访问服务器的本地组。

DOMAIN_ALIAS_RID_RDS_ENDPOINT_SERVERS

0x00000240

S-1-5-32-576

代表端点服务器的本地组。

DOMAIN_ALIAS_RID_RDS_MANAGEMENT_SERVERS

0x00000241

S-1-5-32-577

代表管理服务器的本地组

DOMAIN_ALIAS_RID_HYPER_V_ADMINS

0x00000242

S-1-5-32-578

代表hyper-v管理员的本地组

DOMAIN_ALIAS_RID_ACCESS_CONTROL_ASSISTANCE_OPS

0x00000243

S-1-5-32-579

代表访问控制辅助OPS的本地组。

DOMAIN_ALIAS_RID_REMOTE_MANAGEMENT_USERS

0x00000244

S-1-5-32-580

代表远程管理用户的本地组。

DOMAIN_ALIAS_RID_DEFAULT_ACCOUNT

0x00000245

S-1-5-32-581

代表默认帐户的本地组。

DOMAIN_ALIAS_RID_STORAGE_REPLICA_ADMINS

0x00000246

S-1-5-32-582

代表存储副本管理员的本地组。

DOMAIN_ALIAS_RID_DEVICE_OWNERS

0x00000247

S-1-5-32-583

代表的本地组可以为设备所有者进行预期的设置。

WELL_KNOWN_SID_TYPE枚举定义了常用SID的列表。此外,安全描述符定义语言(SDDL)使用SID字符串以字符串格式引用众所周知的SID。

最后更新于