0


Windows安全——访问控制概述

在Windows安全体系中,授权(Authorizatiion)是授予个人使用系统和其中存储的数据的权利。通常由系统管理员设置并根据用户身份进行验证。

授权是Windows安全机制中一个非常重要的环节,由于要应对各种应用场景,所以授权成为一个庞大复杂的体系。今天我只根据从微软文档学习到的内容粗浅地介绍一下该体系中一个最基本的部分——访问控制模型(Access Control Modal),作为大家深入了解Windows安全体系的一篇入门文章吧。

访问控制模型是一种用于管理和控制用户对系统资源的访问权限的方法。访问控制指的是操作系统控制哪些用户可以访问操作系统中资源的安全特性。

应用程序也可以通过调用访问控制函数来设置哪些用户可以访问特定资源或控制对应用程序提供的资源的访问。本文概述介绍了用于控制对Windows对象(如文件)的访问以及对管理功能(如设置系统时间或审计用户操作)的访问的控制模型。

访问控制模型允许您控制进程访问可保护对象或执行各种系统管理任务的能力。

访问控制模型由两个基本部分组成:

l访问令牌(Access tokens):包含关于登录用户的信息。

l安全描述符(Security descriptors): 包含保护可保护对象的安全信息。

访问令牌用于验证用户身份并包含关于其权限级别的信息,而安全描述符则定义了资源的安全属性,包括哪些用户或用户组对资源有何种访问权限。

开始之前先介绍一下什么是可保护对象:

可保护对象(Securable Objects)

可保护对象是可以拥有安全描述符的对象。所有的命名Windows对象都是可保护对象。某些未命名的对象,如进程和线程对象,也可以拥有安全描述符。对于大多数可保护对象,您可以在创建对象的函数调用中指定该对象的安全描述符。例如,可以在CreateFile和CreateProcess函数中指定安全描述符。此外,Windows安全功能还允许您获取和设置在Windows之外的操作系统上创建的可保护对象的访问信息。

Windows安全功能还为使用私有、应用程序定义的对象的操作提供了支持。

每种可保护对象类型都定义了自己的特定访问权限集和自己的通用访问权限映射。

以下表格显示了用于操作一些常见可保护对象的安全信息的函数。

对象类型

安全描述符操作函数

NTFS文件系统中的文件和目录

GetNamedSecurityInfo, SetNamedSecurityInfo, GetSecurityInfo, SetSecurityInfo

命名管道(Named pipes),匿名管道(Anonymous pipes)

GetSecurityInfo, SetSecurityInfo

进程、线程

GetSecurityInfo, SetSecurityInfo

文件映射对象(File-mapping objects)

GetNamedSecurityInfo, SetNamedSecurityInfo,GetSecurityInfo, SetSecurityInfo

访问令牌

SetKernelObjectSecurity, GetKernelObjectSecurity

窗口管理对象 (窗口站、桌面)

GetSecurityInfo, SetSecurityInfo

注册表键

GetNamedSecurityInfo, SetNamedSecurityInfo,GetSecurityInfo, SetSecurityInfo

Windows 服务

GetNamedSecurityInfo, SetNamedSecurityInfo,GetSecurityInfo, SetSecurityInfo

本地或远程打印机

GetNamedSecurityInfo, SetNamedSecurityInfo,GetSecurityInfo, SetSecurityInfo

Network shares

GetNamedSecurityInfo, SetNamedSecurityInfo,GetSecurityInfo, SetSecurityInfo

进程间同步对象(事件、互斥对象、信号灯、可等待定时器)

GetNamedSecurityInfo, SetNamedSecurityInfo,GetSecurityInfo, SetSecurityInfo

任务对象

GetNamedSecurityInfo, SetNamedSecurityInfo,GetSecurityInfo, SetSecurityInfo

目录服务对象

由活动目录处理

一、访问令牌(Access Tokens)

访问令牌(Access Token)是描述进程或线程的安全上下文的对象。令牌中的信息包括与该进程或线程相关联的用户账户的身份和权限。当用户登录时,系统通过将密码(或其他认证手段,如指纹)与安全数据库中的信息进行比对来验证用户的身份。如果密码通过认证,系统将生成一个访问令牌。代表该用户执行的每个进程都有一个访问令牌的副本。当线程与可保护对象交互或尝试执行需要权限的系统任务时,系统使用访问令牌来识别用户。

访问令牌包含安全标识符(SID),用于标识用户的账号以及用户所属的任何组账号。该令牌还包含用户或用户组所持有的特权列表。当进程试图访问一个可保护对象或执行需要特权的系统管理任务时,系统使用此令牌来识别相关的用户。访问令牌的组成如下:

l用户账户的安全标识符(SID)

l用户所属的组的SID

l用于标识当前登录会话的登录SID

l用户或用户所属组持有的权限列表

l所有者SID

l主要组的SID

l当用户创建一个可保护对象但没有指定安全描述符时系统使用的默认DACL

l访问令牌的来源

l令牌是主要令牌还是模拟令牌

l可选的限制SID列表

l当前模拟级别

l其他统计数据

每个进程都有一个主令牌(Primary Token),该令牌描述与进程关联的用户帐户的安全上下文。默认情况下,当进程的线程与可保护对象进行交互时,系统使用主令牌。此外,线程可以模拟客户账户身份。模拟允许线程使用客户的安全上下文与可保护对象交互。正在模拟客户的线程同时具有主令牌和模拟令牌(Impersonation Token)。

l受限令牌(Restricted Tokens)

受限令牌是通过CreateRestrictedToken函数修改的主要或模拟访问令牌。在受限令牌的安全上下文中运行的进程或模拟线程受到限制,无法访问受保护对象或执行特权操作。CreateRestrictedToken函数可以通过以下方式对令牌进行限制:

l从令牌中删除特权。

l对令牌中的SID应用拒绝属性(见后面描述)

l指定一组限制性SID,可限制对可保护对象的访问。

您可以在调用CreateProcessAsUser函数时使用受限主令牌。通常,调用CreateProcessAsUser的进程必须具有SE_ASSIGNPRIMARYTOKEN_NAME特权,而这种特权通常只由系统代码或在LocalSystem帐户下运行的服务持有。然而,如果CreateProcessAsUser调用指定了调用者主令牌的受限版本,则不需要此特权。这使普通应用程序能够创建受限进程。

您还可以在ImpersonateLoggedOnUser函数中使用受限主要或模拟令牌。要确定一个令牌是否有限制性SID列表,请调用IsTokenRestricted函数。

注意:

使用受限令牌的应用程序应该将受限应用程序运行在默认桌面之外的桌面上。这是必要的,以防止受限应用程序通过SendMessage或PostMessage对默认桌面上的非受限应用程序进行攻击。如果必要,可在桌面之间切换。

顺便介绍一下什么时特权(Privilege)。

特权(Privilege)

特权(Privilege)是帐户(如用户或组帐户)在本地计算机上执行各种与系统相关的操作的权利,例如关闭系统、加载设备驱动程序或更改系统时间。特权与访问权有两点不同:特权控制对系统资源和与系统相关的任务的访问,而访问权控制对可保护对象的访问。

系统管理员分配特权给用户和组帐户,而系统根据对象的访问控制列表(DACL)中授予的访问权来授予或拒绝对可保护对象的访问。

每个系统都有一个帐户数据库,用于存储用户和组帐户持有的特权。当用户登录时,系统生成一个包含用户特权列表的访问令牌,包括授予用户或用户所属组的特权。请注意,特权仅适用于本地计算机;域帐户在不同计算机上可能具有不同的特权。

当用户尝试执行特权操作时,系统会检查用户的访问令牌,以确定用户是否具有必要的特权,如果是,则检查特权是否已启用。如果用户未通过这些测试,系统将不执行该操作。

要确定访问令牌中包含的特权,调用GetTokenInformation函数,该函数还指示哪些特权已启用。大多数特权默认情况下是禁用的。

Windows API定义了一组字符串常量,如SE_ASSIGNPRIMARYTOKEN_NAME,用于标识各种特权。这些常量在所有系统上都相同,并在Winnt.h中定义。有关Windows定义的特权表,请参见Privilege Constants。然而,获取和调整访问令牌中的特权的函数使用LUID类型来标识特权。特权的LUID值可能因计算机而异,也可能在同一计算机上的不同引导之间不同。要获取与一个字符串常量相对应的当前LUID,请使用LookupPrivilegeValue函数。使用LookupPrivilegeName函数将LUID转换为其相应的字符串常量。

系统提供了一组显示名称,用于描述每个特权。当您需要向用户显示特权的描述时,可以使用LookupPrivilegeDisplayName函数检索与特权的字符串常量相对应的描述字符串。例如,在使用美国英语的系统上,SE_SYSTEMTIME_NAME特权的显示名称为"Change the system time"。

您可以使用PrivilegeCheck函数确定访问令牌是否持有指定的一组特权。这主要对正在模拟客户端的服务器应用程序很有用。

系统管理员可以使用管理工具(如User Manager)为用户和组帐户添加或删除特权。管理员还可以以编程方式使用本地安全性权威(LSA)函数来处理特权。LsaAddAccountRights和LsaRemoveAccountRights函数向帐户添加或删除特权。LsaEnumerateAccountRights函数枚举指定帐户持有的特权。LsaEnumerateAccountsWithUserRight函数枚举持有指定特权的帐户。

lSID属性

访问令牌中的用户和组安全标识符(SID)每个都具有一组属性,控制系统在访问检查中如何使用SID。以下表列出了控制访问检查的属性。

属性

说明

SE_GROUP_ENABLED

具有此属性的SID已启用访问检查。当系统执行访问检查时,它会检查适用于访问令牌中已启用SID之一的访问允许和访问拒绝的访问控制条目(ACE)。除非设置了SE_GROUP_USE_FOR_DENY_ONLY属性,否则在访问检查期间将忽略没有此属性的SID。

SE_GROUP_USE_FOR_DENY_ONLY

具有此属性的SID是仅拒绝的SID。当系统执行访问检查时,它会检查适用于该SID的访问拒绝ACE,但会忽略该SID的访问允许ACE。如果设置了此属性,则SE_GROUP_ENABLED属性未设置,且SID无法重新启用。

若要设置或清除组SID的SE_GROUP_ENABLED属性,请使用AdjustTokenGroups函数。无法禁用具有SE_GROUP_MANDATORY属性的组SID。无法使用AdjustTokenGroups禁用访问令牌的用户SID。

要确定令牌中的SID是否已启用(即是否具有SE_GROUP_ENABLED属性),请调用CheckTokenMembership函数。

若要设置SID的SE_GROUP_USE_FOR_DENY_ONLY属性,请在调用CreateRestrictedToken函数时将该SID包含在指定的仅拒绝SID列表中。

要获取SID的属性,请使用GetTokenInformation函数,其参数为TokenGroups。该函数返回一个SID_AND_ATTRIBUTES结构数组,用于标识组SID及其属性。

二、安全描述符(Security Descriptor)

当创建一个可保护对象时,系统会为其分配一个安全描述符,其中包含由创建者指定的安全信息,或者如果没有指定则使用默认的安全信息。应用程序可以使用函数来检索和设置现有对象的安全信息。安全描述符标识了对象的所有者,并且还可以包含以下访问控制列表(ACL):

l自由访问控制列表(DACL),用于标识被允许或拒绝访问该对象的用户和组。

l系统访问控制列表(SACL),用于控制系统如何审计对该对象的访问尝试。

访问控制列表(ACL)包含一系列访问控制条目(ACE)。每个ACE指定了一组访问权限,并包含一个标识了受信任实体(trustee)的SID,对该受信任实体允许、拒绝或者审计这些权限。受信任实体可以是用户帐户、组帐户或登录会话。

[p19-1]受信任实体(Trustees)

受信任实体是应用访问控制条目(ACE)的用户账户、组账户或登录会话。访问控制列表(ACL)中的每个ACE都有一个安全标识符(SID),用于标识受信任实体。

用户账户包括人类用户或诸如Windows服务等程序用于登录到本地计算机的账户。

组账户不能用于登录计算机,但在ACE中非常有用,可以允许或拒绝一组访问权限,适用于一个或多个用户账户。

标识当前登录会话的登录SID,只有在用户注销之前才有效,用于允许或拒绝访问权限。

访问控制函数使用TRUSTEE结构来识别受信任实体。TRUSTEE结构使您可以使用名称字符串或SID来识别受信任实体。如果使用名称,从TRUSTEE结构创建ACE的函数将执行分配SID缓冲区和查找与账户名称对应的SID的任务。有两个辅助函数BuildTrusteeWithSid和BuildTrusteeWithName,它们用指定的SID或名称初始化TRUSTEE结构。

BuildTrusteeWithObjectsAndSid和BuildTrusteeWithObjectsAndName允许您使用特定于对象的ACE信息初始化TRUSTEE结构。另外三个辅助函数GetTrusteeForm、GetTrusteeName和GetTrusteeType用于检索TRUSTEE结构各成员的值。

TRUSTEE结构的ptstrName成员可以是指向OBJECTS_AND_NAME或OBJECTS_AND_SID结构的指针。这些结构除了受信任实体名称或SID之外,还指定了特定于对象的ACE信息。这使得诸如SetEntriesInAcl和GetExplicitEntriesFromAcl等函数可以将特定于对象的ACE信息存储在EXPLICIT_ACCESS结构的Trustee成员中。

1结构

安全描述符包含与可保护对象相关联的安全信息。安全描述符由 SECURITY_DESCRIPTOR 结构及其相关的安全信息组成。安全描述符可以包括以下安全信息:

  • 定义对象所有者和主要组的安全标识符(Security Identifiers,SIDs)。

  • 两个ACL: 自由访问控制列表DACL(Discretionary Access Control List)和系统访问控制列表SACL(System Access Control List)。

访问控制列表(ACL)是一个访问控制条目(ACE)的列表。

不要直接处理ACL的内容。为了确保ACL在语义上是正确的,请使用适当的函数来创建和操作ACL。

ACL还为Microsoft Active Directory服务对象提供访问控制。Active Directory服务接口(ADSI)包括用于创建和修改这些ACL的内容的例程。

l指定允许或拒绝特定用户或组访问权限的自由访问控制列表(Discretionary Access Control List,DACL)。

自由访问控制列表(DACL)确定了允许或拒绝访问可保护对象的服务受信任实体。

l指定生成用于该对象的审核记录的访问尝试类型的系统访问控制列表(System Access Control List,SACL)。

系统访问控制列表(SACL)允许管理员记录对受保护对象的访问尝试。每个ACE指定了特定受信任实体的访问尝试类型,导致系统在安全事件日志中生成记录。SACL中的ACE在访问尝试失败时、成功时或两者都可能生成审计记录。更多有关SACL的信息,请参阅审计生成和SACL访问权。

  • 一组控制位,用于限定安全描述符或其各个成员的含义。例如与ACE的自动继承相关的控制位,标志是否持有DACL以及是否是默认DACL的标志位,用于资源管理器的标志位等等。

要获取安全描述符的控制信息,请调用GetSecurityDescriptorControl函数。要设置与自动ACE继承相关的控制位,请调用SetSecurityDescriptorControl函数。其他控制位由设置安全描述符组件的各个函数设置。例如,如果您使用SetSecurityInfo更改对象的DACL,该函数将设置或清除位,以指示安全描述符是否有DACL、是否为默认DACL等。另一个示例是安全描述符中包含的资源管理器(RM)控制位。这些位根据资源管理器的实现使用,并通过GetSecurityDescriptorRMControl和SetSecurityDescriptorRMControl函数访问。

2.操作

(1)设置安全描述符中的安全信息

l创建及修改ACL

SetEntriesInAcl 函数用于创建一个新的访问控制列表(ACL)。SetEntriesInAcl 可以为 ACL 指定全新的 ACE(访问控制项),也可以将一个或多个新的 ACE 与已存在的 ACL 的 ACE 进行合并。SetEntriesInAcl 函数使用一个 EXPLICIT_ACCESS 结构体数组来指定新的 ACE 的信息。每个 EXPLICIT_ACCESS 结构体包含描述单个 ACE 的信息,包括访问权限、ACE 类型、控制 ACE 继承的标志以及标识受托方 (TRUSTEE) 的结构体。

l向现有ACL添加新的ACE

1).使用GetSecurityInfo或GetNamedSecurityInfo函数从对象的安全描述符获取现有的DACL或SACL。

2).对于每个新的ACE,调用BuildExplicitAccessWithName函数以填充一个EXPLICIT_ACCESS结构,其中包含描述ACE的信息。

3).调用SetEntriesInAcl,指定现有的ACL和新的ACE的EXPLICIT_ACCESS结构数组。SetEntriesInAcl函数分配并初始化ACL及其ACE。

4).调用SetSecurityInfo或SetNamedSecurityInfo函数将新的ACL附加到对象的安全描述符。

如果调用者指定现有的ACL,则SetEntriesInAcl将新的ACE信息与ACL中现有的ACE合并。考虑例如,其中现有的ACL授予对指定trustee的访问权限,而EXPLICIT_ACCESS结构拒绝对该trustee的访问权限。在此情况下,SetEntriesInAcl将为trustee添加一个新的访问被拒绝的ACE,并删除或修改现有的访问被允许的ACE for the trustee。

(2)获取安全描述符中的安全信息

l从ACL获取信息

几个函数被提供以从访问控制列表(ACL)检索访问控制信息。这包括确定ACL授予或审计特定受信任实体的访问权限的函数。其他函数使您能够提取ACL中访问控制条目(ACE)的信息。

l确定ACL授予或审计特定受信任实体的访问权限:

要确定受信任实体对于对象的访问权限,请按照以下步骤操作:

1). 调用GetSecurityInfo或GetNamedSecurityInfo函数以获取对象的DACL的指针。

2). 调用GetEffectiveRightsFromAcl函数以检索DACL授予特定受信任实体的访问权限。

.

l提取ACE的信息:

GetExplicitEntriesFromAcl函数检索一个EXPLICIT_ACCESS结构的数组,描述了ACL中的ACE。这在将ACE信息从一个ACL复制到另一个ACL时非常有用。例如,调用GetExplicitEntriesFromAcl以获取一个ACL中的ACE信息后,可以将返回的EXPLICIT_ACCESS结构传递给SetEntriesInAcl函数,以在新的ACL中创建等效的ACE。

GetEffectiveRightsFromAcl函数使您能够确定DACL授予特定受信任实体的有效访问权限。受信任实体的有效访问权限是由DACL授予受信任实体的访问权限或受信任实体所属的任何组的访问权限。GetEffectiveRightsFromAcl检查指定DACL中的所有访问允许和访问拒绝ACE。

l检查SACL中特定受信任实体或其所属任何组的审计权限:

GetAuditedPermissionsFromAcl函数使您能够检查SACL以确定特定受信任实体或其所属任何组的审计访问权限。审计权限表示导致系统在安全事件日志中生成审计记录的访问尝试类型。该函数返回两个访问掩码:一个包含失败访问尝试的监视访问权限,另一个包含成功访问的监视访问权限。GetAuditedPermissionsFromAcl检查SACL中的所有系统审计ACE。

(3)为新建对象创建和初始化安全描述符

当您创建可保护对象时,可以将安全描述符分配给新对象。创建可保护对象的函数(如CreateFile或RegCreateKeyEx)具有指向SECURITY_ATTRIBUTES结构的指针参数,该结构可以包含新对象的的安全描述符的指针。

管理对象的系统组件或服务器可以将指定的默认安全描述符存储为对象的持久属性。如果对象的创建者未指定安全描述符,则系统使用继承的默认安全信息来创建安全描述符。您可以使用函数更改对象安全描述符中的信息。

新对象DACL的创建

系统使用以下算法为大多数新可保护对象(统使用不同的算法为新的Active Directory对象构建DACL)构建DACL:

1). 对象DACL来自对象创建者指定的安全描述符。系统将任何可继承的ACE合并到指定的DACL中,除非SE_DACL_PROTECTED位在安全描述符的控制位中设置。

2). 如果创建者未指定安全描述符,则系统从可继承的ACE构建对象的DACL。

3). 如果没有指定安全描述符且不存在可继承的访问控制列表(ACE),则对象的DACL是创建者主体或模拟令牌的默认DACL。

4). 如果没有指定、继承或默认的DACL,系统将创建不带DACL的对象,允许所有人对该对象进行完全访问。

新对象SACL的创建

系统使用以下算法为大多数类型的新的可保护对象(系统使用不同的算法为新的Active Directory对象构建SACL)构建SACL:

1). 对象的SACL是创建者指定的安全描述符中的SACL。系统将任何可继承的ACE合并到指定的SACL中,除非安全描述符的控制位设置了SE_SACL_PROTECTED位。即使设置了SE_SACL_PROTECTED位,来自父对象的SYSTEM_RESOURCE_ATTRIBUTE_ACEs和SYSTEM_SCOPED_POLICY_ID_ACEs也将被合并到新对象中。

2). 如果创建者没有指定安全描述符,则系统从可继承的ACE构建对象的SACL。

3). 如果没有指定或继承的SACL,则对象没有SACL。

要为新对象指定SACL,对象的创建者必须启用了SE_SECURITY_NAME特权。如果新对象的指定SACL只包含SYSTEM_RESOURCE_ATTRIBUTE_ACEs,则不需要SE_SECURITY_NAME特权。如果对象的SACL是从继承的ACE构建的,则创建者不需要此特权。

新对象的所有者(Owner)

一个对象的所有者隐式地对该对象具有WRITE_DAC访问权限。这意味着所有者可以修改对象的DACL,从而控制对该对象的访问。

新对象的所有者是创建进程的主或模拟令牌的默认所有者安全标识符 (SID)。

启用了SE_TAKE_OWNERSHIP特权的进程可以将自身设置为对象的所有者。启用了SE_RESTORE_NAME特权或具有WRITE_OWNER访问权限的进程可以将任何有效的用户或组SID设置为对象的所有者。

新对象的主组(Primary group)

新对象的主组是创建者指定的安全描述符中的主组。如果对象的创建者没有指定主组,则对象的主组是创建者的主或模拟令牌的默认主组。

3.ACE

访问控制列表(ACL)中的每个ACE都标识了一个受信任的实体,并指定了该实体被允许、拒绝或审计的访问权限。

访问控制条目(ACE)是访问控制列表(ACL)中的一个元素。一个ACL可以有零个或多个ACE。每个ACE通过指定的受信任实体来控制或监控对对象的访问。

有六种ACE类型,其中三种由所有可保护对象支持,另外三种是由目录服务对象支持的特定对象的ACE(Object-specific ACE)。

所有ACE类型都包含以下访问控制信息:

  • 安全标识符(SID):标识ACE适用于哪个受信任实体。

  • 访问掩码:指定ACE控制的访问权限。

  • 指示ACE类型的标志。

  • 一组位标志:确定子容器或对象是否可以从附加了ACL的主对象继承ACE。

以下表列出了所有可保护对象支持的三种ACE类型。

ACE类型

说明

访问拒绝ACE(Accessdenied ACE)

在DACL中拒绝某可信任实体的访问

访问允许ACE(Accessallowed ACE)

在DACL中允许某可信任实体的访问

系统审核ACE(Systemaudit ACE)

当受信任实体试图执行指定的访问权限时生成审核记录

现在简要介绍一下目录服务对象的三种ACE类型——Object-Specific ACEs。特定对象的ACE适用于目录服务(DS)对象。一个特定对象的ACE包含一对GUID,扩展了ACE保护对象的方式。

GUID

说明

ObjectType

规定以下之一:

-子对象类型:ACE控制创建指定类型的子对象的权限。

-属性集或属性:ACE控制读取或写入属性或属性集的权限。

-扩展权限:ACE控制执行与扩展权限关联的操作的权限。

  • 验证写入:ACE控制执行某些写入操作的权限。这些已在ACL编辑器中定义和公开的验证写入权限提供了对属性的验证写入权限,而不是通过“写入属性”权限授予的对属性的未经检查的低级写入的权限。

InheritedObjectType

指示可以继承ACE的子对象类型。继承也由ACE_HEADER中的继承标志以及放置在子对象上的继承保护来控制。

目前支持三种类型的特定对象的ACE(当前不支持系统警报对象ACE(System-alarm object ACE))。

ACE类型

说明

Accessdenied object ACE

用于DACL(禁止访问控制列表)以拒绝受信任实体对对象上的属性或属性集的访问,或者限制ACE继承到指定类型的子对象。使用ACCESS_DENIED_OBJECT_ACE结构。

Accessallowed object ACE

用于DACL以允许受信任实体对对象上的属性或属性集进行访问,或者限制ACE继承到指定类型的子对象。使用ACCESS_ALLOWED_OBJECT_ACE结构。

Systemaudit object ACE

用于SACL以记录受信任实体尝试访问对象上的属性或属性集的操作,或者限制ACE继承到指定类型的子对象。使用SYSTEM_AUDIT_OBJECT_ACE结构。

任何包含特定对象ACE的ACL必须使用版本为ACL_REVISION_DS的修订版本。

4转换字符串

有效的功能安全描述符以二进制格式包含安全信息。Windows API提供了将二进制安全描述符转换为文本字符串以及从文本字符串转换回二进制安全描述符的功能。以字符串格式表示的安全描述符不起作用,但它们对于存储或传输安全描述符信息可能是有用的。

要将安全描述符转换为字符串格式,请调用ConvertSecurityDescriptorToStringSecurityDescriptor函数。要将字符串格式的安全描述符转换回有效的功能安全描述符,请调用ConvertStringSecurityDescriptorToSecurityDescriptor函数。

(三)访问控制工作机制

当创建某种可保护对象(目录服务对象、文件、目录、注册表键和桌面都是可以具有父对象的可保护对象)时,系统组件或管理对象的服务可以存储指定或默认的安全描述符,使其成为对象的持久属性。如果对象的创建者未指定安全描述符,则系统使用继承或默认的安全信息来创建安全描述符。(可以使用函数来更改对象安全描述符中的信息)

一个对象的ACL(访问控制列表)可以包含从其父容器继承的ACE。例如,注册表子键可以从注册表层次结构中位于其上方的键继承ACE。同样,NTFS文件系统中的文件可以从包含它的目录继承ACE。ACE的ACE_HEADER结构包含一组继承标志,这些标志控制ACE的继承以及ACE对其所附加对象的影响。系统根据ACE继承的规则解释继承标志和其他继承信息。

l继承规则

系统根据一组继承规则将可继承的访问控制项(ACE)传播到子对象。系统根据DACL中ACE的首选顺序将继承的ACE放置在子对象的DACL中。系统在所有继承的ACE中设置INHERITED_ACE标志。

容器和非容器子对象继承的ACE有所不同,取决于继承标志的组合。这些继承规则对DACL和SACL均适用。

父对象ACE标志

对子对象ACL的影响

只使用OBJECT_INHERIT_ACE

对于非容器子对象,将该ACE继承为一个有效ACE

对于容器子对象,继承未仅供继承的ACE,除非NO_PROPAGATE_INHERIT_ACE也被使用了。

只使用CONTAINER_INHERIT_ACE

对于非容器子对象不起作用,对于容器子对象继承为一个有效ACE,且该ACE也是可被继承的,除非NO_PROPAGATE_INHERIT_ACE 也被使用。

CONTAINER_INHERIT_ACE和 OBJECT_INHERIT_ACE同时使用

非容器子对象和容器子对象都将其继承为一个有效ACE,且该ACE也是可被继承的,除非NO_PROPAGATE_INHERIT_ACE 也被使用。

不设置继承标志

对子对象无影响

如果继承的ACE对子对象是有效的ACE,系统将任何通用权限映射到子对象的特定权限。类似地,系统将通用安全标识符(SIDs)(如CREATOR_OWNER)映射到相应的SID。如果继承的ACE是仅继承的ACE,任何通用权限或通用SIDs都保持不变,以便在ACE被下一级子对象继承时可以适当映射。

对于容器对象,如果继承自上级的ACE既对该容器对象是有效ACE,又可被下级对象继承,那么该容器对象可能实际上继承了两个ACE,当被继承的ACE包含通用信息时就会发生这种情况。

对于容器对象,继承既对容器有效又可由其下级继承的情况,容器可能会继承两个ACE。例如可继承ACE包含通用信息,就会发生这种情况。该容器对象继承一个仅继承的ACE,其中包含通用信息,另外继承一个有效的ACE,其中的通用信息已被映射为该容器对象特有的信息。

用于目录服务对象的对象特定的ACE(Object-specific ACE)具有InheritedObjectType成员,该成员可以包含一个GUID,用于标识可以继承ACE的对象类型。如果未指定InheritedObjectType GUID,则对象特定ACE的继承规则与标准ACE相同。在指定了InheritedObjectType GUID的情况下,如果设置了OBJECT_INHERIT_ACE,则能匹配GUID的对象可以继承ACE,并且如果设置了CONTAINER_INHERIT_ACE,则匹配GUID的容器可以继承ACE。请注意,目前仅支持DS对象的对象特定ACE,并且DS将所有对象类型视为容器。

SetNamedSecurityInfo 和 SetSecurityInfo 函数支持继承访问控制项(ACE)的自动传播。例如,如果您使用这些函数向 NTFS 目录添加一个可继承的 ACE,系统将相应地将 ACE 应用于任何现有子目录或文件的访问控制列表(ACL)。

直接应用的 ACE 优先于继承的 ACE。系统通过将直接应用的 ACE 放在自由访问控制列表(DACL)中继承的 ACE 之前来实现这种优先级。当您调用 SetNamedSecurityInfo 和 SetSecurityInfo 函数设置对象的安全信息时,系统将当前的继承模型强加于目标对象下层次结构中所有对象的 ACL。对于已转换为当前继承模型的对象,安全描述符的控制字段中将设置 SE_DACL_AUTO_INHERITED 和 SE_SACL_AUTO_INHERITED 位。在构建反映当前继承模型的新安全描述符时,应注意不要改变安全描述符的语义。

系统在传播继承的 ACE 到子对象时使用以下规则:

  • 如果没有 DACL 的子对象继承 ACE,则结果是一个具有仅包含继承 ACE 的 DACL 的子对象。

  • 如果具有空 DACL 的子对象继承 ACE,则结果是具有仅包含继承 ACE 的 DACL 的子对象。

  • 如果从父对象中删除一个可继承的 ACE,则自动继承会删除子对象继承的 ACE 的任何副本。

  • 如果自动继承导致从子对象的 DACL 中删除所有 ACE,则子对象将具有空的 DACL,而不是没有 DACL。

这些规则可能会导致将一个没有 DACL 的对象转换为具有空 DACL 的对象。没有 DACL 的对象允许完全访问,但具有空 DACL 的对象不允许访问。为确保不受可继承 ACE 影响的子对象没有 DACL,请在对象的安全描述符中设置 SE_DACL_PROTECTED 标志。

这些规则已通过以下功能进行增强:

  • 可继承ACE的自动传播。

  • 区分继承的ACE和直接应用于对象的ACE的标志。

  • 允许指定可以继承ACE的子对象类型的对象特定ACE。

  • 通过在安全描述符的控制位中设置SE_DACL_PROTECTED或SE_SACL_PROTECTED位,可以阻止DACL或SACL继承ACE,但SYSTEM_RESOURCE_ATTRIBUTE_ACE和SYSTEM_SCOPED_POLICY_ID_ACE除外。

在创建新的可保护对象时,系统会检查父对象的安全描述符中是否有可继承的ACE。系统通常将任何可继承的ACE合并到新对象的安全描述符的ACL中。通过在安全描述符的控制位中设置SE_DACL_PROTECTED或SE_SACL_PROTECTED位,可以防止DACL或SACL继承ACE。

l访问可保护对象

当进程尝试访问可保护对象时,会先检查访问令牌中的信息。

如果访问令牌的SID设置了SE_GROUP_ENABLED属性,系统会在被访问对象的DACL中检查针对该SID的允许ACE和拒绝ACE。如果SID没有设置SE_GROUP_ENABLED,而是设置了SE_GROUP_USE_FOR_DENY_ONLY属性,那么只会检查针对该SID的拒绝ACE。

如果进程使用了受限制的SID,系统在检查令牌对受保护对象的访问时使用限制性SID列表。当受限制的进程或线程尝试访问可保护对象时,系统执行两个访问检查:一个使用令牌的启用SID,另一个使用限制性SID列表。只有两个访问检查都允许请求的访问权限才会授予访问。

当进程尝试访问可保护对象时,系统会检查对象的DACL中的ACE,以确定是否授予对其的访问权限。如果对象没有DACL,系统会授予每个人完全访问权限。如果对象的DACL没有ACE,系统将拒绝访问对象的所有尝试,因为DACL不允许任何访问权限。系统按顺序检查ACE,直到找到一个或多个允许所有请求的访问权限的ACE,或者拒绝任何请求的访问权限

当进程尝试访问可保护对象时,系统会按顺序查看对象的自由访问控制列表(DACL)中的访问控制条目(ACE),直到找到允许或拒绝请求的ACE为止。DACL允许用户的访问权限可能会因DACL中ACE的顺序而有所不同。因此,Windows XP操作系统定义了可保护对象DACL中ACE的首选顺序。首选顺序提供了一个简单的框架,确保拒绝访问的ACE实际上拒绝访问。对于Windows Server 2003和Windows XP,ACE的正确顺序由对象特定的ACE和自动继承引入,以下是首选顺序的描述

  1. 所有显式ACE都放置在任何继承的ACE之前。

  2. 在显式ACE组内,拒绝访问的ACE放在允许访问的ACE之前。

  3. 继承的ACE按继承的顺序放置。从子对象的父对象继承的ACE首先出现,然后是从祖父对象继承的ACE,以此类推。

  4. 对于每个级别的继承的ACE,拒绝访问的ACE放在允许访问的ACE之前。

图片

当然,并非所有ACE类型都是ACL中必需的。诸如AddAccessAllowedAceEx和AddAccessAllowedObjectAce之类的函数将ACE添加到ACL的末尾。调用者有责任确保ACE按正确的顺序添加。

lACE设置举例

目录服务(DS)对象的自由访问控制列表(DACL)可以包含一系列访问控制项(ACE),如下所示:

  1. 保护对象本身的ACE

  2. 保护对象上指定属性集的对象特定ACE

  3. 保护对象上指定属性的对象特定ACE

在此层次结构中,较高级别授予或拒绝的权限也适用于较低级别。例如,如果对象特定ACE允许对属性集进行ADS_RIGHT_DS_READ_PROP权限的受信任实体,则该受信任实体对该属性集的所有属性都具有隐式读取权限。类似地,对象本身的ACE允许ADS_RIGHT_DS_READ_PROP访问,则受信任实体对对象的所有属性都具有读取权限。

以下图示显示了一个假设的DS对象及其属性集和属性的树形结构:

图片

假设您想要允许对该DS对象的属性进行以下访问:

  • 允许A组对对象的所有属性进行读/写权限

  • 允许其他所有人对所有属性进行读/写权限,除了属性D

为此,请在对象的DACL中设置ACE,如下表所示:

受信任实体

对象 GUID

ACE 类型

访问权限

组 A

访问允许 ACE

ADS_RIGHT_DS_READ_PROP |ADS_RIGHT_DS_WRITE_PROP

Everyone

属性集 1

访问允许

对象 ACE

ADS_RIGHT_DS_READ_PROP |ADS_RIGHT_DS_WRITE_PROP

受信任实体

对象 GUID

ACE 类型

访问权限

Everyone

属性 C

访问允许

对象 ACE

ADS_RIGHT_DS_READ_PROP |ADS_RIGHT_DS_WRITE_PROP

组 A的ACE没有对象GUID,这意味着它允许访问所有对象的属性。对属性集1的对象特定ACE允许所有人访问属性A和B。另一个对象特定ACE允许所有人访问属性C。请注意,尽管此DACL没有任何拒绝访问的ACE,但它对属性D的访问隐含地拒绝了除组 A之外的所有人。

当用户尝试访问对象的属性时,系统按顺序检查ACE,直到明确授予、拒绝访问或没有更多ACE为止,在这种情况下,将隐式拒绝访问。

以上是对Windows访问控制模型的一点粗浅认识,希望能帮到大家。

标签: windows 安全

本文转载自: https://blog.csdn.net/stevenjoo67/article/details/136765390
版权归原作者 stevenjoo67 所有, 如有侵权,请联系我们删除。

“Windows安全——访问控制概述”的评论:

还没有评论