Windows访问控制
Windows的访问控制模型由两个基本部分组成:
访问令牌(Access Token),包含已登录用户的信息
安全描述符(Security Descriptors),包含用于保护安全对象的安全信息
其余相关的概念还有安全标识符、特权等。
访问令牌
访问令牌是描述进程或线程安全上下文的对象,存储了与进程或线程相关联用户的标识和特权。用户在登录时,系统会先验证密码,验证通过后生成访问令牌,之后用户的所有进程都拥有此访问令牌的副本,如双击打开一个程序,就会拷贝explorer.exe
的访问令牌。
访问令牌包含以下信息:
用户帐户 (SID) 安全标识符
用户组ID
当前登录会话的登录SID
用户或用户组的权限列表
所有者SID
……
令牌分为主令牌和模拟令牌。每个进程都拥有一个主令牌,默认情况下进程的线程与安全对象交互时,使用主令牌。线程可以通过模拟客户端账户的方式,使用客户端账户的身份去与安全对象交互,这种线程具有主令牌和模拟令牌。
主令牌也叫授权令牌(Delegation Token),用于交互式登录(如RDP登录访问);而模拟令牌(Impersonation Token)用于非交互式的会话(如WMI远程访问)。访问令牌存储于内存中,重启或关机后才会清除。默认情况用户只能查看用户自己和比自己权限低的所有访问令牌。
可以通过WinDbg
等调试工具来查看访问令牌的结构。
举例,现在想查看进程Lenovo.Modern.ImController.exe
的访问令牌结构,使用命令!process 0 0 Lenovo.Modern.ImController.exe
得到进程的EPROCESS
结构的地址:
EPROCESS
是内核的一个结构,代表进程的进程对象。
之后使用!process ffff84898fc9c080
查看此进程的信息,可以得到Token地址:
接着使用!token 地址
的命令即可看到。
在用户模式下,如果不指定句柄,则显示与目标线程关联的标记,-n
参数可以显示包含用户名的信息。
安全描述符
安全描述符中包含与安全对象关联的安全信息,如:
安全标识符,包括所有者的SID和组SID
DACL(自由访问控制列表),允许或拒绝特定用户及组的访问权限
SACL(系统访问控制列表),记录特定用户及组的特定操作日志
控制位,限定安全描述符或单个成员的含义
使用WinDbg
进行双机调试,!process 0 0 cmd.exe
获得cmd.exe
的EPROCESS
结构的地址:
再使用!object fffffa8002e5bb30
查看ObjectHeader
的地址:
接着使用dt nt!_OBJECT_HEADER fffffa8002e5bb00
获得此对象的SecurityDescriptor
地址,它指向安全描述符的位置。这里的地址要计算偏移,即[address] & ~0x7
,原因参考: Determining the ACL of an Object
对于DACL或SACL,都包含了零个或多个ACE(访问控制项),主要内容为:
受信任的用户的SID
控制权限的访问掩码(Mask)
ACE类型的标志
一组位标志,确定子对象是否可以继承主对象相关的ACE
ACE主要有三种类型是所有安全对象都支持的:
允许访问,在 DACL 中用于允许访问者访问权限
拒绝访问,在 DACL 中用于拒绝访问者访问权限
审核访问,在SACL中生成审核记录
以上面的图为例,DACL中第一个ACE的类型为ACCESS_ALLOWED_ACE
,即允许操作;Mask
为掩码,指代对应的权限,所以这个ACE的含义就是允许SID为S-1-5-32-544
的对象对此安全对象做0x001fffff
的操作。
安全标识符
上面多次提到了安全标识符(SID),它是用来标识受信者的唯一值,长度可变。每个账户都有一个唯一的SID,存储在安全数据库中,用户每次登录,系统都会检索相应的SID并放入访问令牌中。
SID的组成如下图:
Windows中常见的组或身份及SID:
S-1-0-0
:空 SID,不包含任何成员的组S-1-1-0
:World,包含所有用户的组S-1-3-0
:Creator Owner,要由创建新对象的用户的安全标识符替换的安全标识符S-1-3-1
:Creator Group,要由创建新对象的用户的主组 SID 替换的安全标识符S-1-5-18
:Local SYSTEM,操作系统使用的特殊帐户S-1-5-11
:Authenticated Users,经过身份验证的用户S-1-5-7
:Anonymous,匿名登录或空会话登录S-1-5-21
:not unique,这里的不唯一指的是此SID会标识多个用户或组,但后面的RID不同,保证了不会出现重复的SID
常见的域内RID及代表的用户或组:
500:域中的管理用户帐户
512:域管理员组, 此帐户仅存在于运行服务器操作系统的系统上
501:域中的来宾用户帐户,没有帐户的用户可以自动登录到此帐户
权限检查流程
Windows的权限检查流程是通过访问令牌和安全描述符相结合实现的。当线程尝试访问安全对象时,如果该对象没有DACL,则允许访问;如果存在DACL,则会在DACL中进行查找,允许或拒绝访问。
这个查找是一个比对的过程,将线程的访问令牌中的受信者与每个ACE中的受信者按顺序进行比对,直到发生下列事件之一:
某条ACE拒绝令牌中受信者之一的所有访问权限
一条或多条ACE允许令牌中受信者的所有访问权限
如果对比完了所有ACE,还有一个及以上的访问请求没有显式允许,那么将隐式拒绝访问
线程A被拒绝访问,因为在对比的时候,类型为拒绝访问的ACE1的受信者中含有一个线程A的受信者;线程B被允许访问,因为依次对比的时候,线程B的两个受信者分别在ACE2和ACE3都符合受信者的身份要求。
从上面的例子可以看出,DACL中ACE的顺序非常重要,不同的顺序会造成不同的结果。
权限
权限是指账户的权限,用于在本地计算机上执行各种与系统相关的操作,例如关闭系统等。
通过whoami /priv
命令可以查看当前用户的权限信息:
权限和上面的访问控制有两点不同:
权限控制的是对系统资源和相关任务的访问,而访问控制则针对安全对象
系统管理员可以将权限分配给用户或组,而系统则根据安全描述符相关来授予或拒绝对安全对象的访问权限
当用户执行特权操作时,系统会检查用户是否具有此特权,如果具有,则检查是否启用了此特权,是则允许执行,否则将拒绝。
访问令牌中存在用户及所属组的特权信息:
注意,这些特权仅适用于本地计算机,而域帐户可以在不同的计算机上具有不同的权限。
用户帐户控制
用户帐户控制(UAC)可以防止恶意程序损害计算机,通过UAC,应用程序可以始终在非管理员权限下运行,除非管理员显式授予权限。
当普通用户运行需要管理员权限的应用程序时,UAC会要求该用户提供管理员级别的访问凭据。
在UAC下,管理员登录时,系统会授予一个普通用户令牌和一个管理员令牌,普通用户令牌用来执行不需要管理员权限的应用程序,Explorer.exe
也是使用普通令牌启动的,所以用户启动的其他应用程序同样是普通用户权限。
Last updated