文章目录
- [一 核心概念深化:从"名字"到"密钥锚点"](#一 核心概念深化:从“名字”到“密钥锚点”)
-
- [1.1 Kerberos 的信任模型](#1.1 Kerberos 的信任模型)
- [1.2 SPN 的深度作用原理](#1.2 SPN 的深度作用原理)
-
- [1.2.1 需要 SPN的原因](#1.2.1 需要 SPN的原因)
- [1.2.2 SPN 与 Service Account Key 的绑定](#1.2.2 SPN 与 Service Account Key 的绑定)
- [二 Kerberos 协议深层流程与报文结构](#二 Kerberos 协议深层流程与报文结构)
-
- [2.1 时序图 (包含 Pre-Auth)](#2.1 时序图 (包含 Pre-Auth))
- [2.2 关键数据结构解析](#2.2 关键数据结构解析)
-
- [2.2.1 TGT (Ticket Granting Ticket)](#2.2.1 TGT (Ticket Granting Ticket))
- [2.2.2 TGS (Service Ticket) - 白银票据伪造的关键](#2.2.2 TGS (Service Ticket) - 白银票据伪造的关键)
- [2.2.3 PAC (Privilege Attribute Certificate) - 权限校验的核心](#2.2.3 PAC (Privilege Attribute Certificate) - 权限校验的核心)
- [三 SPN 与 Kerberos 的配合原理深度图解](#三 SPN 与 Kerberos 的配合原理深度图解)
- [四 攻击场景深度剖析:从原理到实战](#四 攻击场景深度剖析:从原理到实战)
-
- [4.1 Kerberoasting (哈希爆破)](#4.1 Kerberoasting (哈希爆破))
- [4.2 Silver Ticket (白银票据) - 伪造 TGS](#4.2 Silver Ticket (白银票据) - 伪造 TGS)
- [4.3 Golden Ticket (黄金票据) - 对比理解](#4.3 Golden Ticket (黄金票据) - 对比理解)
- [五 总结与防御](#五 总结与防御)
-
- [5.1 核心逻辑](#5.1 核心逻辑)
- [5.2 防御建议 (基于原理)](#5.2 防御建议 (基于原理))
- [六 补充:SPN的注册](#六 补充:SPN的注册)
-
- [6.1 SPN注册方式](#6.1 SPN注册方式)
-
- [6.1.1 手动注册(管理员视角)](#6.1.1 手动注册(管理员视角))
- [6.1.2 自动注册(服务视角)](#6.1.2 自动注册(服务视角))
- [6.1.3 SPN 注册的底层时序图](#6.1.3 SPN 注册的底层时序图)
- [6.2 核心细节:权限与自动化配置](#6.2 核心细节:权限与自动化配置)
-
- [6.2.1 默认行为(Default Behavior)](#6.2.1 默认行为(Default Behavior))
- [6.2.2 如何开启自动化?](#6.2.2 如何开启自动化?)
- [6.2.3 为什么有时候需要手动?](#6.2.3 为什么有时候需要手动?)
- [6.3 安全视角:SPN 注册的潜在风险](#6.3 安全视角:SPN 注册的潜在风险)
Kerberos 是一个基于票据(Ticket)的认证系统,它不直接传输密码,而是传输加密的凭证。
- Client (客户端/用户):发起请求的人或程序。
- Server (服务端):提供具体服务(如文件共享、数据库、Web服务)的机器或服务账号。
- KDC (密钥分发中心) :域控制器(Domain Controller),它是整个系统的"公证人"。它包含两个逻辑组件:
- AS (Authentication Service):认证服务,负责发放第一张通行证(TGT)。
- TGS (Ticket Granting Service):票据授予服务,负责根据TGT发放访问具体服务的通行证(TGS)。
SPN (Service Principal Name) 是理解 Kerberos 的关键。如果没有 SPN,Kerberos 就无法工作。
一 核心概念深化:从"名字"到"密钥锚点"
在深入协议之前,必须纠正一个认知偏差:SPN 不仅仅是一个服务名称,它是 KDC 查找加密密钥的"索引键"。
1.1 Kerberos 的信任模型
Kerberos 的核心不是验证密码,而是验证密钥。
- Client (用户) :拥有
User Key(通常由用户密码派生)。 - Server (服务) :拥有
Service Key(通常由服务账号密码派生)。 - KDC (域控) :拥有所有账户的
Key,它是唯一的信任根。
1.2 SPN 的深度作用原理
SPN (Service Principal Name) 在 Kerberos 协议中扮演了路由与密钥锚点的双重角色。
1.2.1 需要 SPN的原因
当 Client 想要访问服务时,它必须告诉 KDC:"我要找谁"。
- 场景 :Client 想访问
MSSQL数据库。 - 问题:KDC 里可能有成千上万个用户和服务账号。如果 Client 只说"我想连数据库",KDC 不知道用谁的密钥来加密这张票据(TGS)。
- 解决 :SPN 提供了唯一标识
MSSQLSvc/server01:1433。
1.2.2 SPN 与 Service Account Key 的绑定
这是 Kerberos 能够工作的关键逻辑链条:
- 注册阶段 :管理员将 SPN (
MSSQLSvc/...) 注册在某个域用户账号(如svc_sql)下。 - 查询阶段:KDC 收到 TGS_REQ 请求,解析出 SPN。
- 密钥映射 :KDC 根据 SPN 找到绑定的账号 (
svc_sql),并提取该账号的密码哈希(NTLM Hash)。 - 加密锚点 :KDC 使用
svc_sql的哈希作为密钥,来加密返回给 Client 的 TGS 票据。
结论:SPN 是"门牌号",它决定了 KDC 应该用哪把"锁"(服务账号密码)来封死这张票据。只有持有对应钥匙的服务端才能打开。
二 Kerberos 协议深层流程与报文结构
为了理解攻击原理,我们需要拆解标准认证过程中的加密密钥变化。
2.1 时序图 (包含 Pre-Auth)
标准的 Kerberos 流程包含一个关键的 Pre-Authentication (预认证) 步骤,用于防止暴力破解用户密码。
Server(目标服务) KDC - TGS(票据授予服务) KDC - AS(认证服务) Client(用户) Server(目标服务) KDC - TGS(票据授予服务) KDC - AS(认证服务) Client(用户) 阶段一:身份预认证 (获取 TGT) 使用 krbtgt 哈希加密 TGT 使用用户密码哈希加密 Session Key。 检查 PA-DATA 是否匹配用户密码哈希 如果不匹配,直接拒绝,防止暴力破解 TGT 使用 krbtgt 哈希加密 Session Key 使用用户密码哈希加密 阶段二:服务票据申请 (获取 TGS) KDC 解密 TGT (用 krbtgt hash) 验证用户身份 根据 SPN 找到服务账号哈希 使用 SPN对应服务的哈希加密TGS Service Ticket 使用服务账号哈希加密 (Client 无法解密,只有 Server 能解) 阶段三:访问服务 (AP-REQ) Server 用自己的哈希解密 Service Ticket 提取 Session Key,验证 Authenticator alt [权限校验通过] [权限校验失败] 1. AS_REQ (请求TGT,包含用户名 + PA-DATA [加密的时间戳]) 2. AS_REP (返回加密的TGT + Session Key) 3. TGS_REQ (附带 TGT + SPN [如 MSSQLSvc/...]) 4. TGS_REP (返回加密的TGS票据,即Service Ticket) 5. AP_REQ (Service Ticket + Authenticator [时间戳]) 6. AP_REP (认证成功) 拒绝访问 (Access Denied)
- AS_REQ/AS_REP :
- Client 问 KDC:"我是 UserA"。
- KDC 验证通过后,给一张 TGT。这张票是通用的,有效期长(默认10小时),用来证明"我已经在域里登录过了"。
- TGS_REQ/TGS_REP :
- Client 拿着 TGT 问 KDC:"我想访问
MSSQLSvc/server01(SPN)"。 - KDC 找到该 SPN 绑定的服务账号(比如
svc_sql)。 - 关键点 :KDC 用
svc_sql的密码哈希加密 TGS。此时,Client 拿到了这张票,但他无法解密它,只有 Server (svc_sql) 能解开。
- Client 拿着 TGT 问 KDC:"我想访问
- AP_REQ/AP_REP (权限检查) :
- Client 把 TGS 发给 Server。
- Server 用自己的密码哈希解密 TGS。
- 真正的权限检查在这里 :Server 读取 TGS 里的 PAC (Privilege Attribute Certificate),里面包含了用户的 SID(安全标识符)和所属组。Server 拿着这些信息去查自己的 ACL(访问控制列表),决定是放行还是拒绝。
2.2 关键数据结构解析
2.2.1 TGT (Ticket Granting Ticket)
- 加密密钥 :
krbtgt账户的哈希(域控的核心密码)。 - 内容:包含 Client 的 SID、有效期、Session Key。
- 作用:证明"我已经登录过",用于后续申请其他服务的票据,无需再次输入密码。
2.2.2 TGS (Service Ticket) - 白银票据伪造的关键
- 加密密钥 :SPN 绑定的服务账号哈希。
- 内容:包含 Client 的 SID、有效期、Session Key。
- 核心逻辑:因为这张票是用"服务账号密码"加密的,所以只有该服务能解密它。
2.2.3 PAC (Privilege Attribute Certificate) - 权限校验的核心
PAC 是 TGS 内部的一个特殊数据块(通常在 KRB-CRED 或 TGS-REP 的加密数据中)。
- 内容:包含用户的 SID、用户所属的所有组 SID、特权信息。
- 校验机制 :
- Server 解密 TGS,提取 PAC。
- Server 读取 PAC 中的
SID(如S-1-5-21...)。 - Server 查询本地或域控的 ACL (Access Control List) :
Can SID S-1-5-21... access this resource? - 注意:PAC 本身是加密在 TGS 里的,攻击者无法修改 PAC 内容(除非伪造整个 TGS)。
三 SPN 与 Kerberos 的配合原理深度图解
为了彻底理解 SPN 的作用,我们将其抽象为 "查找 - 锁定 - 验证" 的过程。
Client (攻击者/用户)
2. 发送 SPN
3. 返回加密 TGS
4. 发送 TGS
5. 获取 Service Key
发起 TGS_REQ
指定 SPN: MSSQLSvc/server01
接收 TGS
离线爆破 TGS 中的 Hash
KDC
Client
Server
获得服务账号密码
KDC (域控制器)
- 查询 SPN
是
否
AD 数据库
SPN 存在吗?
获取绑定账号的 Key
报错:服务不存在
使用 Service Key 加密 TGS
Server (目标服务)
使用 Service Key 解密 TGS
读取 PAC 中的 SID/Group
检查 ACL 权限
深度解析配合原理:
- 索引 (Indexing):Client 发起请求时,必须携带 SPN。KDC 利用 SPN 在 AD 中反向查找对应的服务账号(Service Account)。
- 锁定 (Locking) :一旦找到服务账号,KDC 就锁定了该账号的密码哈希作为加密密钥 。这意味着:TGS 票据的安全性完全依赖于 SPN 绑定的那个账号的密码强度。
- 验证 (Verification):Server 收到 TGS 后,利用自己的密码哈希解密。如果解密成功,说明票据是 KDC 签发的(因为 KDC 知道这个哈希)。随后 Server 检查 PAC 中的权限。
四 攻击场景深度剖析:从原理到实战
基于上述深层原理,我们可以更精准地理解 Kerberoasting 和 Silver Ticket 的攻击逻辑。
4.1 Kerberoasting (哈希爆破)
- 前提:攻击者拥有域内普通用户权限(可以查询 AD 中的 SPN)。
- 原理 :
- 攻击者向 KDC 请求特定 SPN 的 TGS (
TGS_REQ)。 - KDC 返回一张用
Service Account Hash加密的 TGS。 - 关键点:这张 TGS 是发给 Client 的,但只有 Server 能解密。然而,攻击者作为 Client 拿到了它。
- 攻击者向 KDC 请求特定 SPN 的 TGS (
- 攻击动作 :
- 攻击者在本地使用工具(如
Rubeus)提取 TGS 中的加密数据块。 - 由于攻击者不知道 Service Account 的密码,他无法解密。
- 但是,TGS 是离线存在的。攻击者可以使用 Hashcat 或 John the Ripper 对这张票据进行暴力破解(字典攻击)。
- 攻击者在本地使用工具(如
- 结果 :一旦爆破成功,攻击者就获得了
Service Account的明文密码。
4.2 Silver Ticket (白银票据) - 伪造 TGS
- 前提 :攻击者已经通过 Kerberoasting 或其他手段获取了
Service Account Hash(例如 MSSQL 服务账号的哈希)。 - 原理 :
- KDC 生成 TGS 的逻辑是:
Encrypt(Service_Ticket_Data, Service_Account_Hash)。 - 既然攻击者知道了
Service_Account_Hash,他就不需要 KDC 了。
- KDC 生成 TGS 的逻辑是:
- 攻击动作 :
- 攻击者伪造一张 TGS 票据(Service Ticket)。
- 使用获取到的
Service Account Hash对票据进行签名/加密。 - 篡改 PAC :在伪造的 PAC 中,将用户的 SID 修改为
Domain Admin(S-1-5-21...-500)。
- 结果 :
- 攻击者拿着这张伪造的 TGS 访问 MSSQL。
- Server 用自己的哈希解密 TGS -> 成功(因为签名是伪造但密钥是对的)。
- Server 读取 PAC -> 发现用户是 Domain Admin -> 直接放行。
4.3 Golden Ticket (黄金票据) - 对比理解
- 区别 :Golden Ticket 使用的是
krbtgt的哈希。 - 后果 :拥有 krbtgt 哈希意味着攻击者可以伪造任何用户的 TGT,从而获得域内任意权限(包括访问其他服务)。这是比 Silver Ticket 更严重的威胁。
五 总结与防御
5.1 核心逻辑
- SPN = 服务的唯一身份证,也是 KDC 查找加密密钥的索引。
- TGS = 访问特定服务的通行证,其安全性取决于 SPN 绑定的服务账号密码强度。
- PAC = 权限说明书,Server 根据 PAC 中的 SID/Group 决定放行还是拒绝。
5.2 防御建议 (基于原理)
- 强密码策略 :由于 Kerberoasting 本质是爆破服务账号密码,必须强制要求运行在域用户下的服务(如 MSSQL, IIS AppPool)使用长且复杂的密码。
- 最小权限原则 :不要给服务账号分配不必要的组权限。如果
svc_sql不需要访问文件服务器,就不要把它加入相关组,这样即使被爆破,危害也有限。 - 监控 SPN 变更:监控 AD 中 SPN 的异常注册或修改,防止攻击者将恶意 SPN 绑定到受控账号上。
- 禁用不必要的委派:如果服务不需要 Kerberos 委派(Delegation),请在 AD 属性中关闭该选项,防止票据被劫持用于横向移动。
六 补充:SPN的注册
- SPN存储与最终生效的地方 :域控制器 (Domain Controller, DC) 。AD 数据库 (
NTDS.dit) 存储在 DC 上,SPN 属性是 AD 对象的一个字段。 - 发起操作的人/机器 :通常是管理员的电脑 (手动)或服务所在的服务器本身(自动)。
- 是否自动化 :取决于配置 。现代 Windows 服务(如 IIS、SQL Server)通常支持自动注册,但需要权限配合。
6.1 SPN注册方式
- SPN 的注册本质上是对 AD 数据库的一个 LDAP Write (写入) 操作。
| 场景 | 发起者 (Who) | 目标处理者 (Where) | 自动化程度 |
|---|---|---|---|
| 手动注册 | 域管理员的 PC / 运维终端 | 域控制器 (DC) | ❌ 人工操作 |
| 自动注册 | 服务所在的服务器 (如 SQL Server 主机) | 域控制器 (DC) | ✅ 服务启动时触发 |
6.1.1 手动注册(管理员视角)
-
机器:管理员的笔记本电脑或运维跳板机。
-
工具 :Windows 命令行工具
SetSPN.exe。 -
命令示例 :
powershell# 将 SPN 绑定到域用户 svc_sql SetSPN -S MSSQLSvc/server01.test.com:1433 svc_sql -
过程:管理员的电脑通过 LDAP/LDAPS 协议向 DC 发送请求,DC 验证权限后更新 AD 数据库。
6.1.2 自动注册(服务视角)
- 机器 :运行服务的服务器本身(例如
server01)。 - 机制:当 SQL Server 或 IIS 服务启动时,它会尝试向 DC 查询:"我是否已经注册了 SPN?"如果没有,它会自动发送请求去注册。
- 前提条件 :
- 服务必须运行在域用户账号下(不能是 Local System)。
- 该域用户账号必须有权限修改自己的
servicePrincipalName属性(默认情况下,普通域用户没有此权限,需要管理员预先配置或手动注册)。
6.1.3 SPN 注册的底层时序图
- 区分"自动注册"和"手动注册"。
域控制器 (KDC + AD DB) 管理员/服务主机 (Client) 域控制器 (KDC + AD DB) 管理员/服务主机 (Client) 场景 A:服务启动时自动尝试注册 检查权限: 用户是否有修改自己属性的权限? 服务启动失败或日志报错 (需管理员手动介入) SPN 注册成功,Kerberos 可用 alt [权限不足 (默认情况)] [权限允许 (已配置 Self-Registration)] 场景 B:管理员手动强制注册 检查权限: 用户是否为 Domain Admin? alt [是管理员] [非管理员] 1. LDAP Modify Request (添加 SPN: MSSQLSvc/server01) 403 Forbidden / Access Denied 2. Update AD Database (NTDS.dit) 写入 servicePrincipalName 属性 3. Success Response 1. SetSPN Command (LDAP Modify) 2. Update AD Database Success Access Denied
6.2 核心细节:权限与自动化配置
6.2.1 默认行为(Default Behavior)
- Local System / Network Service :如果服务运行在
Local System下,SPN 会自动注册到计算机账号 (Computer Account) 上。这通常不需要额外配置,因为机器账号对自己有完全控制权。 - 域用户账号 (Domain User) :如果服务运行在自定义的域用户(如
svc_sql)下,默认情况下,该用户没有权限修改自己的 SPN 。- 后果:服务启动时自动注册会失败。Kerberos 认证无法工作,客户端可能会回退到 NTLM 认证(安全性较低)。
6.2.2 如何开启自动化?
为了让域用户账号下的服务能自动注册 SPN,管理员需要执行以下操作之一:
- 方法 A(推荐) :将
svc_sql加入 "Domain Admins" 组(不推荐,权限过大)。 - 方法 B(标准做法) :使用
SetSPN -Q查询现有 SPN,然后手动注册一次。之后服务启动时通常能识别到已存在而不再尝试修改。 - 方法 C(高级配置) :在 AD 中设置该用户对象的
msDS-AllowedToActOnBehalfOfOtherIdentity属性或特定的 ACL 权限,允许其自我注册 SPN。
6.2.3 为什么有时候需要手动?
在某些安全加固的环境中,为了防止"服务账号被滥用"(例如攻击者创建一个同名服务来劫持认证),管理员会禁止自动注册 。此时必须通过 SetSPN 工具由管理员手动将 SPN 绑定到正确的账号上。
6.3 安全视角:SPN 注册的潜在风险
- SPN 的注册过程本身也存在安全风险:
-
SPN 劫持 (SPN Hijacking)
- 原理 :如果攻击者能够修改 AD 中的 SPN(例如通过提权或获取了服务账号密码),他们可以将
MSSQLSvc/server01这个 SPN 从合法的svc_sql账号上移除,并注册到攻击者的恶意账号上。 - 后果:当 KDC 收到请求时,会用攻击者账号的哈希加密 TGS。如果攻击者能解密(因为他们知道密码),他们就能伪造票据或进行中间人攻击。
- 原理 :如果攻击者能够修改 AD 中的 SPN(例如通过提权或获取了服务账号密码),他们可以将
-
重复 SPN (Duplicate SPN)
- 原理:AD 要求 SPN 必须唯一。如果有两个不同的账号注册了同一个 SPN,Kerberos 认证会失败。
- 风险:这通常用于 DoS(拒绝服务)攻击。如果攻击者能注册一个重复的 SPN,合法的服务就无法通过 Kerberos 认证,导致业务中断。
-
弱密码爆破 (Kerberoasting)
- 关联 :这就是你之前问到的 Kerberoasting。如果管理员手动注册了 SPN 到一个弱密码的域用户账号上(例如
svc_sql密码是Password123),攻击者就可以利用这个 SPN 进行爆破,获取该服务账号权限。
- 关联 :这就是你之前问到的 Kerberoasting。如果管理员手动注册了 SPN 到一个弱密码的域用户账号上(例如