Windows访问控制模型--ACL分析

概念

Windows访问控制模型由两部分组成:

  • 访问令牌(Access Token)包含用户的标识(User SID,Group SIDS)以及特权列表。
  • 安全描述符(ACL),被访问的安全对象的相关安全信息。

这里的安全对象包括:NTFS卷上的文件和目录、注册表项、网络共享、服务、进程、Active Directory对象(AD 树上的每个条目)等等。

大致认证过程

  1. A访问B
    A向B出示自己的Access Token(包含自己的用户sid,所在的组的sid以及特权列表)。
  2. B检查A
    1. B首先判断是否需要特权才能访问。如果需要,则查看A的Access Token有没有指定特权。
    2. B通过A的Access Token,把A的用户sid以及组sid跟自己的ACL做比对。来判断是否让A访问。

ACL

Windows中的ACL(Access Control List)是用来表示用户(组)权限的列表。域里面用户的身份用sid来表示,而不是用户名(objectsid属性标识它的sid)。

ACL包含DACL(权限访问控制)SACL(日志记录功能)

DACL

DACL起到的作用是权限访问控制,也就是判断一个用户能不能访问安全对象。DACL由若干条ACE构成。如下图所示,权限项目里面每一条都是ACE。

判断用户访问权限的方法
对某个文件进行访问,判断顺序是

1
2
3
4
1. 如果没有DACL,系统将允许访问
2. 如果存在DACL,但没有ACE,系统将拒绝所有访问
3. 如果存在DACL,也存在ACE,那么会按照每个ACE指定允许或拒绝
4. 如果每条ACE都没匹配上,则拒绝访问。

SRM(安全引用监视器,负责执行对象的安全访问检查等)对ACL的解析顺序是(上面第3步的解析过程)

  1. 明确定义的DENY ACE
  2. 明确定义的ALLOW ACE
  3. 继承的DENY ACE
  4. 继承的ALLOW ACE

SACL

SACL的作用是记录访问成功与否,SACL也是由一条一条的ACE构成,每条ACE的内容是某个用户访问成功/失败某个权限。当访问跟满足这条ACE的时候就会被记录下来。

域内对象的ACL

nTSecurityDescriptor属性存储该对象的ACL信息,存储格式是SDDL(Security Descriptor Definition Language)
查看某个对象的ACL(普通域用户查不了这个属性)

1
AdFind.exe -b "CN=micle,OU=研发二组,DC=rootkit,DC=org" NTSecurityDescriptor -rawsddl

下面截取部分ACL的信息

1
2
3
4
5
6
7
8
O:DA     表示owner,这条ACL的所有者(Domain Admins)
G:DA 表示primary group,Windows 通常忽略此参数(这是为了 POSIX 兼容性,但它现在已经退化了)
D: 表示DACL,里面就是ACE
(A;CIID;GW;;;S-1-5-21-1812960810-2335050734-3517558805-1103)
(OA;;WP;bf967950-0de6-11d0-a285-00aa003049e2;bf967a86-0de6-11d0-a285-00aa003049e2;S-1-5-21-1812960810-2335050734-3517558805-1133)
AI: SDDL_AUTO_INHERITED(允许DACL被继承,PAI 阻止DACL被继承)
S: 表示SACL,里面就是ACE
(OU;CIIOIDSA;WP;f30e3bbe-9ff0-11d1-b603-0000f80367c1;bf967aa5-0de6-11d0-a285-00aa003049e2;WD)

ACE

每个ACE中有6个字段,由分号分隔符分隔

  • ACE类型(允许/拒绝/审核)
  • ACE标志(继承和审计设置)
  • 权限(增量权限列表)
  • 对象类型(GUID)
  • 继承的对象类型(GUID)
  • 受托人(SID)
1
2
3
4
5
6
7
(A;CIID;GW;;;S-1-5-21-1812960810-2335050734-3517558805-1103)
A; 允许
CI; 容器继承
GW; 通用写权限
; 对象类型
; 继承的对象类型
S-1-5-21-1812960810-2335050734-3517558805-1103 受托人SID CO:Creator Owner 许多SID都有速记符号

允许sid为S-1-5-21-1812960810-2335050734-3517558805-1103的用户访问,有GW权限,并且权限可以被继承(CI)

ACE类型

Value Description
A 允许访问
D 拒绝访问
OA 允许对象访问: 仅适用于对象的一个子集。
OD 对象访问被拒绝: 仅适用于对象的一个子集。
AU 系统审计(SACL)
AL 系统报警(SACL)
OU 对象系统审计(SACL)
OL 对象系统警报(SACL)

继承类型

Value Description
CI 容器继承: 容器的子对象(如目录)将ACE作为显式ACE继承
OI 对象继承: 不是容器的子对象将ACE作为显式ACE继承
IO 仅继承: ACE不会应用于当前对象,仅通过继承影响子对象
NP 没有传播的继承: 只有直接的下级子对象继承这个ACE(子对象的子对象是不继承的)
ID ACE是继承的
SA 成功的访问审核(SACL)
FA 失败的问审核(SACL)

权限列表

  1. 通用权限(就是对这个条目的通用权限,通用读,通用写等)
  2. 域内的ACL支持某个属性的权限(一个条目包含若干个属性,通用权限是对整个条目的权限)
  3. 扩展权限(比如强制更改密码)

通用权限

Value Description Hex
GA 所有通用权限 0x10000000
GR 通用读取权限 0x80000000
GW 通用写入权限 0x40000000
GX 通用执行权限 0x20000000

更多权限标志可参考:sddl-explained

扩展权限与对某个属性权限的ACE

相较于通用权限,扩展权限与对某个属性的权限多了GUID(00299570-246d-11d0-a768-00aa006e0529)(强制更改密码)这个对象类型。

1
2
3
4
5
6
7
8
(
OA; 对象允许
;
CR; 扩展权限
00299570-246d-11d0-a768-00aa006e0529; 对象类型(GUID)
; 继承的对象类型(GUID)
S-1-5-21-1812960810-2335050734-3517558805-1178 受托人SID
)
  1. 根据GUID查扩展权限名字,扩展权限都存储在CN=Extended-Rights,CN=Configuration,DC=test,DC=localrightsGuid属性下。

    1
    adfind -b "CN=Extended-Rights,CN=Configuration,DC=test,DC=local" -f "rightsGuid=00299570-246d-11d0-a768-00aa006e0529" name
  2. 根据GUID查具体属性的名字,所有属性的都存储在结构分区里面。

    1
    adfind -schema -f "schemaIDGUID={{GUID:BF9679C0-0DE6-11D0-A285-00AA003049E2}}" -binenc name

ACL查询与修改

文件与目录的ACL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#查看指定文件或目录的ACL
icacls C:\Windows\SYSVOL\sysvol\rootkit.org

#备份指定文件(包括当前目录及其子目录中的文件)的ACL,备份结果格式是D:(A;;FA;;;SY)(A;;FA;;;BA)(A;;FA;;;S-1-5-21-649686750-1085018105-1475906644-1000)
icacls C:\Windows\SYSVOL\sysvol\rootkit.org /save Aclfile /t

#还原指定文件(包括当前目录及其子目录中的文件)的ACL,还原时,路径需要设置为上级目录。
icacls C:\Windows\SYSVOL\sysvol\ /restore AclFile /t

#添加用户test1对指定文件(包括当前目录及其子目录中的文件)的完全访问权限
icacls C:\Windows\SYSVOL\sysvol\rootkit.org /grant test1:(OI)(CI)(F) /t

#移除用户test1对指定文件(包括当前目录及其子目录中的文件)的完全访问权限
icacls C:\Windows\SYSVOL\sysvol\rootkit.org /remove test1 /t

#powershell也可以查看和编辑
Get-Acl -Path 'C:\Users\hanhan3\Desktop\1.txt'| Format-Table -wrap

(OI)代表对象继承 (CI)代表容器继承 (F)代表完全访问,查看icacls /?

注册表中的ACL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#查看指定路径的ACL
Get-Acl -Path 'HKLM:\SAM'| Format-Table -wrap

#获得Access项的具体内容
$acl = Get-Acl -Path 'HKLM:\SAM'
$acl.Access

#添加用户test1对指定路径(包括当前注册表项及其子健)的完全访问权限
$acl = Get-Acl HKLM:\SAM
$person = [System.Security.Principal.NTAccount]"test1"
$access = [System.Security.AccessControl.RegistryRights]"FullControl"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"ObjectInherit,ContainerInherit" #表示其子健继承当前注册表项的权限
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.AddAccessRule($rule)
Set-Acl HKLM:\SAM $acl

#移除用户test1对指定路径(包括当前注册表项及其子健)的完全访问权限
$acl = Get-Acl HKLM:\SAM
$person = [System.Security.Principal.NTAccount]"test1"
$access = [System.Security.AccessControl.RegistryRights]"FullControl"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"ObjectInherit,ContainerInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.RemoveAccessRule($rule)
Set-Acl HKLM:\SAM $acl

域环境中的ACL

PowerView

1
2
3
4
5
6
7
8
9
10
#获得当前域内所有对象
Get-DomainObject -Domain test.com
#获得当前域内所有对象的ACL
Get-DomainObjectAcl -Domain test.com
#获得指定用户的ACL
Get-DomainUser test1
#添加用户test1对指定对象(guid)的完全访问权限
Add-DomainObjectAcl -TargetIdentity '483e9973-2d45-4e2f-b034-f272a26950e0' -PrincipalIdentity test1 -Rights All
#移除用户test1对指定对象(guid)的完全访问权限
Remove-DomainObjectAcl -TargetIdentity '483e9973-2d45-4e2f-b034-f272a26950e0' -PrincipalIdentity test1 -Rights All

Adfind

SDDL的可阅读性太差,-sddl+++参数可以更方便阅读。(最高三个+)

1
AdFind.exe -b "CN=PC-JACK-0DAY,CN=Computers,DC=0day,DC=org" nTSecurityDescriptor -sddl+++

如果用-rawsddl ,最后一个参数就要用sid的形式。如果用-sddl+++,最后一个参数就要用账号名的形式。

1
2
3
4
5
6
#查找某个对象在域内的所有ACL权限
AdFind.exe -b "DC=rootkit,DC=org" NTSecurityDescriptor -sddl+++ -sddlfilter ;;;;;"ROOTKIT\jerry" -recmute
#查找有dcync权限的用户
AdFind.exe -b "DC=rootkit,DC=org" NTSecurityDescriptor -sddl+++ -sddlfilter ;;;Replicating Directory Changes;; -recmute
#查找具有dcsync权限的用户(数据量很大,不要用)。(这里没有用三个+,那么过滤条件就要和输出的格式保持一致)
AdFind.exe -s subtree -b "DC=rootkit,DC=org" NTSecurityDescriptor -rawsddl -sddlfilter ;;;"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2";; -recmute -resolvesids

UserAccountControl属性

Converting AD UserAccountControl Attribute Values
UserAccountControl是Active Directory 中用户和计算机帐户的最重要属性之一。该属性决定了帐户在 AD 域中的状态:帐户是活动的还是被锁定的,是否启用下次登录时更改密码的选项,用户是否可以更改自己的密码,禁止被委派,不需要Kerberos预身份验证等等。

例如有一个常规帐户的密码更改要求被禁用。userAccountControl值计算如下:
NORMAL_ACCOUNT (512) + DONT_EXPIRE_PASSWORD (65536) = 66048

UserAccountControl 标志 十六进制值 十进制值
SCRIPT(运行登录脚本) 0x0001 1
ACCOUNTDISABLE(账户被禁用) 0x0002 2
HOMEDIR_REQUIRED(主文件夹是必需的) 0x0008 8
LOCKOUT(账户被锁定) 0x0010 16
PASSWD_NOTREQD(不需要密码) 0x0020 32
PASSWD_CANT_CHANGE(防止用户更改密码) 0x0040 64
ENCRYPTED_TEXT_PWD_ALLOWED(使用可逆加密存储密码) 0x0080 128
TEMP_DUPLICATE_ACCOUNT(用户的帐户,其主帐户在另一个域中) 0x0100 256
NORMAL_ACCOUNT(默认账户,典型的活跃账户) 0x0200 512
INTERDOMAIN_TRUST_ACCOUNT 0x0800 2048
WORKSTATION_TRUST_ACCOUNT 0x1000 4096
SERVER_TRUST_ACCOUNT 0x2000 8192
DONT_EXPIRE_PASSWORD(密码不会过期的用户帐户) 0x10000 65536
MNS_LOGON_ACCOUNT 0x20000 131072
SMARTCARD_REQUIRED(要登录网络,用户需要智能卡) 0x40000 262144
TRUSTED_FOR_DELEGATION 0x80000 524288
NOT_DELEGATED 0x100000 1048576
USE_DES_KEY_ONLY 0x200000 2097152
DONT_REQ_PREAUTH(不需要 Kerberos 预身份验证) 0x400000 4194304
PASSWORD_EXPIRED(用户密码已过期) 0x800000 8388608
TRUSTED_TO_AUTH_FOR_DELEGATION 0x1000000 16777216
PARTIAL_SECRETS_ACCOUNT 0x04000000 67108864

有利用价值的ACL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#通用权限
GenericAll 授予对目标对象的完全控制权,包括WriteDacl和WriteOwner特权
GenericWrite 可以修改所有参数,因此包括对某些属性的WriteProperty,比如member
WriteOwner 修改所有者
WriteDACL 将新ACE写入目标对象的DACL的功能。例如,攻击者可以向目标对象DACL写入新的ACE,从而使攻击者可以“完全控制”目标对象。
Full Control 这个权限就具备以上所有的权限,随便挑一个特殊权限的攻击方式进行攻击就行了。

#扩展权限 AllExtendedRights
#将任意用户、组或计算机添加到目标组
AddMembers
#可以更改目标用户的密码
User-Force-Change-Password(0299570-246d-11d0-a768-00aa006e0529)
#具有这两个扩展权限的用户具备dcsync权限
DS-Replication-Get-Changes(1131f6aa-9c07-11d1-f79f-00c04fc2dcd2)
和DS-Replication-Get-Changes-All(1131f6ad-9c07-11d1-f79f-00c04fc2dcd2)
#如果对一个对象有写入spn的权限,那么就可以对这个对象进行kerberosting
servicePrincipalName

参考

[^1]: Windows内网协议学习LDAP篇之域权限上
[^2]: Windows内网协议学习LDAP篇之域权限下