访问控制模型介绍
访问控制是指如何控制哪些安全主体(security principals ,包括用户和组,通常由唯一的SID代表)可以访问哪些被访问对象(被访问对象包括文件、文件夹、打印机、注册表项和Active Directory 域服务对象)并执行什么操作(包括对象上的读取、写入、修改或完全控制)。要实现这个访问控制的逻辑就需要一个用于代表用户身份用户信息以及权限信息的身份卡,这张身份卡就是访问令牌(Access tokens),还需要一个查看某个用户是否有权限访问某个对象的表,这张表就叫做安全描述符(Security descriptors)。
访问控制模型有两个基本部分:
- 访问令牌(Access tokens):包含了有关已登录用户的信息(与特定的windows账户关联)
- 安全描述符(Security descriptors):包含了保护安全对象的安全信息(与被访问对象关联)
访问控制的主要方式:
- 拒绝对未经授权的用户和组的访问
- 对提供给授权用户和组的访问设置定义完善的限制
访问令牌(Access tokens)
访问令牌(Access Token)是Windows操作系统用于描述进程或线程安全语境的一种对象。系统使用访问令牌来辨识拥有进程的用户,访问令牌与特定的windows账户关联,账户环境下启动的所有进程都会获得该令牌的副本,进程中的线程默认获得这个令牌。
访问令牌内容
- 用户帐户的安全标识符(SID Security Identifies)
- 用户帐户所属的用户组的SIDs
- 一个logon SID,标识当前登录会话
- 用户或用户组的特权清单
- 所有者的SID
- 主要组的SID
- 用户创建安全对象而不指定安全描述符时系统使用的默认DACL
- 访问令牌资源
- 标识令牌是为主令牌(primary token)或模拟令牌(impersonation token)
- 受限制SID的可选列表(如UAC存在时会针对某些账户删除某些特权)
- 当前模拟级别
- 其他数据
可以通whoami /all
查看,或者通过Sysinternals中的Process Explorer查看(Process Explorer->process->properties->security)
whoami /all
查看

Process Explorer 查看
Process Explorer下载地址:https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer

主令牌与模拟令牌
访问令牌分为两种类型——主令牌(primary token)和模拟令牌(Impersonation Token),每个Windows用户在登录时,系统会将登录的账号/密码哈希与安全数据库(SAM)中存储的数据进行对比验证,验证成功后才会生成访问令牌,这个授予的令牌就是主令牌。
- 主令牌:也叫授权令牌(Delegation Token ),当进程创建时Windows操作系统内核会为进程创建并分配一个主令牌,每个进程都含有一个主令牌,主令牌描述了进程相关用户账号的安全语境。值得注意的是,进程在创建时会继承其父进程的主令牌。默认情况下,当进程的线程与安全对象进行交互时,系统使用主令牌。
- 模拟令牌(Impersonation Token):使服务器应用程序能够临时采用客户端身份来访问安全对象。线程可以模拟客户端帐户,模拟允许线程使用客户端的安全语境与安全对象进行交互。模拟客户端的线程同时具有主令牌和模拟令牌。通常如下情况下会为线程创建模拟令牌(当服务端上有一个代替客户端访问资源的功能,但是服务端不具备访问特定资源的权限,此时服务端就需要借助客户端的令牌去访问指定资源,由于主令牌在客户端内存中,此时服务端就需要模拟客户端令牌用客户端令牌去访问指定资源)
模拟令牌有具有四个模拟级别:
- 匿名(Anonymous):授予类似于未识别用户的服务器访问权限。
- 标识(Identification):允许服务器验证客户端的身份,但不利用它进行对象访问。
- 模拟(Impersonation):使服务器能够以客户端的身份进行操作。
- 委托(Delegation):与模拟类似,但包括将此身份假设扩展到服务器与之交互的远程系统的能力,从而确保凭证保存。
令牌创建过程
令牌创建主要分为如下几个步骤:
- 当我们登录已经创建的账号时,Winlogin.exe进程会启动Logon UI引导用户输入密码
- Winlogin.exe进程将用户输入的账号密码发送给Lsass.exe(Local Security Authority Subsystem Service)进程
- Lsass.exe进程将用户密码通过NTLM哈希算法转换成NTLM Hash(这个步骤调用了SSP msv1_0.dll),并丢弃明文密码(在Windows 安全中有个重要思想——不保留明文密码)将NTLM Hash存入内存中,
- 同时将NTLM Hash与SAM文件中对应账户的NTLM Hash对比,如果匹配成功Lsass.exe会从SAM文件中获取用户SID、用户所属组SID,并利用SID创建安全访问令牌、并将令牌句柄和登录信息返回Winlogon.exe

本地管理员令牌
当本地管理员登录时,会创建两个访问令牌:一个具有管理员权限,另一个具有普通权限。默认情况下,当此用户执行进程时,将使用具有常规(非管理员)权限的令牌。当此用户尝试以管理员身份执行任何操作(例如“以管理员身份运行”)时,将使用UAC来请求权限。
令牌安全防御
Windows使用访问令牌来记录用户身份、验证用户权限,每个用户都有一个访问令牌。一般的攻击者会利用DuplicateTokenEx API来对令牌进行模拟盗窃。他们使用DuplicateTokenEx函数复制得到新令牌,将新令牌用于ImpersonateLoggedOnUser函数来模拟以登录用户的安全语境,同时也可以通过DuplicateTokenEx复制令牌,并使用CreateProcessWithToken API 把复制的令牌用于创建在模拟用户的安全语境中运行新进程。
禁止域管理员异机登录
域管理员用户在域环境中具有最高的权限,为了防止域管理员令牌被恶意窃取,必须禁止域管理员异机登录。如果因一些特殊情况域管理员登录了其他机器,应及时将令牌清除,以防止令牌被窃取。
开启“审计进程创建”策略
可以通过开启“审核进程创建”策略来监视令牌操作时所需要的Windows函数的动作。
1.输入gpedit.msc,进入组策略编辑器中
2.依次选择计算机配置->Windows设置->安全设置->高级审核策略配置->系统审核策略->本地组策略对象->详细跟踪->审核进程创建

3.双击打开审核进程创建界面配置成功或失败都创建审核事件

4.可以通过查看事件管理器(eventvwr.msc)来查看执行访问令牌尝试操作的记录


安全描述符(Security Descriptors,SD)
安全描述符(Security Descriptor)包含与安全对象关联的安全信息。 安全描述符由SECURITY_DESCRIPTOR结构及其关联的安全信息组成。 安全描述符可以包含以下安全信息:
安全对象(如文件、文件夹、打印机、注册表项和Active Directory 域服务对象)的所有者及其主要组(primary group)的安全标识符 (SID) 。
- 一个DACL(Discretionary Access Control List),指定允许或拒绝的特定用户或组的访问权限(如读取、写入、修改或完全控制)。
- 一个SACL(System Access Control List),指定对 对象进行哪些操作生成审核记录。
- 一组控制位,用于限定安全描述符或其单个成员的含义。
其中DACL与SACL都是ACL(访问控制列表 Access Control List)
下面是SECURITY_DESCRIPTOR的结构定义
typedef struct _SECURITY_DESCRIPTOR {
BYTE Revision;
BYTE Sbz1;
SECURITY_DESCRIPTOR_CONTROL Control;
PSID Owner;
PSID Group;
PACL Sacl;
PACL Dacl;
} SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR;
DACL与SACL
DACL(discretionary access control list) 一个访问控制列表,该列表由对象的所有者控制,并指定特定用户或组对对象可以具有的访问权限。DACL由多个授予或拒绝用户和组对某个对象的访问权限的 ACE组成。它本质上是规定访问权限的ACL。系统使用以下方式为新对象构建DACL:
- 对象当前DACL是由创建者指定并没有设置SE_DACL_PROTECTEDW位时,会继承所有父类的可继承ACE
- 如果创建者未指定安全描述符,则系统会默认继承父类可继承ACE构建DACL
- 如果未指定DACL,且没有可继承ACE则对象的DACL来自创建者的主令牌或模拟令牌的默认DALC
- 如果没有指定的、可继承的或默认的DACL则系统将会创建不具有DACL的对象,从而允许所有人完全访问。
SACL(system access control list)用于系统审计,用于指定哪些访问者进行哪些访问请求时需要记入系统日志,系统使用如下方式创建SACL
- 创建者指定对象的SACL时,如果没有在控制位中设置SE_SACL_PROTECTED位,系统将会默认继承父类可继承的ACE,但是不管设不设置SE_SACL_PROTECTED控制位,都会继承父类对象的SYSTEM_RESOURCE_ATTRIBUT_ACE和SYSTEM_SCOPED_POLICY_ID_ACE
- 如果创建者未指定安全描述符中的SACL,则系统将继承所有可继承ACE并构建SACL
- 如果创建者未指定或者没有可继承的SACL,则安全描述符中没有SACL
- 要为新建对象指定SACL则创建者需要启用SE_SECURITY_NAME权限,但要是新建对象SACL中仅包含SYSTEM_RESOURCE_ATTRIBUT_ACE则不需要SE_SECURITY_NAME权限,或者该SACL从可继承父类中继承而来也不需要SE_SECURITY_NAME权限。
查看ACL,在任何安全对象右键属性选择安全

在任何安全对象右键属性->安全->高级->权限这里就是完整的DACL

在任何安全对象右键属性->安全->高级->审计这里就是完整的SACL

ACE
ACE(access control entry 访问控制项),一个ACL可以包含零个或多个ACE。每个ACE控制或监视指定受信者(Trustees)对对象的访问。有六种类型的 ACE,其中三种受所有安全对象支持。 其他三种类型是目录服务对象支持的特定于对象的 ACE 。专门针对于对象(Object)访问控制项,用于控制对对象的访问或者对象中某个属性或属性集的访问。
所有类型的ACE都包含以下访问控制信息:
- 安全标识符(SID),用于标识ACE适用于的受托者
- 一个访问掩码(Access Mask),该掩码指定了具体的访问权限(Access Rights),也就是可以对该对象执行的操作(此掩码非常重要,后续很多漏洞会用到)
- 一个位标记,指示ACE类型的标志。
- 一组位标志,指示了安全描述符所属对象的子对象是否继承这个ACE。
下表列出了所有安全对象支持的三种 ACE 类型。
拒绝访问的 ACE(Access-denied ACE) | 在 自由访问控制列表 (DACL) 中用于拒绝对受信人的访问权限。 |
允许访问的 ACE(Access-allowed ACE) | 在 DACL 中用于允许对受信人的访问权限。 |
系统审核 ACE(System-audit ACE) | 在 系统访问控制列表中 (SACL) 用于在受信人尝试行使指定访问权限时生成审核记录。 |
特定于对象的ACE
目录服务 (DS) 对象支持特定于对象的 ACE 。 特定于对象的 ACE 包含一对 GUID,用于扩展 ACE 保护对象的方式。https://learn.microsoft.com/zh-cn/windows/win32/secauthz/object-specific-aces
ObjectType | 标识以下项之一: 1.子对象的类型。 ACE 控制创建指定类型的子对象的权限。 2.属性集或属性。 ACE 控制读取或写入属性或属性集的权利。 3.权限扩展的权利。 ACE控制执行与扩展权限相关的操作的权限。 4.经过验证的写入。 ACE 控制某些针对特定属性的写入操作只能写入特定值,这些经过验证的写入权限确保只有授权的用户可以对属性进行写入,而不是任何用户都可以随意写入任何值。 |
InheritedObjectType | 指示可以继承 ACE 的子对象的类型。 继承也由 ACE_HEADER中的继承标志以及针对子对象上放置的继承的任何保护进行控制。 |
ACE 顺序
DACL访问控制过程
- 如果对象没有DACL,则系统将授予所有人完全访问权限。
- 如果对象的DACL没有ACE,则系统将拒绝所有对象的访问尝试,因为DACL不允许任何访问权限。
- 系统依次检查ACE,直到找到一个或多个允许所有请求的访问权限的ACE,或者直到拒绝任何请求的访问权限为止。
请注意, ACE 的顺序很重要,因为系统会按顺序读取 ACE,直到授予或拒绝访问权限。 必须首先显示用户的拒绝访问 ACE;否则,当系统读取组的访问允许的 ACE 时,它将向受限用户授予访问权限。
这是利用访问令牌和安全描述符对安全主体进行访问控制的原理(遵循最小权限原则):
也可以参考微软官方文档https://learn.microsoft.com/zh-cn/windows/win32/secauthz/dacls-and-aces

安全标识符SID
SID(Security Identifier 安全标识符)用于唯一标识一个安全主体(如计算机账户、用户账户,或者是运行在用户账户或计算机账户安全语境[security context]中的线程或进程)或者一个安全组。安全主体是所有能够被操作系统验证的实体。每个安全主体都有一个由权威认证机构(如域控)颁发的SID,SID存储在一个安全数据库中。在创建账户或组时,操作系统会为每个账户或组授予一个唯一的SID。当SID被用于某个用户或组时,这个SID将不会再被分配给其他的用户或组。
每当用户登录时,操作系统会为用户创建一个访问令牌(Access Token),这个访问令牌包含用户SUID、用户权限、用户所在的所有组的SID(user’s SID, user rights, and the SIDs for any groups the user belongs to),这个令牌为用户在操作系统中执行的每个操作提供安全语境。
另外一些特定分配个域内特定用户和组的域专业SID外,还有一些针对通用组或通用用户的SID,例如Everyone and World SIDs就包含所有用户和组,这种通用SID在所有操作系统中都保持不变。
查询当前用户SID可以通过whoami /user

或者通过WIM查询wmic useraccount where name="%username%" get sid

SID如何工作
使用者以账户名作为识别账户的参考,但是在操作系统内部识别账户和进程是通过参考安全主体的安全语境下的SID实现的。SID是Windows安全模型的基础,SID与Windows Server操作系统的安全基础结构中的授权容器和访问控制技术配合使用,这有助于保护对网络资源的访问,并提供安全的计算机环境。对于域账户,在创建账户时操作系统将域SID和相对标识符(relative identifier,RID)连接形成域用户特有的SID,这个RID在同一个作用域(domain or local)中是不会被复用于其他安全主体的。
每个账户或组都会被授予独立的SID。本地账户或组的SID是由本地安全机构LSA(Local Security Authority)授予的,SID与其他账户信息被存储在注册表中的一个安全区域内。域账户或组的SID是由域安全机构(Domain Security Authority)授予的,SID被作为域中用户或组对象中的一个属性存储在域服务器中。
另外一个SID被删除后,后续创建的SID也不会与这个SID相同,例如一个员工在一个域环境下工作具有SID_A,他离开后域管理员删除了他的域账户也包括SID_A,但是后续他又回来工作,域管理员为他再创建账户时,分配的SID_B与SID_A是不同的,由于SID不同,新创建账户的权限与旧账户权限也不同。
Windows安全在以下安全元素中使用SID:
- 在安全描述符中标识对象和主要组的所有者
- 在访问控制条目(ACE)中,标识允许,拒绝或审核访问的受托者
- 在访问令牌(AC Token)中,用于标识用户和该用户所属的组
SID结构
安全标识符是二进制格式的数据结构,其中包含可变数量的值。 结构中的第一个值包含有关 SID 结构的信息。 其余的值按层次结构排列(类似于电话号码),分别标识 SID 发布机构(例如,“NT Authority”)、SID 颁发域和特定的安全主体或组。 下图演示了 SID 的结构。

下表描述了 SID 的各个值:
修订版本(Revision) | 指示在特定 SID 中使用的 SID 结构的版本。 |
标识符颁发机构(Identifier Authority) | 标识可为特定类型的安全主体颁发 SID 的最高级别的颁发机构。 例如,“Everyone”组的 SID 中的标识符颁发机构值为 1 (World Authority)。 特定 Windows Server 帐户或组的 SID 中的标识符颁发机构值为 5 (NT Authority)。 |
子颁发机构(Subauthority) | 保存 Sid 中最重要的信息,这些信息包含在一系列一个或多个子颁发机构值中。 系列中最后一个值(但不包括最后一个值)之前的所有值共同标识企业中的域。 该系列的这一部分称为域标识符。 系列中的最后一个值称为相对标识符(RID),用于标识相对于域的特定帐户或组。 |
子颁发机构(Subauthority)
保存 Sid 中最重要的信息,这些信息包含在一系列一个或多个子颁发机构值中。 系列中最后一个值(但不包括最后一个值)之前的所有值共同标识企业中的域。 该系列的这一部分称为域标识符。 系列中的最后一个值称为相对标识符(RID),用于标识相对于域的特定帐户或组。
使用标准表示法将 SID 从二进制转换为字符串格式时,SID 的组件更容易可视化:
S-R-X-Y1-Y2-Yn-1-Yn
在这种表示法中,下表描述了 SID 的组成部分:
组成 | 说明 |
S | 指示字符串是 SID |
R | 指示修订级别(Revision) |
X | 指示标识符颁发机构值(Identifier Authority) |
Y | 表示一系列子授权机构值(Subauthority),其中 n 是值的数目 |
在SID的这些部分中最终要的是-Y1-Y2-Yn-1他标识一系列子机构值,这在具有多个域(domain)的企业环境中具有指定某个域的重要作用,域标识符把指定域与其他的域区分开来。在同一企业环境下不存在两个域共享一个域标识符(domain identifier)
安全标识符中的最后一项-Yn是相对标识符(relative identifier),它用于区分同一个域下的不同安全主体(如用户、组等),这个相对标识符不会被两个不同的安全主体共享
例如,内置管理员组的 SID 以标准化 SID 表示法表示为以下字符串:
S-1-5-32-544
此 SID 包含四个组成部分:
- SID版本的修订级别 (1)
- 标识符颁发机构值(5, NT Authority)
- 域标识符 (32, Builtin)
- 相对标识符 (544, Administrators)
内置账户和组(Built-in account and group)具有固定的域标识符32(Builtin),它们的值在所有计算机中都是固定的,而这个域(Builtin)是每台运行 Windows Server 操作系统的计算机上运行的一个域(专门用来放置一些内置用户或组),由于值是固定的所以不需要区分一台计算机的内置帐户和组与另一台计算机的内置帐户和组,因为它们的范围仅限于本地。对于域环境下,域控制器上运行的Builtin域就是域环境下所有计算机的Builtin域。Builtin域内的内置账户和组的SID之间也需要区分开,所以内置这些内置账户和组的SID中相对标识符(RID)是相互独立的。
在另一个示例中,请考虑全局组“Domain Admins”的 SID。 企业中的每个域都有一个“Domain Admins”组,并且每个组的 SID 都不同。 以下示例表示 Contoso, Ltd. 域 (Contoso\Domain Admins) 中的“Domain Admins”组的 SID:
S-1-5-21-1004336348-1177238915-682003330-512
Contoso\Domain Admins 的 SID 具有:
- 修订级别 (1)
- 标识符颁发机构(5,NT Authority)
- 域标识符 (21-1004336348-1177238915-682003330, Contoso)
- 相对标识符(512,Domain Admins)
Contoso\Domain Admins 的 SID 与其域标识符为 21-1004336348-1177238915-682003330 的 SID 与同一企业中其他“Domain Admins”组的 SID 区别开。 企业中没有其他域使用此值作为其域标识符。 Contoso\Domain Admins 的 SID 与其相对标识符 512 在 Contoso 域中创建的其他帐户和组的 SID 区别开。 域中的任何其他帐户或组都没有最终值为 512 的 SID。
常见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)
SID Capability
SID Capability(能力安全标识符 Capability Security Identifier)被用于向应用软件提供访问某些特定资源的能力(如文档、摄像头、定位等)。所有的能力安全标识符都被存储在操作系统的注册表如下位置中HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SecurityManager\CapabilityClasses\AllCachedCapabilities
Capability SIDs是Windows操作系统中的一个安全特性,它们用于控制对特定操作或功能的访问权限,而不是对特定对象的访问权限。这种SID代表了执行某些系统级别的操作的能力,与用户或组的SID不同,后者通常用于标识特定的用户或组并控制对系统资源的访问。
在Windows系统中,Capability SIDs通常用于以下几个方面:
- 应用程序兼容性:允许旧的应用程序在新的操作系统上运行,即使它们使用了已经更改或删除的接口。
- 安全策略:用于定义和实现安全策略,例如,限制哪些用户或程序可以执行特定的系统级任务。
- 权限隔离:在64位的Windows系统中,Capability SIDs用于隔离32位应用程序的权限,即使它们在64位进程中运行。
- 用户权限:在用户帐户控制(UAC)机制中,Capability SIDs可以用于确定用户是否可以提升权限执行管理任务。
- 特定功能访问:例如,访问控制台会话、注册表项或文件等。
参考
https://rootclay.gitbook.io/windows-access-control 中安网星
https://learn.microsoft.com/zh-cn/windows/security/identity-protection/access-control/access-control 微软官方文档
https://zh.wikipedia.org/wiki/%E8%AE%BF%E9%97%AE%E4%BB%A4%E7%89%8C_(Windows) 访问令牌维基百科 https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/access-tokens 访问令牌 HackTricks
https://learn.microsoft.com/zh-cn/windows/win32/secauthz/access-control-lists 微软官方访问控制列表
https://learn.microsoft.com/zh-cn/windows/win32/secauthz/dacls-and-aces 微软官方ACE与ACL
https://learn.microsoft.com/zh-cn/windows/win32/secauthz/ace 微软官方文档ACE
https://learn.microsoft.com/zh-cn/windows/win32/secauthz/access-control-entries 微软官方文档ACE
https://learn.microsoft.com/zh-cn/windows/win32/secauthz/object-specific-aces 微软官方特定于对象的ACE
https://learn.microsoft.com/zh-cn/windows/win32/secauthz/aces-to-control-access-to-an-object-s-properties微软官方文档 用于控制对对象属性的访问的 ACE
https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers微软官方SID