用于保护可保护对象的安全描述符是以二进制形式存储的,但Windows API也提供了可以将安全描述符在二进制与文本字符串之间来回转换的函数。要将二进制形式存储的安全描述符转换成字符串形式,可调用ConvertSecurityDescriptorToStringSecurityDescriptor()函数,而ConvertStringSecurityDescriptorToSecurityDescriptor()则可以进行反向转换。字符串形式的安全描述符虽不能起到保护可保护对象的作用,但它更易于存储和传送。
本篇尝试讲解一下以字符串形式存在的安全描述符所采用的格式规范,这在创建安全描述符以及在命令行用icacls.exe命令操作安全描述符时是非常有帮助的。由于安全描述符中的许多元素,如访问权限掩码(Access Rights Mask)、SID等都要用字符串表示,所以本文先要简单介绍一下访问权限和SID,再介绍安全描述符的字符串形式所采用的格式规范,最后再介绍一下icacls.exe命令。本文结构如下:
- 访问权限
- SID
- 安全描述符定义语言(SDDL)
- ICACLS.EXE
一、访问权限
在之前的文章中我们提到,安全描述符中的ACE要描述针对某受信任实体所授予或拒绝的权限,这些权限是以访问权限掩码(Access Rights Mask)的形式表达的。访问权限掩码是一个32位的值,其中的每个位都对应可保护对象的访问权限,形式如下:
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
GR | GW | GE | GA | 保留 | AS | 标准访问权限 | 对象特定权限 |
各种访问权限实际上是其中一个一个的标志位,代表可以在可保护对象上执行的一组操作。例如注册表键作为可保护对象,它定义了KET_SET_VALUE权限,拥有此权限的线程可以在该键下设置值。不同类型的可保护对象都根据其自身特性定义了适用于自己的一套访问权限。如果线程希望在某可保护对象执行某种操作却不具备相应的权限,系统会拒绝执行该操作。
在访问掩码中,低16位用于对象特定的访问权限,再向上8位是标准访问权限,最高4位用于通用访问权限。24位代表ACCESS_SYSTEM_SECURITY,用于访问对象安全描述符中的SACL。
访问权限掩码的高4位用于指定通用访问权限(Generic Access Rights),分别是
- GR(GENERIC_READ,读操作)(31位)
- GW(GENERIC_WRITE,写操作)(30位)
- GE(GENERIC_EXECUTE,执行操作)(29位)
- GA(GENERIC_ALL,指代所有可能的权限)(28位)
线程在访问可保护对象时系统会将这些通用权限映射到标准权限或对象特定权限。比如文件对象会将通用权限GENERIC_READ映射成READ_CONTROL和SYNCHRONIZE标准权限,以及FILE_READ_DATA、FILE_READ_EA和FILE_READ_ATTRIBUTES这些文件对象特有的访问权限。对于其他类型的对象系统也会根据其类型将GENERIC_READ映射成相应的权限。
当调用类似CreateFile()、OpenProcess()的函数打开某可保护对象的句柄时,可在函数入口参数指定所请求的权限(也有特例,比如CreateSemaphore()函数不需要明确指定所需权限,它要求对所打开对象进行完全访问的)。所请求的权限应以能够满足需求为准,尽量不要请求完全访问,只要通用权限能够满足要求,指定通用权限作为希望采取的访问类型会比指定具体的标准权限或对象特定权限简便得多。
通用权限的抽象层次较高,与对象类型的特定权限相比,还有一组适用于大多数对象类型、抽象层次适中的标准访问权限(Standard Access Rights):
权限 | 说明 |
DELETE | 用于删除对象的权限 |
READ_CONTROL | 读取对象安全描述符中除SACL之外的信息所需的权限 |
SYNCHRONIZE | 将受保护对象用于同步机制的权限。被授予该权限的线程可以在受保护对象转为信号状态前处于等待状态,具体可参考Windows同步机制的相关资料。并不是所有对象类型都支持该权限。 |
WRITE_DAC | 用于修改受保护对象安全描述符中DACL的权限 |
WRITE_OWNER | 用于修改受保护对象安全描述符中所有者的权限 |
为方便使用,Windows根据常见的应用场景将以上标准权限又做了以下组合:
权限组合 | 说明 |
STANDARD_RIGHTS_ALL | 组合DELETE、READ_CONTROL、WRITE_DAC、WRITE_OWNER、SYNCHRONIZE |
STANDARD_RIGHTS_EXECUTE | 当前等同于READ_CONTROL |
STANDARD_RIGHTS_READ | 当前等同于READ_CONTROL |
STANDARD_RIGHTS_REQUIRED | 组合DELETE、READ_CONTROL、WRITE_DAC、WRITE_OWNER |
STANDARD_RIGHTS_WRITE | 当前等同于READ_CONTROL |
24位是ACCESS_SYSTEM_SECURITY权限,用于控制线程获取和设置安全描述符中SACL的能力,该权限仅可用于SACL,不可用于DACL中。只有当线程的访问令牌中被赋予SE_SECURITY_NAME特权时才能获得该访问权限。
另外,Active Directory目录服务中的对象也都有一个安全描述符,在其中可以设置一组目录服务对象特有的权限,见下表:
权限 | 说明 |
ACTRL_DS_OPEN | 打开DS对象 |
ACTRL_DS_CREATE_CHILD | 创建子DS对象 |
ACTRL_DS_DELETE_CHILD | 删除子DS对象 |
ACTRL_DS_LIST | 枚举DS对象 |
ACTRL_DS_READ_PROP | 读取DS对象的属性 |
ACTRL_DS_WRITE_PROP | 写入DS对象的属性 |
ACTRL_DS_SELF | 只有在执行对象支持的已验证权限检查并通过之后,才允许访问。 此标志可以单独用于执行对象的所有已验证权限检查,也可以与特定已验证权限的标识符结合使用,表示仅对该已验证权限检查。 |
ACTRL_DS_DELETE_TREE | 删除对象的树 |
ACTRL_DS_LIST_OBJECT | 列出对象的树 |
ACTRL_DS_CONTROL_ACCESS | 只有在对对象支持的扩展权限进行检查并通过后才允许访问。该标志可单独使用,表示要检查所有的扩展权限,也可以和某一扩展权限的标识符结合使用,表示只对这个指定的扩展权限进行检查。 |
二、SID
SID是用来识别受信任实体的一个可变长度的数值,可以理解为受信任实体的身份证号,要求具有唯一性。Windows安全机制中SID被广泛应用,在安全描述符中、ACE以及访问令牌中都用SID指代受信任实体。安全描述符中的对象所有者及其所属组均用其SID表示,在ACE中被授予或拒绝权限的受信任实体也用其SID表示,在访问令牌中线程所代表的用户及其所属组同样也是用其SID表示。
在如此多的SID中,除了被唯一创建并赋予特定用户和组的SID外,还有一种公认SID(Well-known SID),它们用来标识通用用户和组,比如众所周知的“Everyone"(或World)组被赋予的就是公认SID。公认SID的名称有可能会变化,英文版Windows中的内置管理组”BUILTIN\Administrators“在其他语言的版本中可能有不同的名称,但它们都是用一个共同的公认SID。基于这个原因,也是基于惯例,在创建自己的SID时要基于系统预定义的常数,而且要用系统提供的API函数惭怍SID,不要直接编程操作SID的数据结构。文后会附上用于操作SID的函数集。
1.SID的组成
一个SID包括用于描述SID数据结构的信息以及对受信任实体进行唯一标识的信息。SID包含以下成分:
- SID数据结构的修订号
- 一个48位的SID发布机构的标识符
- 一系列数量不固定的子发布机构或相对标识符(RID,Relative Identifier),用来在SID的发布机构负责范围内确保所发布SID的唯一性。
SID以二进制形式存放,要显示一个SID要调用ConvertSidToStringSid()将其转换成字符串形式,ConvertStringSidToSid()可完成反向转换。这些函数使用以下格式定义以字符串形式表示的SID:
S-R-I-S...
第一个字母”S“表示该字符串是一个SID字符串,”R“代表修订号(Revision level),”I"是SID发布机构的标识,后面的“S..."是一个或多个子发布机构或RID标识。看下面的例子:
S-1-5-32-544
在该例中,修订号为1,发布机构为5(SECURITY_NT_AUTHORITY),第一个RID为32(SECURITY_BUILTIN_DOMAIN_RID),第二个RID为544(DOMAIN_ALIAS_RID_ADMINS)。
2.公认SID(Well-known SID)
公认SID用来表示通用用户和组,比如Everyone(或World)用来指代含所有用户的通用组;CREATOR_OWNER指代对象的创建者(它在ACE中充当占位符,当该ACE被继承时,该占位符可被替换为子对象创建者的SID);Administrators组,本地计算机内置域的管理员组。这些组都是通用组,都用公认SID标识。
公认SID又分为全球公认SID(Universal Well-known SID)和操作系统专有的公认SID,比如Windows系统就定义了大量的公认SID。全球公认SID适用于所有采用这种安全模式的系统。
Windows API定义了一组常数用来指代公认SID分发机构(Identifier Authority)和相对ID(RID,Relative identifier),程序员可基于这些常数来构建公认SID。比如,如果需要判断当前登录的账户是不是某个公认组的成员,可以调用AllocateAndInitiralizeSid()来创建公认组的SID,然后用EqualSid()将其与用户令牌中的组SID做比对。AllocateAndInitializeSid()函数可用来创建SID,它可以将一个SID分发机构的标识和至多8个RID做绑定,创建的SID在用完之后不要忘了用FreeSid()函数将其释放。
下表是一些全球公认SID以及Windows系统为它们定义的常量标识:
全球公认SID | 字符串表示 | 说明 | Windows定义的分发机构常量 | Windows定义的RID常量 | |||
分发机构 | 值 | 字符串表示 | RID | 值 | |||
Null SID | S-1-0-0 | 空组,常用来表示未知SID | SECURITY_NULL_SID_AUTHORITY | 0 | s-1-0 | SECURITY_NULL_RID | 0 |
World | S-1-1-0 | 包含所有用户的组 | SECURITY_WORLD_SID_AUTHORITY | 1 | S-1-1 | SECURITY_WORLD_RID (SDDL符号:WD) | 0 |
Local | S-1-2-0 | 登录到以本地(物理)方式连接到系统的终端的用户。 | SECURITY_LOCAL_SID_AUTHORITY | 2 | S-1-2 | SECURITY_LOCAL_RID | 0 |
S-1-2-1 | SECURITY_LOCAL_LOGON_RID | 1 | |||||
Creator Owner ID | S-1-3-0 | 用于可继承的ACE。在该ACE被继承时被替换为对象创建者的SID | SECURITY_CREATOR_SID_AUTHORITY | 3 | S-1-3 | SECURITY_CREATOR_OWNER_RID (SDDL符号:CO) | 0 |
Creator Group ID | S-1-3-1 | 用于可继承的ACE。在该ACE被继承时被替换为对象创建者所属主组的SID | SECURITY_CREATOR_GROUP_RID (SDDL符号:CG) | 1 |
表中的“SDDL符号”是该标识出现于文本形式的安全描述符时使用的符号,后面会提到。
在Windows中,还有一个分发机构标识SECURITY_NT_AUTHORITY(S-1-5),它不是全球公认SID,而是专用于Windows系统的公认SID,可以用该SID发布机构产生专用于Windows系统的SID。下面的RID可以与之匹配。
RID | 说明 |
SECURITY_DIALUP_RID 字符串值: S-1-5-1 | 使用拨号调制解调器登录终端的用户。 这是一个组标识符。 |
SECURITY_NETWORK_RID
| 跨网络登录的用户。 这是在跨网络登录时添加到进程的令牌中的组标识符。 相应的登录类型是 LOGON32_LOGON_NETWORK。 |
SECURITY_BATCH_RID 字符串值: S-1-5-3 | 使用批处理队列登录的用户。 这是一个组标识符,在进程被记录为批处理作业时被添加到进程的标记中。 相应的登录类型为 LOGON32_LOGON_BATCH。 |
SECURITY_INTERACTIVE_RID
| 登录进行交互式操作的用户。 这是在以交互方式登录时添加到进程的令牌中的组标识符。 相应的登录类型是 LOGON32_LOGON_INTERACTIVE。 |
SECURITY_LOGON_IDS_RID | 一个登录会话。 这用于确保只有特定登录会话中的进程才能访问该会话的窗口工作站对象。 这些 SID 的 X 和 Y 值在每个登录会话中都各不相同。 SECURITY_LOGON_IDS_RID_COUNT 的值是该标识符中的 RID 个数 (5-X-Y)。 |
SECURITY_SERVICE_RID
| 被授权作为服务登录的帐户。 这是在以服务形式登录时添加到进程的令牌中的组标识符。 相应的登录类型是 LOGON32_LOGON_SERVICE。 |
SECURITY_ANONYMOUS_LOGON_RID
| 匿名登录或 null 会话登录。 |
SECURITY_PROXY_RID 字符串值: S-1-5-8 | 代理。 |
SECURITY_ENTERPRISE_CONTROLLERS_RID 字符串值: S-1-5-9 | 企业控制器。 |
SECURITY_PRINCIPAL_SELF_RID
| PRINCIPAL_SELF 安全标识符可在用户或组对象的 ACL 中使用。 在访问检查过程中,系统会将 SID 替换为对象的 SID。 PRINCIPAL_SELF SID 用于指定适用于继承 ACE 的用户或组对象的可继承 ACE。 这是在架构(Schema,可参考Active Directory文档)的默认安全描述符中表示已创建对象 SID 的唯一方法。 |
SECURITY_AUTHENTICATED_USER_RID
| 通过身份验证的用户。 |
SECURITY_RESTRICTED_CODE_RID
| 受限代码。 |
SECURITY_TERMINAL_SERVER_RID 字符串值: S-1-5-13 | 终端服务。 自动添加到登录到终端服务器的用户的安全令牌中。 |
SECURITY_REMOTE_LOGON_RID 字符串值:S-1-5-14 | 此组包括使用远程桌面连接登录到计算机的所有用户。 该组是 Interactive 组的子集。 包含远程交互式登录 SID 的访问令牌也包含交互式 SID。 |
SECURITY_THIS_ORGANIZATION_RID 字符串值:S-1-5-15 | 包含同一组织中的所有用户的组。 仅包含在 Active Directory 帐户中,并且仅由域控制器添加。 |
SECURITY_IUSER_RID 字符串值:S-1-5-17 | 由默认 Internet Information Services (IIS) 用户使用的帐户。 |
SECURITY_LOCAL_SYSTEM_RID
| 操作系统使用的特殊帐户。 |
SECURITY_LOCAL_SERVICE_RID 字符串值: | 由计算机本地服务使用的标识,无需进行广泛的本地访问,也不需要经过身份验证的网络访问。 作为 LocalService 运行的服务以普通用户身份访问本地资源,以匿名用户身份访问网络资源。 因此,与在本地和网络上作为 LocalSystem 运行的服务相比,作为 LocalService 在本地运行的服务的权威性要小得多。 |
SECURITY_NETWORK_SERVICE_RID 字符串值: | 一种标识,由不需要广泛本地访问但确实需要经过身份验证的网络访问的服务使用。 作为 NetworkService 运行的服务以普通用户身份访问本地资源,并使用计算机的标识访问网络资源。 因此,作为 NetworkService 运行的服务与作为 LocalSystem 运行的服务具有相同的网络访问权限,但本地访问权限显著减少。 |
SECURITY_NT_NON_UNIQUE 字符串值: S-1-5-21 | SIDS 并非唯一的。 |
SECURITY_BUILTIN_DOMAIN_RID 字符串值: S-1-5-32 | 内置系统域。 |
SECURITY_WRITE_RESTRICTED_CODE_RID
| 编写受限制的代码。 |
表中的S-1-5-32是内置系统域,以下RID可继续作为其后缀形成本地组的公认SID
RID | 说明 |
DOMAIN_ALIAS_RID_ADMINS
| 用于管理域的本地组。 |
DOMAIN_ALIAS_RID_USERS
| 表示域中所有用户的本地组。 |
DOMAIN_ALIAS_RID_GUESTS
| 一个表示域的来宾的本地组。 |
DOMAIN_ALIAS_RID_POWER_USERS
| 一个用于表示一个或一组用户的本地组,这些用户希望将系统视作自己的个人计算机,而不是多个用户的工作站。 |
DOMAIN_ALIAS_RID_ACCOUNT_OPS
| 一个仅存在于运行服务器操作系统的系统中的本地组。 此本地组允许控制非管理员帐户。 |
DOMAIN_ALIAS_RID_SYSTEM_OPS
| 一个仅存在于运行服务器操作系统的系统中的本地组。 此本地组执行系统管理功能,不包括安全功能。 它可以建立网络共享、控制打印机、解锁工作站并执行其他操作。 |
DOMAIN_ALIAS_RID_PRINT_OPS
| 一个仅存在于运行服务器操作系统的系统中的本地组。 此本地组控制打印机和打印队列。 |
DOMAIN_ALIAS_RID_BACKUP_OPS
| 一个用于控制文件备份和还原权限分配的本地组。 |
DOMAIN_ALIAS_RID_REPLICATOR
| 一个负责将安全数据库从主域控制器复制到备份域控制器的本地组。 这些帐户仅由系统使用。 |
DOMAIN_ALIAS_RID_RAS_SERVERS
| 一个表示 RAS 和 IAS 服务器的本地组。 此组允许访问用户对象的各种属性。 |
DOMAIN_ALIAS_RID_PREW2KCOMPACCESS
| 仅存在于运行 Windows 2000 Server 的系统中的本地组。 |
DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS
| 一个表示所有远程桌面用户的本地组。 |
DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS
| 一个表示网络配置的本地组。 |
DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS
| 一个表示任何林信任用户的本地组。 |
DOMAIN_ALIAS_RID_MONITORING_USERS
| 一个表示正在监控的所有用户的本地组。 |
DOMAIN_ALIAS_RID_LOGGING_USERS
| 一个负责记录用户的本地组。 |
DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS
| 一个表示所有授权访问的本地组。 |
DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS
| 一个仅存在于运行允许终端服务和远程访问的服务器操作系统的系统上的本地组。 |
DOMAIN_ALIAS_RID_DCOM_USERS
| 一个表示可使用分布式组件对象模型(DCOM)的用户的本地组。 |
DOMAIN_ALIAS_RID_IUSERS
| 一个表示 Internet 用户的本地组。 |
DOMAIN_ALIAS_RID_CRYPTO_OPERATORS
| 一个表示对加密运算符的访问权限的本地组。 |
DOMAIN_ALIAS_RID_CACHEABLE_PRINCIPALS_GROUP
| 一个表示可缓存的主体的本地组。 |
DOMAIN_ALIAS_RID_NON_CACHEABLE_PRINCIPALS_GROUP
| 一个表示无法缓存的主体的本地组。 |
DOMAIN_ALIAS_RID_EVENT_LOG_READERS_GROUP
| 一个表示事件日志读取器的本地组。 |
DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP
| 可以使用分布式组件对象模型 (DCOM) 连接到证书颁发机构的逻辑用户组。 |
DOMAIN_ALIAS_RID_RDS_REMOTE_ACCESS_SERVERS
| 一个表示 RDS 远程访问服务器的本地组。 |
DOMAIN_ALIAS_RID_RDS_ENDPOINT_SERVERS
| 一个表示终结点服务器的本地组。 |
DOMAIN_ALIAS_RID_RDS_MANAGEMENT_SERVERS
| 一个表示管理服务器的本地组。 |
DOMAIN_ALIAS_RID_HYPER_V_ADMINS
| 一个表示 hyper-v 管理员的本地组。 |
DOMAIN_ALIAS_RID_ACCESS_CONTROL_ASSISTANCE_OPS
| 一个表示访问控制协助 OPS 的本地组。 |
DOMAIN_ALIAS_RID_REMOTE_MANAGEMENT_USERS
| 一个表示远程管理用户的本地组。 |
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 | 一个表示可以为设备所有者进行预期设置的本地组。 |
以下是与每个域相关的RID:
值 | 说明 |
S-1-5-域-574 DOMAIN_ALIAS_RID_CERTSVC_DCOM_ACCESS_GROUP 显示名称:Builtin\Certificate Service DCOM Access | 可以使用分布式组件对象模型 (DCOM) 连接到证书颁发机构的用户组。 |
S-1-5-域-500 DOMAIN_USER_RID_ADMIN
| 域中的管理用户帐户。 |
S-1-5-域-501 DOMAIN_USER_RID_GUEST
| 域中的来宾用户帐户。 没有帐户的用户可以自动登录该帐户。 |
S-1-5-域-502 DOMAIN_USER_RID_KRBTGT 值:0x000001F6 显示名称:KRBTGT | 密钥分发中心 (KDC) 服务使用的用户帐户。 该帐户仅存在于域控制器上。 |
S-1-5-域-512 DOMAIN_GROUP_RID_ADMINS
| 域管理员的组。 此帐户仅存在于运行服务器操作系统的系统中。 |
S-1-5-域-513 DOMAIN_GROUP_RID_USERS
| 包含域中所有用户帐户的组。 所有用户都会自动添加到此组中。 |
S-1-5-域-514 DOMAIN_GROUP_RID_GUESTS
| 域中的来宾组帐户。 |
S-1-5-域-515 DOMAIN_GROUP_RID_COMPUTERS
| 域计算机的组。 域中的所有计算机都是此组的成员。 |
S-1-5-域-516 DOMAIN_GROUP_RID_CONTROLLERS
| 域控制器的组。 域中的所有 DC 都是此组的成员。 |
S-1-5-域-517 DOMAIN_GROUP_RID_CERT_ADMINS
| 证书发布服务器的组。 运行证书服务的计算机是此组的成员。 |
S-1-5-域-498 DOMAIN_GROUP_RID_ENTERPRISE_READONLY_DOMAIN_CONTROLLERS
| 企业只读域控制器组。 |
S-1-5-21-根域-518 DOMAIN_GROUP_RID_SCHEMA_ADMINS
| 架构管理员的组。 此组的成员可以修改 Active Directory 架构。 |
S-1-5-域-519 DOMAIN_GROUP_RID_ENTERPRISE_ADMINS
| 企业管理员的组。 此组的成员对 Active Directory 林中的所有域具有完全访问权限。 企业管理员负责林级操作,例如添加或删除新域。 |
S-1-5-域-520 DOMAIN_GROUP_RID_POLICY_ADMINS
| 策略管理员的组。 |
S-1-5-域-521 DOMAIN_GROUP_RID_READONLY_CONTROLLERS
| 只读域控制器组。 |
S-1-5-域-522 DOMAIN_GROUP_RID_CLONEABLE_CONTROLLERS
| 可克隆域控制器组。 |
S-1-5-域-524 DOMAIN_GROUP_RID_CDC_RESERVED | 保留的 CDC 组。 |
S-1-5-域-525 DOMAIN_GROUP_RID_PROTECTED_USERS
| 受保护的用户组。 |
S-1-5-根域-526 DOMAIN_GROUP_RID_KEY_ADMINS
| 密钥管理员组。 |
S-1-5-域-527 DOMAIN_GROUP_RID_ENTERPRISE_KEY_ADMINS
| 企业密钥管理员组。 |
以下 RID 用于指定强制性完整性控制(MIC,Mandatory Integrity Control)。
MIC提供了另一种附加的对可保护对象的访问控制机制,该机制是从Windows Vista开始引入的,在实施DACL检查之前起作用。
MIC使用完整性级别和强制策略来实现访问检查。Windows定义了五个完整性级别:不信任(Untrusted)、低(Low)、中(Medium)、高(High)、系统(System)。
安全主体和可保护对象都被赋予完整性级别,由于完整性检查在DACL检查之前实施,所以即使可保护对象的DACL允许某用户访问,但若用户的进程的完整性级别较低也是不能对该可保护对象实施写入操作的。
标准用户被赋予中级完整性级别,权限被提升的用户是高级。用户启动的进程以及用户创建的对象都继承该用户的完整性级别。系统服务被赋予系统级别。没有被赋予完整性级别的可保护对象被系统按中级对象处理,这样做可防止低级别的代码修改该对象。
当用户要运行一个可执行文件时,进程的完整性级别在可执行文件完整性级别和和用户完整性级别之间取其低值,也就是说用户的进程的完整性级别不会比可执行文件的高,这有助于防止用户发起高级别的恶意代码。
安全主体和可保护对象的完整性级别使用完整性SID表示的。安全主体的完整性SID在访问令牌中,可保护对象的完整性SID被存放在SACL的一个特殊的ACE中——SYSTEM_MANDATORY_LABEL_ACE。以下就是在安全主体的访问令牌中使用的SID:
RID | 值 | 说明 | |
SECURITY_MANDATORY_UNTRUSTED_RID | 0x00000000 | 不受信任。 | |
SECURITY_MANDATORY_LOW_RID SDDL符号:LW | 0x00001000 | 低完整性。 | |
SECURITY_MANDATORY_MEDIUM_RID SDDL符号:ME | 0x00002000 | 中完整性。 | |
SECURITY_MANDATORY_MEDIUM_PLUS_RID SDDL符号:MP | SECURITY_MANDATORY_MEDIUM_RID + 0x100 | 中高完整性。 | |
SECURITY_MANDATORY_HIGH_RID SDDL符号:HI | 0X00003000 |
| |
SECURITY_MANDATORY_SYSTEM_RID SDDL符号:SI | 0x00004000 | 系统完整性。 | |
SECURITY_MANDATORY_PROTECTED_PROCESS_RID | 0x00005000 | 受保护的进程。 |
以上表格大致列举了Windows定义的公认SID以及RID,全部摘自微软文档,其中的SDDL符号由笔者在参阅对照后在表中标出,主要目的是为后面介绍安全描述符定义语言(SDDL)做铺垫,如需从事该领域的软件开发,还要具体地阅读开发文档,本文中内容可能不够全面,或Windows的相关定义可能变更。
在做了如此多的铺垫工作后,下一篇我们可以正式介绍SDDL了,敬请期待。
附:用于操作SID的函数集
函数 | 说明 | |
AllocateAndInitializeSid | 分配并初始化具有指定数量的子授权的 SID。 | |
ConvertSidToStringSid | 将 SID 转换为适合显示、存储或传输的字符串格式。 | |
ConvertStringSidToSid |
| |
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 对应的帐户名称。 |