0x01、kerberos简介
kerberos是一种域内认证协议,Kerberos的标志是三头狗,狗头分别代表以下角色:
- Client
- Server
- KDC(Key Distribution Center) = DC(Domain Controller)
Kerberos认证协议的基础概念:
票据(Ticket):是网络对象互相访问的凭证。
TGT(Ticket Granting Ticket):入场券,通过入场券能够获得票据,是一种临时凭证的存在。
KDC负责管理票据、认证票据、分发票据,但是KDC不是一个独立的服务,它由以下服务组成:
- Authentication Service: 为client生成TGT的服务
- Ticket Granting Service: 为client生成某个服务的ticket
另外还需要介绍一个类似于本机SAM的一个数据库:AD,全称叫account database,存储所有client的白名单,只有存 在于白名单的client才能顺利申请到TGT。
从物理层面看,AD与KDC均为域控制器(Domain Controller)。
0x02、域认证粗略流程
下列为粗略的一个认证流程,但是没图;没事,我们在0x03更为详细的分析client和kdc的请求响应。咱们先有个大概的印象
1. client向kerberos服务请求,希望获取访问server的权限。 kerberos得到了这个消息,首先得判断client是否是可信赖的, 也就是白名单黑名单的说法。这就是AS服务完成的工作,通过 在AD中存储黑名单和白名单来区分client。成功后,返回AS返 回TGT给client。
2. client得到了TGT后,继续向kerberos请求,希望获取访问 server的权限。kerberos又得到了这个消息,这时候通过client 消息中的TGT,判断出了client拥有了这个权限,给了client访 问server的权限ticket。
3. client得到ticket后,终于可以成功访问server。这个ticket只是 针对这个server,其他server需要向TGS申请
0x03、域认证流程
我们先看流程图,我们可以发现其中的认证过程分为四步,其中就是与AS和TGS的认证过程。所以我们接下来就慢慢的分析
1、as-req & as-rep
通过简介的图片中可以发现TGT认购权证
由KDC中的AS认证服务(Authentication Service)下发,那我们就可以剖析as的请求宝与返回包
(一)、as-req请求包
当域内某个用户试图访问域中的某个服务,于是输入用户名和密码,本机的Kerberos服务会向KDC的AS认证服务发送一个AS-REQ认证请求。该请求包中包含: 请求的用户名、请求的主机名、加密类型和Authenticator(用户NTLM Hash加密的时间戳)等等
pvno: kerberos版本号,这里为5
msg-type: 消息类型, AS_REQ 对应的是 krb-as-req(10)
padata:主要是一些认证信息,每个认证消息有type和value。
PADA PA-ENC-TIMESTAMP:这个是预认证,就是用用户hash加密时间戳,作为value发送给AS服务器。然后AS服务器那边有用户hash,使用用户hash进行解密,获得时间戳,如果能解密,且时间戳在一定的范围内,则证明认证通过。由于是用用户密码Hash加密的,所以也就造成了可以利用哈希传递攻击
padata-type: padata类型,这里是 kRB5-PADATA-ENC-TIMESTAMP(2)
padata-vaule: padata的值
etype: 加密类型,这里是 eTYPE-AES256-CTS-HMAC-SHA1-96(18)
cipher: 密钥
PADA PA-PAC-REQUEST:这个是启用PAC支持的扩展。PAC(Privilege Attribute Certificate)并不在原生的kerberos里面,是微软引进的扩展。PAC包含在响应包AS_REP中。这里的value对应的值为True或False,KDC根据include的值来确定返回的票据中是否需要携带PAC。
padata-type: padata类型,这里是 kRB5-PADATA-PA-PAC-REQUEST(128)
padata-vaule: padata的值
include-pac: 是否包含PAC,这里为True
req-body:请求body
padding:填充,这里为0
kdc-options:用于与KDC约定一些选项设置
cname:客户端用户名,这个用户名存在和不存在,返回的包有差异,可以用于枚举域内用户名。PrincipalName类型,包含type和Value
name-type:名字类型,这里是 KRB5-NT-PRINCIPAL(1)
cnmae-string:名字,也就是请求的用户名
CNameString: 请求的用户名,这里为 hack
realm:域名,这里为 xie
sname:服务端用户名,PrincipalName类型,包含type和Value。在AS-REQ里面snames krbtgt
name-type:名字类型,这里是 KRB5-NT-SRV-INST(2)
sname-string: krbtgt用户的信息,这里有2个items
SNameString: 这里是krbtgt用户名
SNameString: 这里是域名 xie
till:到期时间,rubeus和kekeo都是20370913024805Z,这个可以作为特征来检测工具。
rtime:也是到期时间
nonce:随机生成的一个数。kekeo/mimikatz nonce是12381973,rubeus nonce是1818848256,这个也可以用来作为特征检测工具。
etype:加密类型,这里有6个items
ENCTYPE: eTYPE-AES256-CTS-HMAC-SHA1-96(18)
ENCTYPE: eTYPE-AES128-CTS-HMAC-SHA1-96(17)
ENCTYPE: eTYPE-ARCFOUR-HMAC-MD5(23)
ENCTYPE: eTYPE-ARCFOUR-HMAC-MD5-56(24)
ENCTYPE: eTYPE-ARCFOUR-HMAC-OLD-EXP (-135)
ENCTYPE: eTYPE-DES-CBC-MD5 (3)
address:客户端的请求地址,也就是客户端的主机名
HostAddress WIN7<20>
ddr-type: 地址类型,这里是 nETBIOS (20)
NetBIOS Name: WIN7<20> (Server service)
(二)、as-rep返回包
当KDC接收到请求之后,通过AD活动目录查询得到该用户的密码Hash,用该密码Hash对请求包的Authenticator进行解密,如果解密成功,则证明请求者提供的密码正确。
而且需要时间戳范围在五分钟内,且不是重放,于是预认证成功。KAS成功认证对方的身份之后,发送响应包给客户端。
响应包中主要包括:krbtgt用户的NTLM Hash加密后的TGT认购权证(即ticket这部分)和用户NTLM Hash加密的Login Session key(即最外层 enc-part 这部分) 以及一些其他信息
Login Session Key的作用是用于确保客户端和KDC下阶段之间通信安全。最后TGT认购权证
、加密的Lgoin Session Key
、时间戳
和 PAC等信息
会发送给客户端。PAC中包含用户的SID,用户所在的组等一些信息。
pvno:kerberos版本号,这里为5
msg-type:消息类型,AS_REP对应的是 krb-as-rep(11)
padata:主要是一些认证信息。一个列表,包含若干个认证消息用于认证
PA-DATA PA-ENCTYPE-INFO2
padata-type: padata的类型,这里是 kRB5-PADATA-ETYPE-INFO2(19)
padata-value: padata的值
ETYPE-INFO2-ENTRY
etype: eTYPE-AES256-CTS-HMAC-SHA1-96(18)
salt: 盐值,这里是 XIE.COMhack
crealm: 域名,这里是 XIE.COM
cname:请求的用户名
name-type: 用户名类型,这里是 kRB5-NT-PRINCIPAL(1)
cname-string: 1item
CNameString: hack
ticket:TGT认购权证
tkt-vno: TGT版本号,这里为5
realm: 域名,这里是 XIE.COM
sname:
name-type: KRB5-NT-SRV-INST(2)
sname-string: 2items
SNameString: krbtgt
SNameString: XIE.COM
enc-part: 这部门是用krbtgt的密码Hash加密的。因此如果我们拥有krbtgt的hash就可以自己制作一个ticket,这就造成了黄金票据攻击
etype: eTYPE-AES256-CTS-HMAC-SHA1-96(18)
kvno: 版本号,这里为2
cipher:密钥
enc-part:这部分是用用户密码Hash加密的。里面最重要的字段是Login session key,作为下阶段的认证密钥。
etype: eTYPE-AES256-CTS-HMAC-SHA1-96(18)
kvno: 版本号,这里为3
cipher:密钥
2、tgs-req & tgs-rep
经过上面的步骤,客户端获得了 TGT认购权证 和 Login Session Key。然后用登陆者的密码NTLM Hash解密Login Session Key得到 原始的Logon Session Key。然后它会在本地缓存此 TGT认购权证 和 原始的Login Session Key。
如果现在它需要访问某台服务器的某个服务,它就需要凭借这张TGT认购凭证向KDC购买相应的入场券ST服务票据(Service Ticket)。
ST服务票据是通过KDC的另一个服务 **TGS(Ticket Granting Service)下发的。在这个阶段,微软引入了两个扩展自协议 S4u2self 和 S4u2Proxy(当委派的时候,才用的到)
(一)、TGS-REQ请求包
客户端向KDC请求针对指定服务的ST服务票据请求,该请求主要包含如下的内容:客户端信息、Authenticator(Login Session Key加密的时间戳)、TGT认购权证(padata下ap-req下的ticket) 和 访问的服务名 以及一些其他信息 。
pvno:kerberos版本号,这里为5
msg-type:消息类型,TGS_REQ对应的是 krb-tgs-req(12)
padata:padata中包含ap_req,这个是TGS_REQ必须携带的部分,这部分会携带AS_REP里面获取到的TGT票据。还有可能会有PA_FOR_USER,类型是S4U2SELF,是一个唯一的标识符,该标识符指示用户的身份,该标识符由用户名和域名组成。S4U2Proxy必须扩展PA_FOR_USER结构,指定服务代表某个用户去请求针对服务自身的kerberos服务票据。还有可能会有PA_PAC_OPTIONS,类型是PA_PAC_OPTIONS,S4U2Proxy必须扩展PA-PAC-OPTIONS结构。如果是基于资源的约束委派,就需要指定Resource-based Constrained Delegation位。
padata-type: padata类型,这里是 KRB5-PADATA-TGS-REQ(1)
padata-value: padate的值
ap-req:ap-req详细分析见下文.这个是TGS_REQ必须携带的部分,这部分会携带AS_REP里面获取到的TGT票据。KDC校验TGT票据,如果票据正确,就返回TGS票据。
req-body:请求body
padding:这里为0
kdc-options:用于与KDC约定一些选项设置
realm:域名,这里为 xie.com
sname:这个是要请求的服务。TGS_REP获得的ST服务票据是用该服务用户的hash进行加密的。如果指定的服务是krbtgt,那么拿到的ST服务票据是可以当做TGT认购权证使用的。
name-type: KRB5-NT-SRV-HST(3)
sname-string: 2 items
SNameString: host
SNameString: win7.xie.com
till:到期时间,rubeus和kekeo都是20370913024805Z,这个可以作为特征来检测工具。
nonce:随机生成的一个数。kekeo/mimikatz nonce是12381973,rubeus nonce是1818848256,这个也可以用来作为特征检测工具。
etype:加密类型
ENCTYPE: eTYPE-AES256-CTS-HMAC-SHA1-96(18)
ENCTYPE: eTYPE-AES128-CTS-HMAC-SHA1-96(17)
ENCTYPE: eTYPE-ARCFOUR-HMAC-MD5(23)
ENCTYPE: eTYPE-ARCFOUR-HMAC-MD5-56(24)
ENCTYPE: eTYPE-ARCFOUR-HMAC-OLD-EXP (-135)
(二)、TGS-REP返回包
TGS接收到请求之后,首先会检查自身是否存在客户端所请求的服务。如果服务存在,则通过 krbtgt 用户的NTLM Hash 解密TGT并得到Login Session Key,然后通过Login Session Key解密Authenticator,如果解密成功,则验证了对方的真实身份,同时还会验证时间戳是否在范围内。并且还会检查TGT中的时间戳是否过期,且原始地址是否和TGT中保存的地址相同。
在完成上述的检测后,如果验证通过,则TGS完成了对客户端的认证,会生成一个用Logon Session Key加密后的用于确保客户端-服务器之间通信安全的Service Session Key会话秘钥(也就是最外层enc-part部分)。
并且会为该客户端生成ST服务票据。ST服务票据主要包含两方面的内容:客户端用户信息 和 原始Service Session Key,整个ST服务票据用该服务的NTLM Hash;进行加密。最终Service Session Key 和 ST服务票据 发送给客户端。
注意:这一步不管用户有没有访问服务的权限,只要TGT正确,就都会返回ST服务票据,这也是kerberoasting能利用的原因,任何一个用户,只要hash正确,就可以请求域内任何一个服务的ST票据
pvno:kerberos版本号,这里为5
msg-type:消息类型,TGS_REP对应的是 krb-tgs-rep(13)
crealm: 域名,这里是 XIE.COM
cname:请求的用户名
name-type: 名称类型,这里为 KRB5-NT-PRINCIPAL(1)
cname-string: 1 item
CNameString: hack
ticket:即ST服务票据
tkt-vno: 服务票据版本号,这里为5
realm: XIE.COM
sname:
name-type: KRB5-NT-SRV-HST(3)
sname-string: 2 items
SNameString: host
SNameString: win7.xie.com
enc-part: 这部分是用请求服务的密码Hash加密的。因此如果我们拥有服务的密码Hash,那么我们就可以自己制作一个ST服务票据,这就造成了白银票据攻击。也正因为该票据是用请求服务的密码Hash加密的,所以当我们得到了ST服务票据,可以尝试爆破enc_part,来得到服务的密码Hash。这也就造成了kerberoast攻击
etype: eTYPE-AES256-CTS-HMAC-SHA1-96(18)
kvno: 版本号,这里为3
cipher:密钥
enc-part:这部分是用AS-REP返回的session-key加密的。里面最重要的字段是Service session key,作为下阶段的认证密钥。
etype: eTYPE-AES256-CTS-HMAC-SHA1-96(18)
cipher:密钥
0x04、Kerberos下的攻击手法
哈希传递攻击:在AS-REQ阶段,是用用户密码Hash加密的Authenticator(用户NTLM Hash加密的时间戳
,所以也就造成了哈希传递攻击
域用户名枚举:AS-REQ 的 cname 值,当域用户不存在时,返回包提示错误
密码喷洒攻击:并且当用户名存在,密码正确和错误时,返回包也不一样,所以可以进行用户名密码爆破。是用固定的密码去跑用户名
黄金票据:AS-REP 阶段,由于返回的 TGT 认购权证是由 krbtgt 用户的密码Hash加密
的,因此如果我们拥有 krbtgt 的 hash 就可以自己制作一个TGT认购权证。
AS-REP Roasting攻击:AS-REP阶段,最外层的 enc-part 是用用户密码 Hash 加密的。对于域用户,如果设置了选项” Do not require Kerberos preauthentication”,此时向域控制器的 88 端口发送 AS_REQ 请求,对收到的AS_REP内容(enc-part底下的ciper,因为这部分是使用用户 hash 加密
的 Login Session Key,我们通过进行离线爆破就可以获得用户hash)重新组合,能够拼接成”Kerberos 5 AS-REP etype 23”(18200)的格式,接下来可以使用hashcat对其破解
kerberoast攻击:在TGS-REP阶段,由于enc-part是用服务密码Hash加密的,所以我们可以通过爆破获得服务的hash
白银票据:在TGS-REP阶段,TGS_REP里面的ticket的enc-part是使用服务的hash进行加密的,如果我们拥有服务的hash,就可以给我们自己签发任意用户的TGS票据,这个票据也被称为白银票据。相较于黄金票据,白银票据使用要访问服务的hash,而不是krbtgt的hash,由于生成的是TGS票据,不需要跟域控打交道,但是白银票票据只能访问特定服务。但是要注意的一点是,伪造的白银票据没有带有有效KDC签名的PAC。如果将目标主机配置为验证KDC PAC签名,则银票将不起作用