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 进行爆破,获取该服务账号权限。
相关推荐
REDcker2 小时前
C++ vcpkg:安装、使用、原理与选型
开发语言·c++·windows·操作系统·msvc·vcpkg
破阵子443282 小时前
从零开始:Windows 系统下 FFmpeg 安装与使用完全指南
windows·ffmpeg
0110编程之路2 小时前
Wine & Ubuntu 调用 Windows 应用
linux·windows·ubuntu
Roc-xb2 小时前
Windows MySQL 密码忘记了如何重置密码?
windows·mysql
春日见2 小时前
深度神经网络的底层数学原理
运维·服务器·windows·深度学习·自动驾驶
我不是懒洋洋17 小时前
预处理详解
c语言·开发语言·c++·windows·microsoft·青少年编程·visual studio
人工智能训练18 小时前
从 1.1.3 到 1.13.2!Ubuntu 24.04 上 Dify 升级保姆级教程(零数据丢失 + 一键迁移)
linux·运维·人工智能·windows·ubuntu·dify
mldlds18 小时前
Windows安装Redis图文教程
数据库·windows·redis
softbangong19 小时前
815-批量Excel文件合并工具,批量excel文件、工作表合并软件
linux·windows·excel·文件合并·excel合并·数据整理