Kerberos认证与委派

Kerberos协议认证全流程

  1. Client申请TGT

    Client向KDC的AS服务器提出请求。请求中包含Client用户hash加密的时间戳、Client的信息(Client info)等。之后由AS认证服务解密时间戳并在AD(活动目录)中查找该账户。如果能解密,且时间戳在一定的范围内,AS会生成一个随机的Session Key,并再返回给Client一张TGT票据(由krbtgt账户hash加密的Client info和Session Key)和Client账户hash加密后的Session key。

  2. Client向TGS服务申请访问目标服务的Ticket

    Client利用自己的hash对加密后的Session key解密,获得Session Key。之后Client再次KDC请求访问目标服务。该请求包含TGT和使用Session key加密的Client info。

    KDC使用Ktbtgt的Hash对TGT解密,获取Client info和Session Key。使用Session Key对Client发来的被Session key加密的Client info进行解密,获得Client info后,再比对TGT中的Client info,相同则认证通过。

    通过认证后,TGS会返回一张Ticket和使用Session key加密的Server Session key,这张Ticket使用Server hash加密,其中包含了Server session key和Client info。

  3. Client向Server提交Ticket完成认证

    Client收到消息后,使用Session Key解密获得Server Session Key。再向Server发送Server Session Key加密的Clinet info和TGS返回的Ticket。

    Server使用自己的hash解密Ticket,获得Server Session Key,再使用Server Session Key解密由Server Session Key加密的Clinet info,再比对Ticket中的Client info,相同则认证通过。

Kerberos PAC

在前面介绍的Kerberos认证流程中,只要用户的hash正确,那么就可以拿到TGT,有了TGT就可以拿到TGS,有了TGS就可以访问服务,任何一个用户都可以访问任何服务。忽略一个最重要的因素,那就是用户有无权限访问该服务。

为了解决这个问题,微软引进了PAC,引进PAC之后的kerberos流程:

  1. 用户向KDC发起AS_REQ,请求凭据是用户hash加密的时间戳,KDC使用用户hash进行解密,如果结果正确返回用krbtgt hash加密的TGT票据,TGT里面包含PAC(包含用户的sid以及用户所在的组)。

  2. 用户凭借TGT票据向KDC发起针对特定服务的TGS_REQ请求,KDC使用krbtgt hash进行解密,如果结果正确,就返回用服务hash加密的TGS票据。这一步不管用户有没有访问服务的权限,只要TGT正确,就返回TGS票据。

  3. 用户拿着TGS票据去请求服务,服务使用自己的hash解密TGS票据。如果解密正确,就拿着PAC去KDC询问用户有没有访问权限。

    域控解密PAC,获取用户的sid以及所在的组,再判断用户是否有访问服务的权限。

注:PAC对于用户和服务全程都是不可见的。只有KDC能制作和查看PAC。

S4U2SELF

S4U2self使得服务可以代表用户获得针对服务自身的kerberos服务票据。这使得服务可以获得用户的授权(可转发的用户TGS票据),然后将其用于后期的认证(主要是后期的s4u2proxy),这是为了在用户以不使用Kerberos的方式对服务进行身份验证的情况下使用。很重要的一点是服务代表用户获得针对服务自身的kerberos票据这个过程中服务是不需要用户的凭据的。

s4u2self的过程如下图所示

前提条件:服务已经有通过KDC验证的TGT(是以服务的自己身份去申请的TGT)

步骤1,服务(JACKSON-PC$)使用S4U2self扩展名代表用户(administrator)获得针对服务本身(JACKSON-PC$)的服务票证。该服务将填写PA_FOR_USER数据结构,类型为S4U2SELF,再将请求发送到TGS。

如果TGS支持PA_FOR_USER扩展,则TGS在步骤2中通过KRB_TGS_REP消息返回用户的服务票证。如果服务请求了可转发选项,并且TGS的本地策略允许,则TGS检验通过后必须将票证标志字段设置为可转发。

既只要满足下面三个条件,则TGS必须将票证标志字段设置为可转发。

  1. 服务申请的TGT是可以转发的
  2. 服务配置了约束委派
  3. 服务请求了可转发选项

如果用户的UserAccountControl字段中设置了USER_NOT_DELEGATED位,那么返回的TGS是永远也没法转发的。例如当Administrator配置了敏感账户不能被委派,返回的TGS的flag字段没有forwardable。

S4U2PROXY

s4u2proxy使得服务1向KDC请求访问服务2的TGS,代表用户访问服务2。

在步骤1中,服务1代表用户获取服务2的服务票证。服务1发送KRB_TGS_REQ消息,并将S4U2SELF阶段获得的票据作为请求中的AddtionTicket。

如果满足下面这些条件,则在步骤2中TGS会制作KRB_TGS_REP消息以返回服务票证(可转发的)

  1. 拥有来自用户的授权(在S4U2SELF阶段获得的TGS票据),放在AddtionTicket里面。
  2. 在请求的kdc-options中设置了CNAME-IN-ADDL-TKT标志。
  3. 服务请求了可转发选项
  4. 服务1有到服务2的约束委派,将服务2的SPN放在sname里面。

委派

被设置委派的对象只能是拥有SPN的账户

非约束委派

服务1被配置了非约束的委派,那么服务1可以接受任何用户的委派的去请求其他所有服务。例如:某个用户委托服务1访问某个服务,那么这个用户会将TGT(在TGS里面)发送到服务1并缓存到服务1的LSASS中。然后服务1代表用户去请求某个服务。

约束委派

约束委派会用到两个扩展S4U2Self和S4U2Proxy。计算机用户(JACKSON-PC$) 被配置了到某个服务的约束委派,那么JACKSON-PC$可以模拟任何用户去请求该服务。相较于非约束委派,约束委派在配置的时候需要指定委派某个服务,而不是所有服务。

收到用户的请求后,首先代表用户获得针对服务自身的可转发的kerberos服务票据(S4U2SELF)。拿着这个票据向KDC请求访问特定服务的可转发的TGS(S4U2PROXY)并代表用户访问特定服务。

  1. 服务1以服务账号hash加密时间戳并设置可转发的字段,再向KDC申请可转发的TGT。
  2. 服务1携带可转发的TGT并使用S4U2self扩展名代表用户(例如:Administrator)获得针对服务1本身的TGS票证(可转发的TGS)。 S4U2Self
  3. 服务1携带步骤1申请到的TGT和步骤2获取的可转发的TGS票证作为addtionTicket一起发送给KDC。请求代表用户访问服务2的TGS。 S4U2Proxy
  4. 服务1拿着TGS代表用户administrator向服务2发起请求。

Tips:

  1. S4U2self使得服务可以代表用户获得针对服务自身的kerberos服务票据。这个过程中服务代表用户获得针对服务自身的kerberos票据,服务是不需要用户的凭据的。
  2. 在步骤2中如果Administrator用户被配置敏感账户不能被委派的话,那么KDC返回的TGS就不是可转发的,就无法被用来做约束委派。

基于资源的约束委派

基于资源的约束委派只能在Windows Server 2012 R2和Windows Server 2012的域控制器上配置,但可以在混合模式林中应用。

基于资源的约束委派与传统约束委派非常相似但配置相反。服务1到服务2的约束委派在服务1账户的msDS-AllowedToDelegateTo属性中配置,定义从服务1到服务2的”传出”信任。而基于资源的约束委派是在服务2的msDS-AllowedToActOnBehalfOfOtherIdentity属性中配置,定义从服务1到服务2的”传入”信任。所以只要拥有服务2的权限就可以配置服务2的基于资源的约束委派。

参考

[^1]: AS_REQ & AS_REP
[^2]: TGS_REQ & TGS_REP
[^3]: 给大家讲个关于kerberos协议的故事…