域委派:使得上游服务能使用用户凭据访问下游服务,使得下游服务根据域用户判断权限,例如:
web 用户 hack ---------------访问------------------> web 服务器 ( www-data 域服务账户运行)-------------------访问(以 hack 用户的身份)----------------------> 数据库服务器( SQLServiceAccount 服务账户运行)
当 hack 用户访问 web 服务器时,在 web 服务器上运行代码的用户是域用户 www-data ,而执行 web 后端代码操作的是 hack 用户, www-data 属于系统层,hack 属于应用层。当 web 服务器使用委派访问数据库服务器时,数据库服务器运行代码的用户是域用户 SQLServiceAccount ,而执行查询操作的用户是 hack 用户,SQLServiceAccount 属于系统层,hack 属于应用层。
当 web 服务器访问数据库时,并没有以 www-data 域内服务账户访问数据库服务器,而是通过委派利用 hack 用户的身份进行访问。上游服务:委派用户凭据的服务。下游服务:被上游服务访问的服务。
只有注册了 spn 的账户(服务账户或机器账户)才有可能用于委派,因为 spn 能将域用户映射到域服务。
3种委派
-
非约束性委派(UD:Unconstrained Delegation)
-
约束性委派(CD:Constrained Delegation)
-
基于资源的约束性委派(RBCD:Resource Based Constrained Delegation)
非约束性委派(UD)
上游服务账户能够获取用户的 tgt 认购权证,并将 tgt 缓存到 lass 进程,使得上游服务账户能利用用户的 tgt 认购权证,以用户的权限访问其他服务。
注,非约束性委派的特点:
-
非约束性委派设计时,没有对上游服务账户获取用户的 tgt 进行限制,使得服务账户能使用用户的 tgt 请求到任何服务的 st ,这使得服务账户使用用户凭据访问任何服务。
-
非约束性委派的配置需要 SeEnableDelegationPrivilege 特权,域管理员和企业管理员默认有这个特权。
-
非约束性委派配置在上游服务账户上,不会被下游服务所约束。
-
配置了非约束性委派的机器账户的 userAccountControl 属性:WORKSTATION_TRUST_ACCOUNT | TRUSTED_FOR_DELEGATION,对应16进制0x81000 。
-
配置了非约束性委派的服务账户的 userAccountControl 属性:NORMAL_ACCOUNT | TRUSTED_FOR_DELEGATION,对应16进制0x80200 。
-
域控默认配置了非约束性委派,也有 TRUSTED_FOR_DELEGATION 标志位。
非约束性委派流程
-
用户发送 as-req 请求上游服务1。
-
kdc 发送 as-rep 返回 tgt1 认购权证。
-
用户发送 tgs-req 请求下游服务2。
-
kdc 发送 tgs-rep 返回可转发的 tgt2 认购权证。
总结前4步:用户请求两个 tgt , tgt1 要用来请求上游服务1的 st ,另一个 tgt2 是用来发给上游服务1的可转发的 tgt ,上游服务1有了这个可转发的 tgt2 ,他将能够代表用户访问其他服务。
-
用户利用 tgt1 向 kdc 发送 tgs-req 请求上游服务1的 st 服务票据。
-
kdc 发送 tgs-rep 返回上游服务1的 st 服务票据给用户。
-
用户使用 st 发送 ap-req 请求上游服务1,同时发送了 tgt1 和可转发的 tgt2,以及 tgt2的 Session Key。
-
tgt1 的作用就是普通的 Kerberos 身份验证请求。
-
tgt2 是可转发的,它的作用就是发送给上游服务,供其使用。
注:上游服务想要使用 tgt2 来代表用户访问其他服务,就需要获得 tgt2 内的 Session Key (因为 tgs-req 请求服务票据需要 Session Key 加密时间戳作为身份验证),所以上游服务获得 Session Key 需要通过用户接受到 tgt2 的 as-rep 请求包后,使用用户密码 hash 解密 Logon Session Key 后,将 Session Key 发送到上游服务。
-
-
上游服务1的服务账户利用可转发的 tgt2 请求下游服务2的 st ,以代表客户访问服务。
-
kdc 返回 下游服务2的 st 给 上游服务1。
此时服务1的服务账户拿到了服务2的 st 服务票据,就可以访问服务2了
-
服务1的服务账户发送 ap-req 请求服务2。
-
服务2验证 ap-req ,并响应结果给服务1。
-
服务1的服务账户有了响应结果后,处理转发给用户。
总结:用户直接将自己请求到的 tgt 认购权证发给上游服务1服务账户供它使用,代表用户对上游服务1的充分信任,上游服务1有权利使用用户凭据进行任何操作。
漏洞:
非约束性委派配置在上游服务账户上,不会被下游服务所约束。这使得上游服务进行委派时, kdc 只会判断上游服务有没有配置委派。此时如果上游服务的凭据被攻击者拿到,那么攻击者利用此上游服务获得到在此服务上配置委派的用户的凭据。
非约束性委派的配置
域控默认配置了非约束性委派,非约束性委派的配置对应如下图的 “信任此 计算机/用户 来委派任何服务” 选项:
当我们对某个用户添加此选项后,此用户拥有了非约束性委派权限。
约束性委派(CD)
管理员指定了配置约束性委派的服务账户能利用用户身份访问某些固定的服务,相比于非约束性委派,上游服务代表用户访问的下游服务,必须要有管理员来指定。
两种约束性委派:
-
仅使用 kerberos(不能进行协议转换)
-
使用任何身份验证协议(能进行协议转换)
仅使用 kerberos
-
机器账户和服务账号的 userAccountControl 属性与正常账号一样。
-
机器账户和服务账号的 msDS-AllowedToDelegateTo 属性会有允许被委派的下游服务 spn 。
使用任何身份验证协议
-
机器账户的userAccountControl属性:WORKSTATION_TRUST_ACCOUNT | TRUETED_TO_AUTHENTICATE_FOR_DELEGATION,对应的16进制是0x1001000 。
-
服务账户的userAccountControl属性:NORMAL_ACCOUNT | TRUETED_TO_AUTHENTICATE_FOR_DELEGATION,对应的16进制是0x1000200 。
-
机器账户和服务账号的 msDS-AllowedToDelegateTo 属性会有允许被委派的下游服务spn 。
约束性委派流程
上图描述了以下协议步骤:
-
用户向上游服务1发出身份验证请求。此步骤身份验证是通过 Kerberos 以外的其他方式执行的(例如:通过 web 表单的方式或 NTLM 方式进行认证)。
-
上游服务1向 kdc 发送 kerberos 认证获取 tgt 后,使用此 tgt 发送使用了 s4u2self 扩展的 tgs-req 请求,用于请求可转发的上游服务1访问自身的 st 。
-
上游服务1首先获得一个 TGT(假设它已经从 Kerberos KDC 获得了自己的 TGT)。
-
然后,服务1会使用自己的 TGT 发出一个带有 S4U2Self 扩展的 TGS-REQ 请求,来请求获取一个针对自己的服务票据(ST)。
-
S4U2Self 扩展的作用是请求可转发的、用于访问自身的 ST。这种服务票据是可转发的,并且服务可以用它来访问自身资源。
-
在此之后,我们称这个可转发的上游服务1访问自身的 st 为 S4U2Self 票据 。
-
-
kdc 在 tgs-rep 返回 S4U2Self 票据 。
-
上游服务1使用 S4U2Self 票据 响应用户的请求。
-
用户继续向上游服务1发出请求。此时上游服务1需要以用户身份访问下游服务2上的资源。
-
上游服务1发送 s4u2proxy 扩展的 tgs-req 请求,此请求中不光携带着这一次 kerberos 通信的 tgt 还携带着 S4U2Self 票据 ( s4u2self 阶段得到的),kdc 将判断此 st 的合法性。
-
如果此 st 是合法的,kdc 将返回可转发的用户身份的访问下游服务2的 st ,此 st 的 cname 和 crealm 字段中存储的客户端身份是用户的身份。
-
在此之后,我们称这个可转发的用户身份的访问下游服务2的 st 为 S4U2Proxy 票据 。
-
-
上游服务1使用 S4U2Proxy 票据 向下游服务2发出请求。下游服务2将此请求视为来自用户,并假定用户已通过 kdc 的身份验证。
-
下游服务2响应请求。
-
上游服务1响应用户的消息5的请求。
S4u2Self
S4U2proxy 扩展用于请求一个可转发的用户身份的访问下游服务2的 st (也就是 S4U2Proxy 票据 ),在此之前S4U2proxy 扩展需要一个可转发的上游服务1访问自身的 st (也就是 S4U2Self 票据 )作为上游服务1的身份验证凭据,而这个 S4U2Self 票据,就是上游服务1使用自身的 tgt 向 kdc 发送携带 S4u2Self 扩展的 tgs-req 来请求到的。也就是说 S4U2proxy 的完成依赖于 S4u2self 步骤获得的 S4U2Self 票据。
流程:
显然 s4u2self 扩展是在 tgs-req 和 tgs-rep 请求服务票据的时候,s4u2self 目的就是请求一个可转发的、自身服务访问自身服务的一个 S4U2Self 票据,他不光能进行 s4u2proxy 扩展的认证,还能让服务使用这个 st 服务票据访问自身服务。所以说 S4U2Self 票据 有如下两个作用:
-
作为身份验证的凭据,用于请求 S4U2Proxy 票据 。
-
单纯使用 S4U2Self 票据 访问自身服务
S4u2Proxy
还是之前说的那一点:S4U2proxy 的完成依赖于S4u2self 步骤获得的 S4U2Proxy 票据 。基于 S4U2Self 票据,KDC 会验证上游服务的身份和委派权限,并生成 S4U2Proxy 票据 。而这里的 S4U2Proxy 票据 就能代表用户访问目标服务。
如下步骤:
tgs-req 要请求 S4U2Proxy 票据 ,但要注意的是,tgs-req 不仅发送了针对这一次 kerberos 通信的 tgt ,还发送了之前 s4u2self 请求过来的可转发的、访问自身服务的一个 S4U2Self 票据。
基于资源的约束性委派(RBCD)
拥有配置目标服务的基于资源的约束性委派的域用户有:
-
域管理员。
-
将此服务加入域内的域账户,也就是服务的 mS-DS-CreatorSID 属性。
配置了基于资源的约束性委派账户的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性的值为被允许委派的上游服务的 SID。但需要注意的一点,基于资源的约束性委派是配置在下游服务上的。
基于资源的约束性委派是配置在下游服务 B 上的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性,kdc 通过查询下游服务 B 的此属性得知哪些域用户具有委派访问权限。
-
上游服务 A 使用自身身份申请 tgt 。
-
tgs 阶段使用 s4u2self 申请上游服务 A 针对自身的不可转发 的 st 。(此后称之为 S4U2Self 票据 )
-
服务 A 第二次 kerberos 认证,tgs 阶段使用 s4u2proxy 使用用户身份申请可转发的 st(目标服务是服务 B ),且 tgs-req 的数据包还携带 s4u2self 阶段的不可转发的st。(此后称之为 S4U2Proxy 票据 )
-
ap 阶段使用 S4U2Proxy 票据 代表用户身份访问服务 B 。
约束性委派的 S4u2Self 票据 是可转发的,而基于资源的约束性委派的 S4u2Self 票据 是不可转发的。这是因为 S4u2Self 票据 可转发标志是微软专门为约束性委派设计的,只有上游服务 A 的 msDS-AllowedToDelegateTo 不为空时(配置了约束性委派) ,S4u2Self 票据 就是可转发的。换言之,只要上游服务配置了约束性委派,其 S4u2Self 票据 不论在任何通信中,都是可转发的。然而当我们使用基于资源的约束性委派时,往往上游服务不用配置 msDS-AllowedToDelegateTo ,所以 S4u2Self 票据 保持默认不可转发。
总结
-
非约束性委派配置在上游服务,上游服务使用用户发送的的可转发的 tgt 访问服务。
-
约束性委派配置在上游服务的 msDS-AllowedToDelegateTo 属性中,此属性指明了合法的下游服务。
-
基于资源的约束性委派配置在下游服务的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性中,此属性指明了合法的上游服务。