返回介绍

(七)安全标识符(SID)

发布于 2022-11-26 10:40:50 字数 21261 浏览 0 评论 0 收藏 0

安全标识符

安全标识符(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
AllocateAndInitializeSid使用指定数量的子权限分配和初始化SID
ConvertSidToStringSid将SID转换为适合于显示、存储或传输的字符串格式。
ConvertStringSidToSid将字符串格式的SID转换为有效的功能性SID
CopySid将源SID复制到缓冲区
EqualPrefixSid测试两个SID前缀值是否相等。 SID前缀是除最后一个子权限值以外的整个SID
EqualSid测试两个SID是否相等。它们必须完全匹配才能被视为相等
FreeSid通过使用AllocateAndInitializeSid函数释放先前分配的SID。
GetLengthSid检索SID的长度
GetSidIdentifierAuthority检索指向SID标识符权限的指针
GetSidLengthRequired检索存储具有指定数量的子权限的SID所需的缓冲区大小
GetSidSubAuthority检索指向SID中指定的子机构的指针
GetSidSubAuthorityCount检索SID中的子机构数.
InitializeSid初始化SID结构
IsValidSid通过验证修订号在已知范围内并且子授权机构的数量小于最大数量,来测试SID的有效性
LookupAccountName检索与指定帐户名对应的SID
LookupAccountSid检索与指定的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 SIDString valueIdentifies
Null SIDS-1-0-0没有成员的群组。当SID值未知时,通常使用此方法。
WorldS-1-1-0包括所有用户的组。
LocalS-1-2-0在本地(物理上)登录到系统的终端上登录的用户。
Creator Owner IDS-1-3-0由创建新对象的用户的安全标识符替换的安全标识符。此SID在可继承ACE中使用。
Creator Group IDS-1-3-1将由创建新对象的用户的主要组SID替换的安全标识符。在可继承ACE中使用此SID。

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

Identifier authorityValueString value
SECURITY_NULL_SID_AUTHORITY0S-1-0
SECURITY_WORLD_SID_AUTHORITY1S-1-1
SECURITY_LOCAL_SID_AUTHORITY2S-1-2
SECURITY_CREATOR_SID_AUTHORITY3S-1-3
SECURITY_NT_AUTHORITY5S-1-5

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

Relative identifier authorityValueString value
SECURITY_NULL_RID0S-1-0
SECURITY_WORLD_RID0S-1-1
SECURITY_LOCAL_RID0S-1-2
SECURITY_LOCAL_LOGON_RID1S-1-2
SECURITY_CREATOR_OWNER_RID0S-1-3
SECURITY_CREATOR_GROUP_RID1S-1-3

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

常量字符串识别
SECURITY_DIALUP_RIDS-1-5-1使用拨号调制解调器登录终端的用户。这是一个组身份
SECURITY_NETWORK_RIDS-1-5-2跨网络登录的用户。这是在通过网络登录时添加到进程令牌中的组标识符。相应的登录类型为LOGON32_LOGON_NETWORK。
SECURITY_BATCH_RIDS-1-5-3使用批处理队列工具登录的用户。这是在作为批处理作业记录时添加到进程令牌中的组标识符。相应的登录类型为LOGON32_LOGON_BATCH
SECURITY_INTERACTIVE_RIDS-1-5-4登录进行交互操作的用户。这是在以交互方式登录时添加到进程令牌中的组标识符。相应的登录类型为LOGON32_LOGON_INTERACTIVE。
SECURITY_LOGON_IDS_RIDS-1-5-5-X-Y登录会话。这用于确保只有给定登录会话中的进程才能访问该会话的窗口站对象。对于每个登录会话,这些SID的X和Y值都不同。值SECURITY_LOGON_IDS_RID_COUNT是此标识符(5-X-Y)中RID的数量。
SECURITY_SERVICE_RIDS-1-5-6授权作为服务登录的帐户。这是在作为服务登录时添加到进程令牌中的组标识符。相应的登录类型为LOGON32_LOGON_SERVICE
SECURITY_ANONYMOUS_LOGON_RIDS-1-5-7匿名登录,或空会话登录
SECURITY_PROXY_RIDS-1-5-8代理.
SECURITY_ENTERPRISE_CONTROLLERS_RIDS-1-5-9企业控制器.
SECURITY_PRINCIPAL_SELF_RIDS-1-5-10可以在用户或组对象的ACL中使用PRINCIPAL_SELF安全标识符。在访问检查期间,系统将SID替换为对象的SID。PRINCIPAL_SELF SID对于指定适用于继承该ACE的用户或组对象的可继承ACE很有用。这是在架构的默认安全描述中表示创建的对象的SID的唯一方法。
SECURITY_AUTHENTICATED_USER_RIDS-1-5-11经过身份验证的用户。
SECURITY_RESTRICTED_CODE_RIDS-1-5-12Restricted code.
SECURITY_TERMINAL_SERVER_RIDS-1-5-13Terminal Services. Automatically added to the security token of a user who logs on to a terminal server.
SECURITY_LOCAL_SYSTEM_RIDS-1-5-18操作系统使用的特殊帐户。
SECURITY_NT_NON_UNIQUES-1-5-21SIDS are not unique.
SECURITY_BUILTIN_DOMAIN_RIDS-1-5-32The built-in system domain.
SECURITY_WRITE_RESTRICTED_CODE_RIDS-1-5-33Write restricted code.

以下RID与每个域有关。

RIDValueIdentifies
DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP0x0000023E可以使用分布式组件对象模型(DCOM)连接到证书颁发机构的用户组。
DOMAIN_USER_RID_ADMIN0x000001F4域中的管理用户帐户。
DOMAIN_USER_RID_GUEST0x000001F5域中的来宾用户帐户。没有帐户的用户可以自动登录到该帐户。
DOMAIN_GROUP_RID_ADMINS0x00000200域管理员组。该帐户仅存在于运行服务器操作系统的系统上。
DOMAIN_GROUP_RID_USERS0x00000201包含域中所有用户帐户的组。所有用户都将自动添加到该组中。
DOMAIN_GROUP_RID_GUESTS0x00000202域中的来宾组帐户。
DOMAIN_GROUP_RID_COMPUTERS0x00000203域计算机的组。域中的所有计算机都是该组的成员。
DOMAIN_GROUP_RID_CONTROLLERS0x00000204域控制器的组。域中的所有DC都是该组的成员。
DOMAIN_GROUP_RID_CERT_ADMINS0x00000205证书发布者组。运行证书服务的计算机是该组的成员
DOMAIN_GROUP_RID_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS0x000001F2企业只读域控制器组。
DOMAIN_GROUP_RID_SCHEMA_ADMINS0x00000206模式管理员组。该组的成员可以修改Active Directory架构。
DOMAIN_GROUP_RID_ENTERPRISE_ADMINS0x00000207企业管理员组。该组的成员具有对Active Directory林中所有域的完全访问权限。企业管理员负责林级操作,例如添加或删除新域。
DOMAIN_GROUP_RID_POLICY_ADMINS0x00000208策略管理员组。
DOMAIN_GROUP_RID_READONLY_CONTROLLERS0x00000209只读域控制器组。
DOMAIN_GROUP_RID_CLONEABLE_CONTROLLERS0x0000020A可克隆域控制器的组
DOMAIN_GROUP_RID_CDC_RESERVED0x0000020C保留的CDC组
DOMAIN_GROUP_RID_PROTECTED_USERS0x0000020D受保护的用户组。
DOMAIN_GROUP_RID_KEY_ADMINS0x0000020E关键管理员组
DOMAIN_GROUP_RID_ENTERPRISE_KEY_ADMINS0x0000020F企业密钥管理员组

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

RIDValueIdentifies
SECURITY_MANDATORY_UNTRUSTED_RID0x00000000Untrusted.
SECURITY_MANDATORY_LOW_RID0x00001000Low integrity.
SECURITY_MANDATORY_MEDIUM_RID0x00002000Medium integrity.
SECURITY_MANDATORY_MEDIUM_PLUS_RIDSECURITY_MANDATORY_MEDIUM_RID + 0x100Medium high integrity.
SECURITY_MANDATORY_HIGH_RID0X00003000High integrity.
SECURITY_MANDATORY_SYSTEM_RID0x00004000System integrity.
SECURITY_MANDATORY_PROTECTED_PROCESS_RID0x00005000Protected process.

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

RIDValueString ValueIdentifies
DOMAIN_ALIAS_RID_ADMINS0x00000220S-1-5-32-544用于管理域的本地组。
DOMAIN_ALIAS_RID_USERS0x00000221S-1-5-32-545代表域中所有用户的本地组
DOMAIN_ALIAS_RID_GUESTS0x00000222S-1-5-32-546代表域来宾的本地组。
DOMAIN_ALIAS_RID_POWER_USERS0x00000223S-1-5-32-547一个本地组,用于代表希望将系统视为其个人计算机而不是多个用户的工作站的用户或一组用户。
DOMAIN_ALIAS_RID_ACCOUNT_OPS0x00000224S-1-5-32-548仅在运行服务器操作系统的系统上存在的本地组。此本地组允许控制非管理员帐户。
DOMAIN_ALIAS_RID_SYSTEM_OPS0x00000225S-1-5-32-549仅在运行服务器操作系统的系统上存在的本地组。该本地组执行系统管理功能,不包括安全功能。它建立网络共享,控制打印机,解锁工作站并执行其他操作。
DOMAIN_ALIAS_RID_PRINT_OPS0x00000226S-1-5-32-550仅在运行服务器操作系统的系统上存在的本地组。此本地组控制打印机和打印队列。
DOMAIN_ALIAS_RID_BACKUP_OPS0x00000227S-1-5-32-551一个用于控制文件备份和还原特权的分配本地组。
DOMAIN_ALIAS_RID_REPLICATOR0x00000228S-1-5-32-552一个本地组,负责将安全数据库从主域控制器复制到备份域控制器。这些帐户仅由系统使用。
DOMAIN_ALIAS_RID_RAS_SERVERS0x00000229S-1-5-32-553代表RAS和IAS服务器的本地组。该组允许访问用户对象的各种属性。
DOMAIN_ALIAS_RID_PREW2KCOMPACCESS0x0000022AS-1-5-32-554仅在运行Windows 2000 Server的系统上存在的本地组。有关更多信息,请参见允许匿名访问。
DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS0x0000022BS-1-5-32-555代表所有远程桌面用户的本地组。
DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS0x0000022CS-1-5-32-556代表网络配置的本地组。
DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS0x0000022DS-1-5-32-557代表任何林信任用户的本地组。
DOMAIN_ALIAS_RID_MONITORING_USERS0x0000022ES-1-5-32-558代表所有受监视用户的本地组。
DOMAIN_ALIAS_RID_LOGGING_USERS0x0000022FS-1-5-32-559负责记录用户的本地组。
DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS0x00000230S-1-5-32-560代表所有授权访问的本地组。
DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS0x00000231S-1-5-32-561仅在运行允许终端服务和远程访问的服务器操作系统的系统上存在的本地组。
DOMAIN_ALIAS_RID_DCOM_USERS0x00000232S-1-5-32-562一个本地组,代表可以使用分布式组件对象模型(DCOM)的用户。
DOMAIN_ALIAS_RID_IUSERS0X00000238S-1-5-32-568代表Internet用户的本地组。
DOMAIN_ALIAS_RID_CRYPTO_OPERATORS0x00000239S-1-5-32-569一个本地组,代表对密码运算符的访问。
DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP0x0000023BS-1-5-32-571表示可以缓存的主体的本地组。
DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP0x0000023CS-1-5-32-572表示无法缓存的主体的本地组。
DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP0x0000023DS-1-5-32-573代表事件日志读取器的本地组。
DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP0x0000023ES-1-5-32-574可以使用分布式组件对象模型(DCOM)连接到证书颁发机构的本地用户组。
DOMAIN_ALIAS_RID_RDS_REMOTE_ACCESS_SERVERS0x0000023FS-1-5-32-575代表RDS远程访问服务器的本地组。
DOMAIN_ALIAS_RID_RDS_ENDPOINT_SERVERS0x00000240S-1-5-32-576代表端点服务器的本地组。
DOMAIN_ALIAS_RID_RDS_MANAGEMENT_SERVERS0x00000241S-1-5-32-577代表管理服务器的本地组
DOMAIN_ALIAS_RID_HYPER_V_ADMINS0x00000242S-1-5-32-578代表hyper-v管理员的本地组
DOMAIN_ALIAS_RID_ACCESS_CONTROL_ASSISTANCE_OPS0x00000243S-1-5-32-579代表访问控制辅助OPS的本地组。
DOMAIN_ALIAS_RID_REMOTE_MANAGEMENT_USERS0x00000244S-1-5-32-580代表远程管理用户的本地组。
DOMAIN_ALIAS_RID_DEFAULT_ACCOUNT0x00000245S-1-5-32-581代表默认帐户的本地组。
DOMAIN_ALIAS_RID_STORAGE_REPLICA_ADMINS0x00000246S-1-5-32-582代表存储副本管理员的本地组。
DOMAIN_ALIAS_RID_DEVICE_OWNERS0x00000247S-1-5-32-583代表的本地组可以为设备所有者进行预期的设置。

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击“接受”或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文