使用受限制的双跳和模拟的SSO在Active Directory中使用Kerberos无法更新服务票证

问题描述 投票:0回答:1

深入探讨Kerberos约束委派已在Client/Server app, how to create process on remote system as a domain user without transferring that users username/password to the remote system?support kerberos constrained delegation using SSPI for multiprocess

我有一个分布式应用程序,它在多个服务器上工作,并依靠Kerberos令牌依靠SSO进行用户身份验证,并且所有内容都按照上述线程中的说明进行了布局(并可以正常工作)。简而言之,

  1. 用户连接到在Server1上运行的服务
  2. Server1会将用户的作业分派到正在运行的Server2服务主体帐户下的另一项服务 一个。 Server1请求(并获取)有关SPN的票证 b。 Server1将票证传输到Server 2
  3. Server2解析该票证(即AcquireCredentialsHandleAcceptSecurityContext),然后调用QuerySecurityContextToken,后跟DuplicateHandleCreateProcess,将重复的句柄传递给子进程,然后然后子进程调用ImpersonateLoggedOnUser
  4. Server2上的子进程现在正在模拟原始用户运行,并且正在能够以该用户的身份在某些Server3上访问网络资源]

所以,一切都很好,直到不再。在步骤2a中获得的服务票证的寿命最长为10小时(假设为服务票证的默认10小时有效期设置了AD)。票证寿命有时远少于10小时的原因是,在步骤1和2之间可能会有明显的延迟,例如,用户在提交要处理的工作之前可能要整天进行一些准备工作。因此,服务票证的结束时间将是原始用户登录后的10个小时,即与用户连接时生成的TGT的结束时间相匹配。

大约在服务票证到期前5分钟,Server2似乎试图续签该票证,并且在klist中确实显示了新的票证,用于表示Server2上子进程的LUID。但是,此新票证似乎是“格式错误的”,并且此时,客户端进程失去了被模拟用户时访问网络资源的能力。具体来说,尽管客户端进程仍然持有针对Server3资源的有效Kerberos服务票证,但是当从Server2到达Server3时,它会从Kerberos身份验证下降为NTLM身份验证,这时它将被Server3拒绝。

以下是klist输出的示例,该示例用于故障发生时在Server2上运行子进程的LUID的LUID;

Current LogonId is 0:0x5777e  
Targeted LogonId is 0:0x3966b5

Cached Tickets: (5)

#0>     Client: user @ VNET.COM
        Server: MSSQLSvc/sql.vnet.com:1433 @ VNET.COM
        KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
        Ticket Flags 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
        Start Time: 2/20/2020 22:21:02 (local)
        End Time:   2/21/2020 7:07:45 (local)
        Renew Time: 2/27/2020 21:07:45 (local)
        Session Key Type: RSADSI RC4-HMAC(NT)
        Cache Flags: 0
        Kdc Called: DC.Vnet.com

#1>     Client: user @ VNET.COM
        Server: ldap/DC.Vnet.com/Vnet.com @ VNET.COM
        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
        Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_canonicalize
        Start Time: 2/20/2020 22:21:02 (local)
        End Time:   2/21/2020 7:07:45 (local)
        Renew Time: 2/27/2020 21:07:45 (local)
        Session Key Type: AES-256-CTS-HMAC-SHA1-96
        Cache Flags: 0
        Kdc Called: DC.Vnet.com

#2>     Client: user @ VNET.COM
        Server: svc @
        KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
        Ticket Flags 0xa10000 -> renewable pre_authent name_canonicalize
        Start Time: 2/20/2020 22:23:37 (local)
        End Time:   2/21/2020 7:07:45 (local)
        Renew Time: 2/27/2020 21:07:45 (local)
        Session Key Type: RSADSI RC4-HMAC(NT)
        Cache Flags: 0x4 -> S4U
        Kdc Called: DC.Vnet.com

#3>     Client: user @ VNET.COM
        Server: svc @
        KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
        Ticket Flags 0xa10000 -> renewable pre_authent name_canonicalize
        Start Time: 2/20/2020 22:23:37 (local)
        End Time:   2/21/2020 7:07:45 (local)
        Renew Time: 2/27/2020 21:07:45 (local)
        Session Key Type: RSADSI RC4-HMAC(NT)
        Cache Flags: 0x4 -> S4U
        Kdc Called: DC.Vnet.com

#4>     Client: user @ VNET.COM
        Server: SVCD/APP.Vnet.com @ VNET.COM
        KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
        Ticket Flags 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
        Start Time: 2/20/2020 22:11:39 (local)
        End Time:   2/20/2020 22:26:39 (local)
        Renew Time: 0
        Session Key Type: RSADSI RC4-HMAC(NT)
        Cache Flags: 0x8 -> ASC
        Kdc Called:

在上面的清单中,票证#4是在步骤2a中请求的原始服务票证; SPN为“ SVCD / APP.Vnet.com”,与此SPN相关联的域帐户(并运行Server2服务进程)为“ svc”。该票证用于在Server2上创建用户的安全上下文,并且子进程正在模仿该安全上下文。在子进程尝试访问LDAP和MS SQL服务器(对于子进程需要执行的工作)时,模拟后生成票证#0和#1,因此这确认所有受约束的委派设置均正确并且子进程正在运行预期长达10小时。在某些情况下,需要更新票证#0和#1-它们已成功更新,并且过程一直在进行。

现在,问题是:#2和#3滴答声是在#4结束前几分钟生成的,但对我来说似乎很奇怪的是ServerRealm部分,即“ svc @…”为空白。同样,在生成这些票证的那一刻,Server2子进程停止能够打开与Server3的新MS SQL连接(并且在Server3上,匿名登录拒绝事件将与匹配的时间戳一起记录)。我还应该提到,尽管在上面的示例中有两个相同的“ Server:svc @”票证,但在某些情况下,我会看到7、14,甚至30多个相同的票证。所有这些都在同一时间发布,好像Server2进行了一些疯狂的尝试来从KDC中获得所需的东西一样,但是失败了。

我的解释是Server2想要续订用于模拟的服务票证,但未能这样做。

至此,我不确定问题是否存在; a)AD设置(即受约束的委托详细信息),或 b)具有“ svc”域帐户的权限(它具有SetImpersonatePrivilege,但可能还需要其他内容),或 c)以用户安全上下文在Server2中的父进程和子进程之间转移的方式,或 d)完全不同的东西

到目前为止,在花了很多时间阅读和研究之后,我已经尝试了c的各种序列排列)(例如,使用DuplicateTokenEx + CreateProcessAsUser来代替,在各种标志周围翻转以获取重复的句柄和令牌等),但我对a)和b)可以而且应该做什么(如果有的话)感到困惑。我尝试更改某些设置没有任何效果,但是我避免使用“核”选项,例如在svc帐户上设置SeTcbPrivilege,因为在我看来,这是不可接受的解决方案。

最后的观察结果是,票据#4缺少“ Kdc Called”和“ Renew Time”,但是我印象深刻的是,这是通过InitializeSecurityContext获得的不透明票据的一种正常现象。

为了使Server2上的子进程能够在最初的10小时后运行,我需要更改什么?

c++ windows active-directory kerberos kerberos-delegation
1个回答
0
投票

我通过Farzan Mirheydari提供的注释解决了该问题,可以将其简化为在AD中为[[svc

© www.soinside.com 2019 - 2024. All rights reserved.