如果您有某个服务的密钥表,您是否可以使用 Kerberos 命令行工具在本地检查是否可以获取有效的服务票证,而无需实际部署该服务,而只需拥有该服务的密钥表?
例如
kinit
check_against --verbose httpservice.keytab HTTP/[email protected]
[email protected] not allowed for HTTP/[email protected]
或者是否有一些开源代码可以做到这一点?
答案1
按照您在示例中展示的具体方式吗?不,因为票证和密钥表都根本不包含这种“用户 X 允许使用服务 Y”的信息。
票证可能包含用户名或组成员身份(PAC)等原始信息,但它们不会通过密钥表进行验证;它们只是解密使用 keytab(它实际上是一个“加密密钥表”),但任何实际的授权检查都将由服务自己的代码/逻辑完成。因此,keytab 的唯一用途是从票证中查看 PAC 的原始内容,而不是获得通过/失败。
(我不知道任何用于解密 PAC 的通用工具——“Active Directory 红队”工具中可能有一些。)
在极少数情况下,KDC 在签发票证之前会进行授权检查,这时 keytab 也毫无用处,因为如果授权检查失败,KDC 根本不会签发票证——它不会签发故意无效的票证。所以如果是这种情况,只需请求票证并查看是否能拿到票证就足够了。(不过,我怀疑情况并非如此。)
(MIT Krb5 有kvno
请求票证的命令,但还有其他方法。)
因此,就“有效性”而言,您唯一能做的检查是密钥表是否能够解密票证(即密钥表中的密钥是否与 KDC 上的密钥同步)。为此,您不需要具体的服务,但最简单的方法实际上是让 Kerberos 库执行整个身份验证过程仿佛您就是服务。换句话说,编写一个最小的 Kerberos 服务,该服务只与自身进行 GSSAPI 身份验证(作为客户端和服务器)。幸运的是,这只需要几行python-gssapi
:
keytab = "foo.keytab"
spn = gssapi.Name("[email protected]", gssapi.NameType.hostbased_service)
server_creds = gssapi.Credentials(usage="accept", name=spn,
store={"keytab": keytab})
server_ctx = gssapi.SecurityContext(usage="accept", creds=server_creds)
client_ctx = gssapi.SecurityContext(usage="initiate", name=spn)
# Client: Get the token that would be sent in "Authorization: Negotiate"
c2s_token = client_ctx.step(None)
# Server: Consume the token (verify it against the keytab)
# Throws an exception if the keytab is out of sync with the KDC
s2c_token = server_ctx.step(c2s_token)
# Server: Read out the client principal name from the ticket
if server_ctx.complete:
print("Authenticated as", server_ctx.initiator_name)
这基本上就是 mod_auth_gssapi(或旧版 mod_auth_kerb)验证票证时所做的操作。再次注意,它不执行任何授权检查——Kerberos 所做的只是说“票证属于用户 X”,而实际的访问检查必须由程序本身完成。