Kerberos 与 SPN:深度架构解析与信任链原理

文章目录

  • [一 核心概念深化:从"名字"到"密钥锚点"](#一 核心概念深化:从“名字”到“密钥锚点”)
    • [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)的认证系统,它不直接传输密码,而是传输加密的凭证。

  1. Client (客户端/用户):发起请求的人或程序。
  2. Server (服务端):提供具体服务(如文件共享、数据库、Web服务)的机器或服务账号。
  3. 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 能够工作的关键逻辑链条:

  1. 注册阶段 :管理员将 SPN (MSSQLSvc/...) 注册在某个域用户账号(如 svc_sql)下。
  2. 查询阶段:KDC 收到 TGS_REQ 请求,解析出 SPN。
  3. 密钥映射 :KDC 根据 SPN 找到绑定的账号 (svc_sql),并提取该账号的密码哈希(NTLM Hash)。
  4. 加密锚点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)

  1. AS_REQ/AS_REP
    • Client 问 KDC:"我是 UserA"。
    • KDC 验证通过后,给一张 TGT。这张票是通用的,有效期长(默认10小时),用来证明"我已经在域里登录过了"。
  2. TGS_REQ/TGS_REP
    • Client 拿着 TGT 问 KDC:"我想访问 MSSQLSvc/server01 (SPN)"。
    • KDC 找到该 SPN 绑定的服务账号(比如 svc_sql)。
    • 关键点 :KDC 用 svc_sql 的密码哈希加密 TGS。此时,Client 拿到了这张票,但他无法解密它,只有 Server (svc_sql) 能解开。
  3. 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-CREDTGS-REP 的加密数据中)。

  • 内容:包含用户的 SID、用户所属的所有组 SID、特权信息。
  • 校验机制
    1. Server 解密 TGS,提取 PAC。
    2. Server 读取 PAC 中的 SID(如 S-1-5-21...)。
    3. Server 查询本地或域控的 ACL (Access Control List)Can SID S-1-5-21... access this resource?
    4. 注意: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 (域控制器)

  1. 查询 SPN


    AD 数据库
    SPN 存在吗?
    获取绑定账号的 Key
    报错:服务不存在
    使用 Service Key 加密 TGS
    Server (目标服务)
    使用 Service Key 解密 TGS
    读取 PAC 中的 SID/Group
    检查 ACL 权限

深度解析配合原理:

  1. 索引 (Indexing):Client 发起请求时,必须携带 SPN。KDC 利用 SPN 在 AD 中反向查找对应的服务账号(Service Account)。
  2. 锁定 (Locking) :一旦找到服务账号,KDC 就锁定了该账号的密码哈希作为加密密钥 。这意味着:TGS 票据的安全性完全依赖于 SPN 绑定的那个账号的密码强度。
  3. 验证 (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 拿到了它。
  • 攻击动作
    • 攻击者在本地使用工具(如 Rubeus)提取 TGS 中的加密数据块。
    • 由于攻击者不知道 Service Account 的密码,他无法解密。
    • 但是,TGS 是离线存在的。攻击者可以使用 HashcatJohn 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 了。
  • 攻击动作
    • 攻击者伪造一张 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 防御建议 (基于原理)

  1. 强密码策略 :由于 Kerberoasting 本质是爆破服务账号密码,必须强制要求运行在域用户下的服务(如 MSSQL, IIS AppPool)使用长且复杂的密码
  2. 最小权限原则 :不要给服务账号分配不必要的组权限。如果 svc_sql 不需要访问文件服务器,就不要把它加入相关组,这样即使被爆破,危害也有限。
  3. 监控 SPN 变更:监控 AD 中 SPN 的异常注册或修改,防止攻击者将恶意 SPN 绑定到受控账号上。
  4. 禁用不必要的委派:如果服务不需要 Kerberos 委派(Delegation),请在 AD 属性中关闭该选项,防止票据被劫持用于横向移动。

六 补充:SPN的注册

  1. SPN存储与最终生效的地方域控制器 (Domain Controller, DC) 。AD 数据库 (NTDS.dit) 存储在 DC 上,SPN 属性是 AD 对象的一个字段。
  2. 发起操作的人/机器 :通常是管理员的电脑 (手动)或服务所在的服务器本身(自动)。
  3. 是否自动化取决于配置 。现代 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 的注册过程本身也存在安全风险:
  1. SPN 劫持 (SPN Hijacking)

    • 原理 :如果攻击者能够修改 AD 中的 SPN(例如通过提权或获取了服务账号密码),他们可以将 MSSQLSvc/server01 这个 SPN 从合法的 svc_sql 账号上移除,并注册到攻击者的恶意账号上。
    • 后果:当 KDC 收到请求时,会用攻击者账号的哈希加密 TGS。如果攻击者能解密(因为他们知道密码),他们就能伪造票据或进行中间人攻击。
  2. 重复 SPN (Duplicate SPN)

    • 原理:AD 要求 SPN 必须唯一。如果有两个不同的账号注册了同一个 SPN,Kerberos 认证会失败。
    • 风险:这通常用于 DoS(拒绝服务)攻击。如果攻击者能注册一个重复的 SPN,合法的服务就无法通过 Kerberos 认证,导致业务中断。
  3. 弱密码爆破 (Kerberoasting)

    • 关联 :这就是你之前问到的 Kerberoasting。如果管理员手动注册了 SPN 到一个弱密码的域用户账号上(例如 svc_sql 密码是 Password123),攻击者就可以利用这个 SPN 进行爆破,获取该服务账号权限。
相关推荐
Byron Loong14 小时前
【调试】Dump 文件分析的完整流程
windows
Geoking.15 小时前
VSCode 安装 Claude Code 插件 + ccswitch 配置 DeepSeek API 完整教程(Windows 新手向)
ide·windows·vscode
潘达斯奈基~16 小时前
Windows 下 Claude Code使用 Agent Teams 配置教程
windows
happymaker062619 小时前
Spring框架学习日记——DAY02(依赖注入的方式)
windows
honder试试19 小时前
Elasticsearch(es)在Windows系统上的安装与部署(含Kibana)
windows·elasticsearch·jenkins
IT里的交易员20 小时前
【系统】Windows 安装 uv
windows·uv
我不是立达刘宁宇1 天前
windows密码操作
windows
Royzst1 天前
一、集合概述(前置基础)
开发语言·windows·python
时光追逐者1 天前
一款基于 C# 开发的 Windows 10/11 系统增强工具,精简、优化、定制一站完成!
开发语言·windows·c#·.net
liuhuizuikeai1 天前
菜品抽奖活动MFC+服务端
c++·windows·mfc