Kerberos(3)-委派工作原理

委派工作原理

委派(SPN)是域中的一种安全设置,是指将域内用户的权限委派给服务账号,使得服务账号能以用户的权限在域内执行某个操作。 例:当A访问服务B时,服务B拿着A用户的凭证去访问服务C,这个过程称为委派。委派分为三种方式:

  1. 非约束性委派
  2. 约束性委派
  3. 基于资源的约束性委派(RBCD)

用户和服务

用户

在域中,可以找到不同类型的用户帐户:

普通域用户:用来执行日常操作或者特定任务。

机器用户:computers组内计算机,账号后面有个$。从域的角度来看,计算机是用户,也可以说计算机是用户的子类。

服务用户:运行服务并将服务加入域内的用户,如SQL Server、MYSQL等。域用户通过注册SPN也能成为服务账号。

在域内只有机器账号和服务账号才有委派属性。

服务

对于服务的解释:

  • 由域中的SPN(服务主体名称)标识,它表示服务的名称、类别、所有者和主机。
  • 作为一个进程在计算机(服务的主机)中执行。但是服务不一定要运行才能获取TGS。
  • 在域用户(服务的所有者)的上下文中执行。服务通常在其主机的计算机账户的上下文中运行,但不是每次都这样。
  • 可以由域的许多用户(如Kerberos、LDAP、SMB或者MSSQL)使用,并且任何域用户都可以获得域中任何服务的TGS。

这里需要注意的就是服务(作为进程)在用户账户的上下文中运行,所以具有该用户的权限。域用户可以拥有服务,其服务的SPN存储在用户的属性ServicePrincipalName的值中。

如果想为用户添加SPN,需要Validated-SPN权限,默认情况下普通域用户无权限但是机器账号有权限,普通域用户需要域管理员来添加权限。

服务委派

由于服务是在它所有者用户的上下文中执行,所以kerberos委派存在以下特点:

  • 只有当服务的所有者用户有权执行委派时,服务才能执行委派。就是用户有委派权限,则其所有服务和进程都具有委派权限。
  • 当服务与KDC交互的时候,服务具有其所有者用户的身份。因为KDC只关心和它交互的用户,而不是服务和进程。多以属于同一用户的任何服务和进程都可以在Kerberos中执行相同的操作。

域中对于委派安全的措施

在域中有两种方式可以避免对特定的用户账号进行任何委派:

  • 设置用户账户User-Account-Control 属性中的 NotDelegated(或 ADS_UF_NOT_DELEGATED)标志。此标志将禁用账户的任何类型委派。默认情况是没有设置的。
  • 将用户添加到受保护用户组中(windows server 2012 r2才有此功能)。默认情况该组没有成员。受保护用户组内用户受限内容:
    • 无法使用NTLM身份验证。
    • 在kerberos预身份验证中不能使用DES或者RC4加密。
    • 不能使用任何类型的kerberos委派。
    • kerberosTGT票据超时时间不能超过默认的4小时。

研究委派相关内容,默认假设用户不经过以上处理。

无约束委派

无约束委派是最简单的委派类型,它允许服务无限制的模拟任何经过身份验证的用户。在无约束委派中,相当于服务为用户获取了一个有效的TGT票据,这样服务在kerberos认证流程中就相当于这个用户。

服务为用户获取TGT:

当用户为无约束委派服务请求TGS时,KDC在TGS中包含了用户的TGT。

具体来说,用户的TGT包含在服务所有着密钥加密的票据中,所以服务接收到TGS后,是可以获取到用户的TGT。

KDC如何将用户的TGT包含在TGS中:

如果服务的所有着设置了TrustedForDelegation(或ADS_UF_TRUSTED_FOR_DELEGATION)标志,KDC将包含TGT。此标志存储在域用户账户的“用户账户控制”属性中。

需要注意,为了修改用户的TrustedForDelegation标志,需要在域控制器上拥有SeEnableDelegationPrivilege 权限。

例:

下图是目前比较详细的委派流程图。

img

流程步骤如下

  1. User1为UserZ的ServerceZ服务请求一个TGS。
  2. KDC检查UserZ是否设置了TrustedForDelegation标志(是)。
  3. KDC在ServiceZ的TGS中包含User1的TGT。
  4. ServiceZ接收包含User1的TGT的TGS并将其存储在内存中供以后使用。

攻击方式思路

目前无约束委派在实战中基本遇不到。但是基本利用方式了解以下,之后委派攻击实战中演示。

主要方式还是让特权用户来请求受控的服务进行交互,这样就可以窃取到特权用户的额TGT。

还有种利用方式是留后门,给控制的用户添加无约束委派属性。

当然也能在控制的服务或者用户中找到存储的其他用户TGT,可能性比较小。

约束委派和基于资源约束委派

除了无约束委派,还有两种委派方式:

  • 约束委派
  • 基于资源的约束委派(RBCD)(在windows server 2012引入)

这两种委派实质是受委派的服务只能代表用户访问在白名单中的第三方服务。

Kerberos创建白名单服务

Kerberos本身无法创建特殊票据来为某个用户或者用户组实现委派。出于这也原因,微软实现了2个Kerberos扩展,允许服务代表特定的用户向自己请求一个特殊的可转发服务票据,这样用户可以不使用Kerberos的方式去进行服务进行身份验证,让受委派的服务去使用kerberos认证其他服服务。而这两个扩展是:

  • S4U2Proxy(用户代理服务)
  • S4U2Self(用户自我服务)

S4U2Proxy

S4U2Proxy 是一个扩展,它允许服务使用用户发送的 TGS 来代表用户从 KDC 为第三方服务获取新的 TGS。

KDC判断用户TGS第三方服务申请TGS的依据

KDC必须检查两个列表:

  1. 用户都有一个可以为哪些服务请求TGS的列表。此列表存储在用户的msDS-AllowedToDelegateTo属性中。要修改此属性,需要SeEnableDelegationPrivilege权限,这个列表只在委派中使用。
  2. 用户都有一个允许向任何服务获取TGS的用户列表。此列表存储在msDS-AllowedToActOnBehalfOfotherIdentity属性中。用户自己可以根据需求编辑自己的允许用户列表。这就是RBCD中使用的列表。

因此,KDC 将检查以下条件,以确定是否可以应用委托。

  • 如果服务客户端受到保护,不能被委托(受保护用户组的成员或设置了 NotDelegated 标志),那么 S4U2Proxy 将失败。
  • 如果请求的服务在 msDS-AllowedToDelegateTo 中,则KDC将检查:
    • 发送的TGS是可转发的(设置了 forwardable 标志),那么KDC将为请求的服务返回一个可转发的TGS(应用于约束委派)
    • 否则S4U2Proxy将失败。
  • 如果请求TGS的用户在被请求的服务所有者用户的msDS-AllowedToActOnBehalfOfOtherIdentity 属性中,那么KDC将返回一个可转发的 TGS (应用于RBCD)。
  • 否则S4U2Proxy将失败。

此外,如果用户可以为相同的目标服务应用约束委派和RBCD,则约束委派将优先;这意味着在这种情况下,如果发送的 TGS 无法转发,那么甚至不去尝试应用 RBCD, S4U2Proxy 就会失败。 这里有一个特殊的地方是 S4U2Proxy 返回的 TGS,始终是可转发的。

S4U2Proxy 在约束委派中的例子:

img

在这个例子中:

  1. User1 将 TGS 发送到 ServiceZ。

  2. UserZ 拥有的 ServiceZ 使用此 TGS 代表 User1 向 KDC 请求 ServiceX 的 TGS 。

  3. KDC 检查:

    1. ServiceX 被列在 UserZ 中的 msDS-AllowedToDelegateTo 是否为 yes。
    2. 发送的 TGS 是否是可转发的,若是,则可以约束委派。
  4. KDC 向 ServiceZ 返回 TGS,以代表 User1 与 ServiceX 交互。

  5. ServiceZ 通过模拟 User1 使用新的 TGS 与 ServiceX 交互。

S4U2Proxy 在RBCD中的例子:

img

在这个例子中:

  1. User1将 TGS 发送到ServiceZ。
  2. UserZ 拥有的 ServiceZ 使用此 TGS代表 User1向 KDC 请求ServiceX 的 TGS 。
  3. KDC 检查:
    1. ServiceX 被列在 UserZ 中的 msDS-AllowedToDelegateTo 是否为NO,若是,则不能约束委派。
    2. 如果 UserZ 被列在 UserX 的 msDS-AllowedToActOnBehalfOfOtherIdentity 中,则成为 ServiceX 的所有者(yes)。可以RBCD。
  4. KDC 向 ServiceZ 返回 TGS 以代表 User1 与 ServiceX 交互。
  5. ServiceZ 通过模拟 User1 使用新的 TGS 与 ServiceX 交互。

扩展

使用 TGS 有一个有趣的技巧:只需更改目标服务名称,就可以为同一用户的任何服务使用相同的 TGS。

这是因为:

  1. 服务名称写在票据的明文部分,任何人都可以修改。

  2. 同一用户的所有服务共享相同的 Kerberos 密钥,因此任何服务都可以正确解密同一用户的另一个服务的 TGS。

此技巧可用于绕过受约束委派使用的服务的白名单 ( msDS-AllowedToDelegateTo )。

例:

img

在这个例子中:

  1. User1 将 TGS 发送给 ServiceZ。
  2. UserZ 拥有的 ServiceZ 使用这个 TGS 去请求 KDC 为 ServiceX 提供 TGS,该TGS由UserXY 代表 User1 拥有。
  3. KDC 检查:
    1. ServiceX 在UserZ 中的 msDS-AllowedToDelegateTo 是否为NO,若是,则不能约束委派。
    2. UserZ 在 UserXY 中的 msDS-AllowedToActOnBehalfOfOtherIdentity 是否为NO,若是,则不能RBCD。
  4. KDC 拒绝 ServiceZ 提出的请求。
  5. ServiceZ 代表 User1 请求 KDC,为UserXY 拥有的另一个服务 ServiceY 提供一个TGS。
  6. KDC 检查:
    1. ServiceY 在 UserZ 的 msDS-AllowedToDelegateTo 中是否为 yes。
    2. 发送的 TGS 是否是可转发的,若是,则可以约束委派。
  7. KDC 将 TGS 返回给 ServiceZ 以代表 User1 与 ServiceY 交互。
  8. ServiceZ ( UserZ ) 将 TGS 的目标服务从ServiceY 更改为ServiceX。
  9. ServiceZ通过模拟 User1 使用修改后的 TGS 与 ServiceX 交互。

这不是常规服务的正常操作过程,因为几乎没有服务会编辑 TGS 的服务名称来和其他服务联系,这种行为是攻击者的典型操作,攻击者试图使用这个技巧来绕过 KDC 施加的限制。

S4U2Self

S4U2Self 的目的是允许对不支持 Kerberos 身份验证的服务使用委派,这些服务无法从客户端用户获取 TGS。

为了绕过这个限制,S4U2Self 允许服务代表另一个用户为自己请求 KDC 的 TGS;这也称为协议转换。

可使用S4U2Self的用户

KDC 会根据用户帐户的某些特征(例如帐户的服务和 TrustedToAuthForDelegation 标志)对 S4U2Self 请求做出不同的响应。

TrustedToAuthForDelegation(或 ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION)标志被包含在 User-Account-Control 用户帐户的属性,要修改此标志,需要在域控制器中具有 SeEnableDelegationPrivilege 权限。

为了使用 S4U2Self,KDC 将遵循以下规则:

  • 如果用户没有服务,那么 KDC 将不会返回 TGS。
  • 如果模拟的目标用户不允许被委派(因为在受保护的用户组中或设置了 NotDelegated 标志),那么 KDC 将返回一个不带 forwardable 标志的TGS。TGS 如果还包含了 an incorrect service name(https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html#solving-a-sensitive-problem),可以根据链接内容进行修改。
  • 如果为用户设置了TrustedToAuthForDelegation标志,则 KDC 将返回带有可转发标志的 TGS 。
  • 如果没有为用户设置 TrustedToAuthForDelegation 标志,那么 KDC 将返回一个不带 forwardable 标志的TGS。

S4U2Self 示例

img

在这个例子中:

  1. User 1在不使用 Kerberos 的情况下对 ServiceZ 执行身份验证。在这种情况下可以使用 NTLM 或其他协议。
  2. UserZ拥有的ServiceZ代表User1为自己请求一个TGS。
  3. KDC 检查:
    1. UserZ是否是任何服务的所有者(yes)。
    2. TrustedToAuthForDelegation 标志是否设置为 UserZ 帐户(yes)。
  4. KDC 代表 User1 为自己返回一个可转发的 TGS 给 ServiceZ,它可以在 S4U2Proxy 中使用。

S4U2Self 和 S4U2Proxy 一起使用的例子

在约束委派下

img

在这个例子中:

  1. User1 在不使用 Kerberos 的情况下对 ServiceZ 执行身份验证。在这种情况下可以使用 NTLM 或其他协议。
  2. UserZ 的 ServiceZ 代表 User1 为自己请求一个 TGS。
  3. KDC 检查:
    1. UserZ 是否是任何服务的所有者(yes)。
    2. TrustedToAuthForDelegation 标志是否设置为 UserZ 帐户(yes)。
  4. KDC 代表 User1 为自己向 ServiceZ 返回一个可转发的TGS。
  5. ServiceZ 使用此 TGS 代表 User1 向 KDC 请求 ServiceX 的 TGS。
  6. KDC 检查:
    1. ServiceX 被列在 UserZ 中的 msDS-AllowedToDelegateTo 是否为 yes。
    2. 发送的 TGS 是否是可转发的(yes),若是,则可约束委派。
  7. KDC 将可转发的 TGS 返回给 ServiceZ 以代表 User1与 ServiceX 交互。
  8. ServiceZ 通过模拟 User1 使用新的 TGS 与 ServiceX 交互。

在RBCD下

img

在这个例子中:

  1. User1 在不使用 Kerberos 的情况下对 ServiceZ 执行身份验证。在这种情况下可以使用 NTLM 或其他协议。
  2. UserZ 拥有的 ServiceZ 代表 User1 为自己请求 TGS。
  3. KDC 检查:
    1. UserZ 是否是任何服务的所有者(yes)。
    2. TrustedToAuthForDelegation 标志设置是否为UserZ帐户(yes)。
  4. KDC代表User1为自己向ServiceZ返回一个可转发的TGS。
  5. ServiceZ使用此 TGS代表User1向 KDC 请求ServiceX的 TGS 。
  6. KDC 检查:
    1. ServiceX 被列在 UserZ 中的 msDS-AllowedToDelegateTo 是否为 NO,若是,则不能受约束的委派。
    2. 如果 UserZ 列在 UserX 的 msDS-AllowedToActOnBehalfOfOtherIdentity 中,则成为 ServiceX 的所有者(yes);可以RBCD。
  7. KDC 将可转发的 TGS 返回给 ServiceZ 以代表 User1 与 ServiceX 交互。
  8. ServiceZ 通过模拟 User1 使用新的 TGS 与 ServiceX 交互。