(三)ACL
访问控制列表

DACL:自主访问控制列表(DACL)是安全描述符中最重要的,它里面包含零个或多个访问控制项(ACE,Access Control Entry),每个访问控制项的内容描述了允许或拒绝特定账户对这个对象执行特定操作。
SACL:系统访问控制列表(SACL) 主要是用于系统审计的,它的内容指定了当特定账户对这个对象执行特定操作时,记录到系统日志中。
访问控制列表(ACL)是访问控制条目(ACE)的列表。 ACL中的每个ACE都标识一个对象(通常称这个对象为受托者,受托者可以是一个用户、用户组或者是一个登陆会话),并指定允许、拒绝或审核该受托者的访问权限。可保护对象的安全描述符可以包含两种类型的ACL:DACL和SACL。
DACL标识是否允许或拒绝访问安全对象。当进程尝试访问安全对象时,系统将检查该对象的DACL中的ACE,以确定是否授予对该对象的访问权限。
如果对象没有DACL,则系统将授予所有人完全访问权限。
如果对象的DACL没有ACE,则系统将拒绝所有尝试访问该对象的尝试,因为DACL不允许任何访问权限。
系统依次检查ACE,直到找到一个或多个允许所有请求的访问权限的ACE,或者直到拒绝任何请求的访问权限为止。
下图显示了对象的DACL如何允许访问一个线程而拒绝访问另一个线程。

对于线程A,系统将读取第一条ACE并立即拒绝访问,因为拒绝访问的ACE适用于线程访问令牌中的用户。在这种情况下,系统将不检查之后的ACE。对于线程B,第一条ACE不适用,因此系统进入允许写入访问的ACE 2和允许读取和执行访问的ACE 3。
SACL使管理员可以记录任何人对安全对象的访问。每个ACE指定受托者尝试访问的类型,这些访问使系统在安全事件日志中生成记录。当访问尝试失败或成功时,SACL中的ACE可以生成审核记录。
不要尝试直接使用ACL的内容。为确保ACL在语义上正确,需使用适当的函数来创建和操作ACL。
ACL还提供对Microsoft Active Directory目录服务对象的访问控制。 Active Directory服务接口(ADSI)包括用于创建和修改这些ACL内容的例程。相关内容会另开文章详细介绍。
从ACL获取信息
微软提供了几种从访问控制列表(ACL)中检索访问控制信息的功能。这些功能包括确定ACL授予或审核指定受托者的访问权限的功能。其他功能使您能够提取有关ACL中访问控制项(ACE)的信息。
GetExplicitEntriesFromAcl函数检索描述在ACL中的ACE的EXPLICIT_ACCESS结构的数组。将ACE信息从一个ACL复制到另一个ACL时,此功能很有用。例如,对GetExplicitEntriesFromAcl的调用以在一个ACL中获取有关ACE的信息之后,可以通过在对SetEntriesInAcl函数的调用中传递返回的EXPLICIT_ACCESS结构,以在新的ACL中创建等效的ACE。
GetEffectiveRightsFromAcl函数使您能够确定DACL授予指定受托者的有效访问权限。受托人的有效访问权是DACL授予受托人或受托人为成员的任何组的访问权。 GetEffectiveRightsFromAcl检查指定DACL中的所有允许访问和拒绝访问的ACE。
使用以下步骤确定受托者对对象的访问权限:
调用
GetSecurityInfo或GetNamedSecurityInfo函数以获取指向对象的DACL的指针。调用
GetEffectiveRightsFromAcl函数以检索DACL授予指定受托者的访问权限。
GetAuditedPermissionsFromAcl函数使您可以检查SACL,以确定指定受托人或受托人所属成员的任何组的审核访问权限。审核的权限指示导致系统在安全事件日志中生成审核记录的访问尝试的类型。该函数返回两个访问掩码:一个包含对失败的访问尝试进行监视的访问权限,另一个包含对成功的访问进行监视的访问权限。 GetAuditedPermissionsFromAcl检查SACL中的所有系统审核的ACE。
创建或修改ACL
Windows支持一组功能,这些功能可以创建访问控制列表(ACL)或修改现有ACL中的访问控制项(ACE)。
SetEntriesInAcl函数创建一个新的ACL。 SetEntriesInAcl可以为ACL指定一组全新的ACE,也可以将一个或多个新ACE与现有ACL的ACE合并。 SetEntriesInAcl函数使用EXPLICIT_ACCESS结构的数组来指定新ACE的信息。每个EXPLICIT_ACCESS结构都包含描述单个ACE的信息。此信息包括访问权限、ACE的类型、控制ACE继承的标志以及标识受托者的TRUSTEE结构。
向现有ACL添加新ACE
使用
GetSecurityInfo或GetNamedSecurityInfo函数可从对象的安全描述符获取现有的DACL或SACL。对于每个新的ACE,可调用
BuildExplicitAccessWithName函数以使用描述ACE的信息填充EXPLICIT_ACCESS结构。调用
SetEntriesInAcl,为新ACE指定现有的ACL和EXPLICIT_ACCESS结构的数组。SetEntriesInAcl函数分配并初始化ACL及其ACE。调用
SetSecurityInfo或SetNamedSecurityInfo函数,将新的ACL附加到对象的安全描述符。
如果调用方指定了现有的ACL,则SetEntriesInAcl会将新的ACE信息与ACL中的现有ACE合并。例如,考虑以下情况:现有ACL授予对指定受托者的访问权限,而EXPLICIT_ACCESS结构拒绝对同一受托者的访问权限。在这种情况下,SetEntriesInAcl为受托者添加一个新的拒绝访问的ACE,并为受托者删除或修改现有的允许访问的ACE。
相关示例代码我准备了C++与C#两个版本:
C++版本代码,示例使用GetNamedSecurityInfo函数获取现有的DACL。然后,它使用有关ACE的信息填充EXPLICIT_ACCESS结构,并使用SetEntriesInAcl函数将新ACE与DACL中的任何现有ACE合并。最后,该示例调用SetNamedSecurityInfo函数将新的DACL附加到对象的安全描述符。:
C#版本,修改文件的ACL。在C#中大部分的对象都拥有SetAccessControl方法来修改其ACL,该方法需要一个安全对象需要针对特定的对象进行获取,比如文件中是FileSecurity,在注册表中是RegistrySecurity。在传入这个安全对象之前调用AddAccessRule即可增加ACE,RemoveAccessRule即可删除ACE,下面是文件的详细代码:
注册表相关ACL修改代码:
最后更新于
这有帮助吗?