freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

内网攻防 | Kerberos协议安全解析
2023-11-01 22:59:44

Kerberos协议

在古希腊神话中,Kerberos指的是:有着一只三头犬守护在地狱之门之外,禁止任何人类闯入地狱之中。而现实中Kerberos是一种网络身份验证协议,旨在通过密钥加密技术为客户端/服务器应用程序提供身份验证,主要用在域环境下的身份验证。 Kerberos协议是一种基于第三方可信主机的计算机网络协议,用来在非安全网络中,对个人通信以安全的手段进行身份认证。Kerberos协议在内网域渗透中至关重要,白银票据,黄金票据,攻击域控等都离不开Kerberos协议。

image-20231101103249192

关键角色

  • Domain Controller(域控制器),简称DC,一台计算机,实现用户、计算机的统一管理。在Kerberos中会多次用到一个用户的Hash值,kebtgt,他是DC中的一个特殊用户,是一个无法登录的账户,是在创建域时系统自动创建的,在整个Kerberos认证中会多次用到它的Hash值去做验证

  • Key Distribution Center(密钥分发中心),简称KDC,默认安装在域控里,包括AS和TGS

  • Authentication Service(身份验证服务),简称AS,用于KDC对Client认证

  • Ticket Granting Service(票据授予服务),简称TGS,用于KDC向Client和Server分发Session Key(临时key)

  • Active Directry(活动目录),简称AD,用于储存用户、用户组、域相关信息,AD会维护一个Account Database(账户数据库). 它存储了域中所有用户的密码Hash和白名单。只有账户密码都在白名单中的Client才能申请到TGT。

  • Client 客户端,指的是用户

  • Server 服务端,可能是某台计算机,也可能是某个服务

举个例子:当A要和B进行通信的时候,A就需要向B证明自己是A,直接的方式就是A用二人之间的秘密做密钥加密明文文字生成密文,把密文和明文文字一块发送给B,B再用秘密解密得到明文,把解密得到的明文与明文文字进行对比,若一致,则证明是A

但是网络中,密文和文字很有可能被窃取,并且只要时间足够,总能破解得到密钥。所以不能使用这种长期有效的密钥,要改为短期的临时密钥。那么这个临时密钥就需要一个第三方可信任的机构来提供,即KDC



六步

image-20231101103258070

  1. 首先Clinet向域控制器DC请求访问Server,DC通过去AD活动目录中查找依次区分Client来判断Client是否可信

  2. 认证通过返回TGT给Client,Client得到TGT(Ticket Granting Ticket)

  3. Client继续拿着TGT请求DC访问Server,TGS通过Client消息中的TGT,判断Client是否有访问权限

  4. 如果有,则给Client有访问Server权限的Ticket,也叫ST(Service Ticket)

  5. Client得到Ticket后,再去访问Server,且该Ticket只针对这一个Servery有效

  6. 最终Server与Client建立通信

三个阶段

详细认证步骤大致可以分为三个阶段:

  • AS_REQ & AS_REP

  • TGS_REQ & TGS_REP

  • AP-REQ & AP-REP

image-20231101103304879

  1. AS-REQ-AS-REP阶段:(Client与AS的交互)

首先Client用自己的哈希值NTLM-hash对timestamp、client-info、server-info等数据进行加密,发送给AS,向AS请求TGT票据(AS-REQ) 当AS收到Client发来的信息后,AS会先向域控AD请求,询问是否有此Client用户,如果有的话,就会取出该Clinet的NTLM-hash,然后生成一个随机密钥称为Session-Key as(临时密钥Session-Key),并使用CLinet NTLM-hash加密Session-Key as 作为一部分内容 还有一部分内容就是TGT:使用KDC一个特定账户kebtgt的HTLM-hash对Session-key as、timestamp、Client-info进行的加密。然后将这两部分回复给Client。(AS-REP) 该阶段是Client和AS的认证

  1. TGS-REQ-TGS-REP阶段:(Client与TGS的交互)

Client收到AS发来的AS-REP后,先使用自身的NTLM-hash 解密得到Session-key as,然后使用Session-key as 对Client-info、timestamp、Server-info加密作为一部分,加上TGT,一并发送给KDC中的TGS(TGS-REQ) TGS收到请求后,使用krbtgt的NTLM hash解密TGT,得到Session-key as、timestamp、Client-info,同时使用TGT解密出的Session-key as解密第一部分内容,得到Client-info、tiemstamp。对比这两部分解密得到的内容以验证是否通过,通过后,生成一个新的随机密钥(Session-Key tgs),并向Client回复TGS-REP的两部分内容: 一部分是Session-key as 加密的Session-key tgs 另一部分是ST(ticket),即Server NTLM-hash加密的数据(Session-key tgs、timestamp、Client-info) 该阶段是Client和KDC的通信

  1. AP-REQ-AP-REP阶段:(Client与Server的交互)

Client收到TGS-REP后,先用自己保存的Session-key as解密出Session-key tgs,再使用Session-key tgs解密第一部分得到Client-info、timestamp。然后与ST的Client-info、timestamp进行对比。timestamp一般时间为八小时。验证通过后,回复AP-REP,最终建立通信

三个阶段产生的漏洞

image-20231101103313783


SPN与Kerberoast攻击

SPN介绍

SPN,ServicePrincipal Names,即服务主题名称,是服务实例(比如:HTTP、SMB、MySQL等服务)在使用Kerberos身份验证在网络上的唯一标识符,其由服务类、主机名和端口组成。Kerberos认证过程使用SPN将服务实例服务登录账户相关联,如果想使用Kerberos协议来认证服务,那么必须正确配置SPN。在使用Kerberos身份验证的网络中,必须在内置计算机账户或域用户账户下为服务器注册SPN。对于内置机器账户,SPN将自动进行注册。但是,如果在域用户账户下运行服务,则必须为要使用的账户手动注册SPN

如果用一句话来说明的话就是如果想使用Kerberos协议来认证服务,那么必须正确配置SPN 由于每台服务器都需要注册用于Kerberos身份验证服务的SPN,所以为在不进行扫描的前提下收集有关内网域环境信息提供了一个隐蔽的办法 SPN的识别是Kerberoasting攻击的第一步



当某用户需要访问MySQL服务时,系统会以当前用户的身份向域控查询SPN为MySQL的记录。当找到该SPN记录后,用户会再次与KDC通信,将KDC发送的TGT作为身份凭据发送给客户,并将需要访问的SPN发送给KDC。KDC中的TGS服务对TGT进行解密。确认无误后,由TGS将一张允许访问该SPN所对应的服务的ST服务票据和该SPN所对应的服务的地址发送给用户,用户使用该票据即可访问MySQL服务

SPN类型

SPN的类型分为两种:

  • 一种是注册在活动目录的机器账户(Computers)下,当一个服务的权限为Local System或Network Service,则SPN注册在机器账户下

  • 一种是注册在活动目录的域用户账户(Users)下,当一个服务的权限为一个域用户,则SPN注册在域用户账户(User)下

SPN的语法格式

在 SPN 的语法中存在四种元素,两个必须元素和两个额外元素,其中<service class>和为<host>必须元素
<service class>/<host>:<port> <servername>
<service class>:标识服务类的字符串
<host>:服务所在主机名称
<port>:服务端口
<service name>:服务名称,所谓的实例名称

服务类型    /对应机器名:服务端口[默认端口可不写]
  • <service class>可以理解为服务的名称,常见的WWW、LDAP、SMTP、DNS、HOST等,例如:MSSQLSvc/WIN-CKT0M35R6UO.top.pentest.top:1433

  • <host>有两种形式,FQDN和NetBIOS名,例如WIN-CKT0M35R6UO.top.pentest.top或者是WIN-CKT0M35R6UO

  • 如果服务运行在默认端口上,则端口号<port>可以省略

在内网中,SPN扫描通过查询向域控服务器执行服务发现。这对于红队而言,可以帮助识别正在运行着重要服务的主机,如终端,交换机等。 CN=Computers就是主机,CN=Users就是在域用户下注册 例如 image-20231101103349559例如下面的一条

MSSQLSvc(标识服务类)/SQL.hack.lab(服务所在主机名称):1433(服务端口)/mssql(服务名称)

主机名称:可以分为FQDN和netbios,一个是运行SQL Server的计算机的FQDN(SQL.hack.lab)。还有一种就是SQL Server的计算机的netbios名字(SQL),俗称短名。 端口号/实例名:服务所监听的计算机端口号。对于SQL Server而言,如果SQL运行在默认端口(1433)上,则端口号可以省略。 例如:

MSSQLSvc/myserver.corp.mycomany.com:1433
MSSQLSvc/myserver:1433
MSSQLSvc/myserver.corp.mycomany.com
MSSQLSvc/myserver:
MSSQLSvc/myserver.corp.mycomany.com:instancename
MSSQLSvc/myserver:instancename

SPN配置

查询

查询全部已注册的条目setspn -q */*

1 查看当前域内所有的SPN: setspn  -Q  */*
2 查看指定域laosec.cn注册的SPN:setspn -T laosec.cn -Q */*      如果指定域不存在,则默认切换到查找本域的SPN
3 查找本域内重复的SPN: setspn -X
4 删除指定SPN:setspn -D SQLServer/mssql.laosec.cn:1433/MSSQL
5 查找指定用户/主机名注册的SPN:setspn -L username/hostname

image-20231101103402160image-20231101103409914查询指定域注册的条目setspn –L lucky(域用户)

所有域内用户都有权查询SPN如果查询出现以下错误:

Ldap 错误(0x31 -- 无效凭据): ldap_bind_sW 无法检索域“”的 DN: 0x00000031 警告: 未指定有效的目标,正在还原为当前域。 Ldap 错误(0x31 -- 无效凭据): ldap_bind_sW 搜索现有 SPN 时出错: 0x00000031

原因可能是:域主机未与域控时间同步 在域主机上配置同步域控时间net time \\dc.hack.lab /set

GetUserSPNs.ps1使用GetUserSPNs.ps1也可以进行查询 https://github.com/nidem/kerberoast/blob/master/GetUserSPNs.ps1GetUserSPNs 是 Kerberoast 工具集中的一个 PowerShell 脚本,可以用来查询域内用户注册的 SPN。 image-20231101103420795

PowerViewhttps://github.com/PowerShellMafia/PowerSploitPowerView是PowerSpolit中Recon目录下的一个powershell脚本PowerView 相对于上面几种是根据不同用户的 objectsid 返回的信息更加详细。Import-Module .\PowerView.ps1Get-NetUser -SPNimage-20231101103426400

GetUserSPNsGetUserSPNs 是 Kerberoast 工具集中的一个 vbs 脚本用来查询域内用户注册的 SPN。 下载地址: https://github.com/nidem/kerberoast/blob/master/GetUserSPNs.vbs执行命令:

cscript ./GetUserSPNs.vbs

GetUserSPNs.pyGetUserSPNs.py是impacket工具包的一款工具,该工具包用于对SMB1-3或IPv4/IPv6上的TCP、UDP、ICMP、IGMP,ARP,IPv4,IPv6,SMB,MSRPC,NTLM,Kerberos,WMI,LDAP等协议进行低级编程访问,可使用该工具对目标主机进行SPN探测。

安装地址: https://github.com/SecureAuthCorp/impacket该工具在最新版本的kali是内置的,直接运行即可 GetUserSPNs.py hack.lab/lucky:p@ssw0rd -dc-ip 172.16.0.106 -request

注册

setspn -A MSSQLSvc/SQL.chen.test:1433 test意思就是说注册一条服务类为MSSQLSvc,主机为SQL.chen.test,端口为1433,注册在test域用户下。 部分的服务会自动尝试利用自己的账户进行注册SPN,比如SQLServer在每次启动的时候,都会去尝试注册SPNsetspn -S MSSQLSvc/SQL.hack.lab:1433 test跟上面的区别就是,-S可以验证是否有重复的SPN,如果有就禁止注册。因为如果有重复的SPN会导致kerberos认证的时候失败 域管理用户和机器用户本身有注册SPN的权限,域用户没有,如果要注册要赋予Read servicePrincipalName和Write serverPrincipalName权限

删除

setspn -D MSSQLSvc/SQL.hack.lab:1433 test

查重

setspn -XLDAP协议 去查询SPN的时候,都会用到一个协议,叫做LDAP(LightweightDirectory Access Protocol),中文名为轻量目录访问协议。是一种用来查询与更新 Active Directory 的目录服务通信协议。AD 域服务利用 LDAP 命名路径(LDAP naming path)来表示对象在 AD 内的位置,以便用它来访问 AD 内的对象。 LDAP 数据的组织方式: 更直观的说可以把 LDAP 协议理解为一个关系型数据库,其中存储了域内主机的各种配置信息。 在域控中默认安装了 ADSI 编辑器,全称 ActiveDirectory Service Interfaces Editor (ADSI Edit),是一种 LDAP 的编辑器,可以通过在域控中运行 adsiedit.msc 来打开(服务器上都有,但是只有域控中的有整个域内的配置信息)。

Kerberoasting攻击

Kerberos协议在请求访问某个服务时存在一个缺陷,Kerberoasting正是利用这个缺陷的一种攻击技术。首先,我们列举一下正常情况下一个用户请求访问某个服务时会经过哪些步骤:

  1. 首先用户将AS-REQ数据包发送给KDC密钥分发中心,要对一个域进行身份验证

  2. KDC收到用户的请求后会验证用户的凭据,如果凭据有效,则返回TGT认购权证,该TGT认购权证用于以后的ST服务票据的请求

  3. 如果用户想要通过身份认证访问某个服务的话,那么他需要发起票据授予请求,请求中包含TGT以及所请求服务的SPN服务主体名称

  4. 如果TGT有效并且没有过期,那么TGS会从TGT认购权证中提取信息创建一个用于访问目标服务的一个ST服务票据,该ST服务票据使用服务账户的凭证进行加密。然后,域控制器开始查找哪个账户在ServicedPrincipalName(SPN)字段中注册了所请求的SPN

  5. 用户收到了包含服务票据的TGS响应数据包

  6. 最后,服务票据会转发给目标服务,然后使用服务账户的凭据进行解密

整个过程相对比较简单,我们需要注意的是,服务票据会使用服务账户的哈希进行加密,这样一来,Windows域中任何经过身份验证的用户都可以从TGS处请求ST服务票据。由于服务票证是用链接到请求SPN的账户的哈希加密的,所以攻击者可以离线破解整个加密块,恢复账户的明文密码

将上述内容总结一下就是。在kerberos协议过程中,TGS_REP步骤中,用户将会收到由目标服务实例的NTLM hash加密生成的TGS,加密算法为RC4-HMAC,如果获得这个TGS,就可以尝试穷举口令,模拟加密过程,进行破解 由于域内的任何用户都可以向域内的任何服务请求TGS,知道相关服务的SPN后,可以用SPN申请一张票据ST(TGS Ticket),如果Kerberos协议设置票据为RC4加密,则可以通过爆破的方式得到服务对应用户的密码

将kerberoasting攻击分为几个步骤:SPN服务主体名称发现、请求服务票据、服务票据的导出以及服务票据的暴力破解

SPN服务主体的名称发现

上面也有所总结,这里简略过一遍

使用SetSPN查询

SetSPN 是 Windows 系统自带的工具,可以查询域内的 SPN

setspn -Q */*    # 查看当前域内所有的 SPN
setspn -T whoamianony.org -Q */*    # 查看指定域 whoamianony.org 注册的SPN, 如果指定域不存在, 则默认切换到查找本域的 SPN
setspn -L <username>/<hostname>    # 查找指定用户/主机名注册的 SPN

image-20231101103445616image-20231101103450888

使用GetUserSPNs.ps1脚本

https://github.com/nidem/kerberoast/blob/master/GetUserSPNs.ps1GetUserSPNs 是 Kerberoast 工具集中的一个 PowerShell 脚本,可以用来查询域内用户注册的 SPN。Import-Module.\GetUserSPNs.ps1image-20231101103457084

使用PowerView.ps1脚本

https://github.com/PowerShellMafia/PowerSploit/PowerView 是 PowerSploit 框架中 Recon 目录下的一个 PowerShell 脚本,PowerView 相对于上面几种是根据不同用户的 objectsid 来返回,返回的信息更加详细。

Import-Module .\PowerView.ps1
Get-NetUser -SPN

请求服务票据

使用Rubeus工具

https://github.com/GhostPack/RubeusRubeus 工具里面的 kerberoast 支持对所有用户或者特定用户执行 kerberoasting 操作,其原理在于先用 LDAP 查询于内的 SPN 服务主体名称,然后发送 TGS 包,最后直接打印出能使用 Hashcat 或 John 爆破的 Hash。默认情况下会打印出注册于用户下的所有 SPN 的服务票据的 Hashcat 格式

Rubeus.exe kerberoast

image-20231101103504055

使用PowerShell命令请求

为特定SPN请求服务票据的最简单的方法时通过PowerShell

请求单个TGS:
Add-Type -AssemblyName System.IdentityModel

New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "SQLServer/mssql.laosec.cn:1433/MSSQL"

请求所有TGS:
Add-Type -AssemblyName System.IdentityModel

setspn.exe -q */* | Select-String '^CN' -Context 0,1 | % { New-Object Sys
# SPN # 黄金票据 # 白银票据 # 密码喷洒 # Kerberos安全
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录