Kerberos认证流程
一、Kerberos简介
Kerberos协议由麻省理工学院开发,如今主要被用于Windows网络认证,Windows 2000和之后的操作系统使用Kerberos协议为其默认认证方法。加入Windows域则代表启动Kerberos作为客户端到服务端认证的默认协议,如果双方其一或全都未加入Windows域,则使用NTLM进行身份验证。
二、标准认证流程
Kerberos协议认证过程中主要存在三种角色:
Client
,客户端,访问服务Server
,服务端,提供服务KDC
(Key Distribution Center),密钥分发中心
Kerberos协议的认证流程如下图所示:

1. KRB_AS_REQ
Client
向KDC
的AS(Authentication Service)
服务发送KRB_AS_REQ
请求,目的是获得TGT
(Ticket Granting Ticket),发送的内容包括使用Client
用户哈希加密的时间戳,这也就是用户凭证。
这一步也叫做预认证,证明Client
有域内的用户和对应的哈希,可以进行下一阶段的请求。

抓包来看,KRB_AS_REQ
包含的字段如下:
pvno
,Kerberos协议版本号,现在常用的是Kerberos 5
msg-type
,消息类型,10
即0x0a
,代表krb-as-req
padata
,认证相关信息req-body
,里面包含kdc-options
、cname
、sname
、till
、nonce
、etype
等

padata
即PA_DATA
,其中在KRB_AS_REQ
阶段时用到的主要是:
ENC_TIMESTAMP
,用户哈希加密的时间戳PA_PAC_REQUEST
,启动PAC支持的扩展

在req-body
里,主要有:
kdc-options
,一些flag字段cname
,发起请求的用户名sname
,请求的服务名,在KRB_AS_REQ
中为krbtgt
realm
,域名till
,到期时间nonce
,随机生成的一个数etype
,加密类型
2. KRB_AS_REP
KDC在收到KRB_AS_REQ
之后,使用发起请求的用户的哈希解密凭证得到时间戳,如果解密成功并且时间在一定范围内,则通过预认证。
预认证通过后,KDC
会返回TGT
票据,此票据是使用KDC
的krbtgt
用户的hash加密的,理论上无法被伪造和解密。

KRB_AS_REP
的主要字段有:
pvno
, 版本msg-type
,消息类型crealm
,域名cname
,请求的用户名ticket
,加密的票据enc-part
,里面有下阶段的认证密钥

可以看到,在ticket
字段里,主要包含了域名、服务名、使用krbtgt
用户哈希加密的密文等。

而enc-part
里也是密文,但这里的密文是使用请求用户的哈希加密的,所以是可以解密的,里面是下一阶段的认证密钥。
3. KRB_TGS_REQ
通过预认证之后,Client
向KDC
的TGS(Ticket Granting Service)
服务发起请求,请求中包含了之前申请的TGT。
主要的字段和KRB_AS_REQ
相同,但内容有区别。

padata
字段里的ap-req
字段里的ticket
就是上面申请的TGT,而authenticator
是在KRB_AS_REP
中得到的下一阶段认证密钥。

req-body
里主要有这些字段:
kdc-options
,一些特殊选项,比如是否可转发等cname
,请求的用户名realm
,域名sname
,需要申请访问的服务名,如cifs
等,如果服务是krbtgt
,那得到的ST(服务票据)是可以当做TGT来使用的till
,到期时间nonce
,随机数
4. KRB_TGS_REP
KDC
验证TGT
票据和对应服务后,会返回ST
票据给Client
,这张票据对应着相关服务的访问权限,也就是俗称的白银票据。此票据是使用所请求的服务账户hash加密的,理论上也不可伪造和解密。

这些字段就不再解释,和之前步骤的大致相同,这里同样有enc-part
,它是使用前面KRB_AS_REP
阶段得到的key
字段加密的,解密后同样得到一个key
,作为下一阶段的认证密钥。
5. KRB_AP_REQ
Client
请求访问对应的服务,提供ST和KRB_TGS_REP
阶段得到的认证密钥加密的字段,以获取访问权限。通过设置ap-options
的MUTUAL-REQUIRED
可以进行双向认证。
6. KRB_AP_REP
除非Client
要求进行双向认证,否则服务端一般不回复KRB_AP_REP
.
三、扩展后的认证流程
Kerberos协议支持S4U扩展,通过此扩展可以实现委派的功能。
这时流程中存在四个角色:
Client
,客户端KDC
Service1
,代理用户请求的服务Service2
,要被访问的服务
S4U
扩展有两个子协议:S4U2self
和S4U2proxy
,前者让Service1
代表用户获得对Service1
自身的票据,也就是获得了Client
对Service1
的票据;后者则允许Service1
代表用户去请求Service2
的服务权限。
这里要说明的是,委派功能并不完全等同于S4U
扩展,还能使用forwarded TGT的方法实现,流程如下图:

从上面可以看出,这种方式要求Client
要先通过Kerberos的方式进行认证,而S4U2self
可以让用户使用其他的验证方式来获得对Service1
的访问权限,这样就简化了整体流程,也扩展了适用场景。
使用S4U
扩展后,委派的流程如下:

1. Request
Client
可以使用Kerberos以外的验证方式,来获得对Service1
的访问权限,这里Service1
并不需要得到Client
的相关凭据。
2. S4U2self
Service1
已经从KDC处得到了TGT,那么它会代表Client
去请求KDC,以获得自身可转发的ST.

可以看到padata
里多了pA-FOR-USER
,里面的KerberosString
字段表明Service1
是代表哪个用户进行请求的。

req-body
里能看到cname
和sname
都是Service1
,因为Service1
代替了Client
向KDC发起请求,请求的目标服务也是Service1
.
要想获得可转发的ST,需要满足:
使用的TGT是可转发的
Service1
配置了约束委派请求时设置了可转发标志
Client
不是敏感账户
3. Service ticket, as if from user
KDC返回对Service1
的可转发ST给Service1
4. Response
这一步实际上没什么作用,因为单靠S4U2self
协议并不能请求到其他服务,这需要靠S4U2proxy
完成。
5. Request
Client
向Service1
发起请求,需要Service1
以Client
的身份去访问Service2
,这里就要求Service1
通过前几个步骤来获得对自身的可转发ST.
6. S4U2proxy for Service 2
Service1
代表Client
向KDC请求获得Service2
的ST,这个ST也应是可转发的,所以kdc-options
应设置forwardable
和cname-in-addl-tkt
,后者是为了标志S4U2proxy
功能。

与普通的KRB_TGS_REQ
一样,使用的TGT放在padata
中。这里的cname
是Client
,sname
为Service2
.

这次还多了一个Service1
的ST,放在了req-body
的additional-tickets
中。
7. Ticket for Service 2
如果上一步的请求中存在特权属性证书(PAC),那么KDC会验证PAC,在PAC有效或不存在PAC的情况下,返回Service2
的ST给Service1
。此ST中cname
和crealm
字段存储的是Client
的信息,不是Service1
的信息。
8. Request As User
Service1
向Service2
发起请求,后者会将其看作是Client
,并且认为Client
已经通过了KDC验证。
9. Response
Service2
响应Service1
10.Response
Service1
响应用户
Last updated