相关术语
委托人(principal):是一个具有唯一标识的实体,可以是一台计算机或一项服务,通过
使用 KDC 颁发的票据来进行通信。委托人可以分为两类:用户和服务,分别具有不同种类
的标识符。用户通过如 user@REALM
格式的用户主体名称(User Principal Name,简称
UPN)来标识,记住 REALM 一定是大写的。例如用户 bob 在 bhusa.com 域中应该表示为
bob@BHUSA.COM
。
服务主体名称(Service Principal Name,SPN):用于域中的服务和计算机账户。SPN 的
格式形如 serviceclass/host_port/serviceName
。例如, 主机 dc1.bhusa.com 上 LDAP
服务的 SPN 可能类似于 ldap/dc1.bhusa.com, ldap/dc1 和
ldap/dc1.bhusa.com/bhusa.com。参考全限定主机名和仅主机名,一个服务可能注册为多
个 SPN
DNS:活动目录极度依赖 DNS,因为 DNS 可以让 AD 表现出层次结构化的树状结构,同时 也可以和开放的目录标准接轨,因此在搭建域时时,DNSService(或另有架设 DNS Server) 一定要存在于网络或该网域控制站中,不单单是资源查找需要 DNS,客户端请求 DC 时同 样需要它,通过 SRV 记录识别。
NetBIOS:Network Basic Input/Output System,它提供了 OSI 模型中的会话层 Service, 让在不同计算机上运行的不同程序,可以在局域网中互相连线以及分享数据,相当于一个 API。
MS-RPC:远程调用,可以更加快速的构造出 client/server 端模型,像 Windows Server 的域协议完全是基于 MS-RPC,以及 DNS 管理工具和 Microsoft Exchange Server。
认证步骤
-
客户端对用户口令执行 hash 运算。此散列值(即用户密钥)成为客户端和 KDC 共享的 长期密钥(long term key)。
-
KRB_AS_REQ:客户端加密一个时间戳,然后发送给身份验证服务(AS)。
-
KRB_AS_REP:身份验证服务会解密时间戳,若解密成功,表明了客户端获得某个特定用 户的口令(即验证了用户的身份)。AS 向客户端回复两条消息:
-
短期会话密钥(Session Key),用于客户端向 KDC 发起后续的请求,该消息经客 户端的长期密钥加密。(此短期会话密钥仅适用于该客户端和 KDC 之间)
-
票据授予票据(Ticket Granting Ticket,TGT),包含有关用户名、域名、时间和 组成员资格等信息。该消息经 仅 KDC 可知 的密钥加密(krbtgt 账户的 NT-Hash)。
KDC 不记录状态:客户端每次请求访问一项服务时,TGT 都会被转发
-
-
KRB_TGS_REQ:客户端使用 AS 返回的 Session Key 构建访问特定服务的请求,客户端 把 TGT 连同请求一起发送到票据授予服务(TGS)。
-
KRB_TGS_REP:票据授予服务解密 TGT 和服务请求,然后如果请求被允许,票据授予服 务向客户端发送一个服务票据(Service Ticket,ST)。ST 包括两部分:
-
远程服务器的部分:包含请求用户的组成员资格、时间戳、用于客户端和远程服务 器之间通信的会话密钥。使用 远程服务器 和 KDC 共享的长期密钥加密这部分消息。
-
客户端的部分:包含用于客户端和远程服务器之间通信的会话密钥。使用步骤 KRB_AS_REP 中得到的短期会话密钥加密这部分消息。
-
-
KRB_AP_REQ:客户端把 ST 中的远程服务器部分和请求一起发送到远程服务器。远程服 务器将直接接受该服务器票据,并不需要和 KDC 通信,因为该票据是用远程服务器和 KDC 共享的长期密钥加密过的,解密成功即表明 KDC 已经允许了此次通信。
Kerberos 协议是无状态的,KDC 和 TGS 并没记录以前的交互信息,因此 TGS 所需使用的 全部信息都在 TGT 中。因为 TGT 使用 krbtgt 的密码加密过,理论上只有两方能够解密 TGT:颁发票据的 KDC 和接受票据并创建访问网络资源的服务票据的 TGS。这种情况让 krbtgt 成为域中最重要的密码,只要 TGT 被 krbtgt 账户密码正确地加密,TGT 中的所有 信息都是可信的。
pass-the-ticket
在微软活动目录中颁发的 TGT 是可移植的。由于 Kerberos 的无状态特性,TGT 中并没有 关于票据来源的标识信息。这意味着可以从某台计算机上导出一个有效的 TGT,然后导入到 该环境中其他的计算机上。新导入的票据可以用于域的身份认证,并拥有票据中指定用户的 权限来访问网络资源。
AS_REQ
用户向 KDC 发送请求, 请求凭据是用户 hash 加密的时间戳
-
pvno kerberos 版本号
-
msg-type 类型, AS_REQ 对应的就是 KRB_AS_REQ(0x0a)
-
PA_DATA
一个列表, 保存了一些认证用的数据和值AS_REQ 用到的数据有两个:
-
ENC_TIMESTAMP 这个是预认证,就是用用户 hash 加密时间戳,作为 value 发送给 AS 服务器。然后 AS 服 务器那边有用户 hash,使用用户 hash 进行解密,获得时间戳,如果能解密,且时间戳 在一定的范围内,则证明认证通过
-
PA_PAC_REQUEST 这个是启用 PAC 支持的扩展。PAC(Privilege Attribute Certificate)并不在原生的 kerberos 里面,是微软引进的扩展。PAC 包含在 AS_REQ 的响应 body(AS_REP)。这里的 value 对应的是 include=true 或者 include=false(KDC 根据 include 的值来判断返回的票 据中是否携带 PAC)。
-
- REQ_BODY
-
kdc-options, 一些 flag 字段
-
cname
, PrincipalName 类型 在 AS_REQ 里面 cname 是请求的用户, 这个用户名存在和不存在, 返回的包有差异, 可以 用于枚举域内用户名。用户名错误
密码错误
-
sname, PrincipalName 类型 在 AS_REQ 里面 sname 是 krbtgt,类型是 KRB_NT_SRV_INST
-
realm, 域名
-
from, 发送时间
-
till, 到期时间 rubeus 和 kekeo 都是
20370913024805Z
, 这个可以作为特征来检测 -
nonce, 随机数 kekeo/mimikatz nonce 是 12381973, rubeus nonce 是 1818848256, 这个也可以用来作为 特征检测
-
etypr, 加密类型
-
AS_REP
KDC 使用用户 hash 进行解密,如果结果正确返回用 krbtgt hash 加密的 TGT 票据,TGT 里面包 含 PAC, PAC 包含用户的 sid、用户所在的组
-
msg-type AS_REQ 的响应 body 对应的就是 KRB_AS_REP(0x0b)
-
crealm, 域名
-
cname, 用户名
-
ticket
使用 krbtgt hash 加密的 ticket, 用于 TGS_REQ 的认证, 用户不能读取其内容 如果拥有 krbtgt hash 就可以自行制作 ticket, 即黄金票据 -
enc_part
这部分是可以解密的,key 是用户 hash,解密后得到 Encryptionkey, Encryptionkey 里面最重要的字段是 session key,作为下阶段的认证密钥
TGS_REQ
TGS_REQ 这个阶段不需要账号密码,需要 AS_REP 获取到的 TGT 凭据(ticket)
-
msg-type 类型,TGS_REQ 对应的就是 KRB_TGS_REQ(0x0c)
-
PA-DATA
-
AP_REQ 这个是 TGS_REQ 必须携带的部分,这部分会携带 AS_REP 里面获取到的 TGT 票据,就放在这 个结构体里面。KDC 校验 TGT 票据,如果票据正确,就返回 TGS 票据(ST)。
-
PA_FOR_USER 类型是 S4U2SELF; 值是一个唯一的标识符, 该标识符指示用户的身份, 由 用户名和域名组成。
-
PA_PAC_OPTIONS 类型是 PA_PAC_OPTIONS, 值是以下 flag 的组合
-
-
REQ_BODY
-
sname 要请求的服务, TGS_REP 获得的 ticket 是用该服务用户的 hash 进行加密的
-
AddtionTicket 附加票据,在 S4U2proxy 请求里面,既需要正常的 TGT,也需要 S4U2self 阶段获取到的 TGT,那么这个 TGT 就添加到 AddtionTicket 里面。
-
TGS_REP
-
msg-type AS_REQ 的响应 body 对应的就是 KRB_TGS_REQ(0x0d)
-
ticket 这个 ticket 用于 AP_REQ 的认证。其中里面的 enc_part 是加密的,用户不可读取里面的内容。 在 AS_REQ 请求里面是,是使用 krbtgt 的 hash 进行加密的,而在 TGS_REQ 里面是使用要请求 的服务的 hash 加密的。因此如果我们拥有服务的 hash 就可以自己制作一个 ticket,即白银 票据。正因为是使用要请求的服务的 hash 加密的,所以我们可以通过爆破 enc_part 获得该 服务的 hash, 详情见相关的安全问题>kerberoasting
-
enc_part 注意,这个 enc_part 不是 ticket 里面的 enc_part
TGS_REP
这部分是可以解密的, key 是上一轮 AS_REP 里面返回的 session_key, 也就是导入凭据里面 的 session_key, 解密后得到 encryptionkey, encryptionkey 这个结构里面最重要的字段 也是 session_key(但是这个 session_key 不同于上一轮里面的 session_key), 用来作为作 为下阶段的认证密钥。
S4U2SELF
S4U2self 使得服务可以代表用户获得针对服务自身的 kerberos 服务票据。这使得服务可以 获得用户的授权(可转发的用户 TGT),然后将其用于后期的认证(主要是后期的 s4u2proxy), 这是为了在用户以不使用 Kerberos 的方式对服务进行身份验证的情况下使用。
服务代表用户获得针对服务自身的 kerberos 票据这个过程, 是不需要用户的凭据的, 但需要 服务已经有通过 KDC 验证的 TGT
PAC
PAC 用于校验用户的权限, 即解决”What can I do”问题, 引入 PAC 后, kerberos 认证流 程如下:
-
用户向 KDC 发起 AS_REQ, 请求凭据是用户 hash 加密的时间戳, KDC 使用用户 hash 进行解密, 如果结果正确返回用 krbtgt hash 加密的 TGT 票据, TGT 里面包含 PAC, PAC 包含用户的 sid 和用户所在的组
-
用户凭 TGT 票据向 KDC 发起针对特定服务的 TGS_REQ 请求, KDC 使用 krbtgt hash 进行解密, 如果结果正确, 就返回用服务 hash 加密的 ST 票据(这一步不管用户有没有 访问服务的权限, 只要 TGT 正确, 就返回 ST, 这也是 kerberoating 能利用的原因— 任何一个用户, 只要 hash 正确, 可以请求域内任何一个服务的 ST)
-
用户拿着 ST 去请求服务, 服务使用自己的 hash 解密 ST。如果解密正确, 就拿着 PAC 去 KDC 那边询问用户有没有访问权限, 域控解密 PAC。获取用户的 sid 以及所在的组, 再判断用户是否有访问服务的权限
有些服务并没有验证 PAC 这一步, 这也是白银票据能成功的前提, 因为就算拥有服务 hash, 可以制作 ST, 也不能制作 PAC
注: PAC 对于用户和服务全程都是不可见的, 只有 KDC 能制作和查看 PAC