通过抓包工具了解下 kerberos的 pre-authentication是如何工作的
1 一个因keytab文件失效导致认证失败的问题
某客户大数据集群中的HIVE开启了kerberos安全认证(hive.server2.authentication=kerberos),某业务应用使用管理员提供的pricipal和keytab创建到 hs2 的JDBC链接时频繁报错,通过命令行验证该prinical和keytab也频繁报错(kinit xx -kt xx.keytab)。 于是果断打开kdc服务端日志(MIT kerberos 默认是 /var/log/krb5kdc.log),发现了类似如下相关日志:
## /var/log/krb5kdc.log相关日志: May 10 15:20:39 uf30-1 krb5kdc[6377](info): AS_REQ (1 etypes {17}) 192.168.71.70: NEEDED_PREAUTH: dap2@CDH.COM for krbtgt/CDH.COM@CDH.COM, Additional pre-authentication required May 10 15:20:39 uf30-1 krb5kdc[6377](info): closing down fd 13 May 10 15:20:39 uf30-1 krb5kdc[6377](info): preauth (encrypted_timestamp) verify failure: Preauthentication failed May 10 15:20:39 uf30-1 krb5kdc[6377](info): AS_REQ (1 etypes {17}) 192.168.71.70: PREAUTH_FAILED: dap2@CDH.COM for krbtgt/CDH.COM@CDH.COM, Preauthentication failed # 命令行执行kinit相关报错: kinit: Preauthentication failed while getting initial credentials
日终中很明确地提示了,"Additional pre-authentication required",且“Preauthentication failed”,而该错误的常见原因是,客户端和服务端时钟差异过大(一般默认是5分钟),或者KDC服务端修改了对应principal的密码(可能是有意修改,也可能是无意修改),于是找管理员重新生成了一份该principal的新的 keytab 文件,切换使用该新版本keytab文件后问题解决:
- This preauthentication failure can happen for several reasons. Mostly we see when either the password for the relevant account in the Active Directory has changed since the keytab file was created;
- or the system clock is off by about 5 minutes from that of the Active Directory.
- 通过klist -ekt xxx.keytab 也可以对比发现新旧keytab文件的KVNO不同,所以可以确认旧的KEYTAB文件是失效的:
问题虽然解决了,但什么是 pre-authentication 呢?其又是如何工作的呢?
2 什么是 pre-authentication
简单来讲,pre-authentication 是 Kerberos V5 版本对V4版本在安全感上的一个增强,可以抵御针对 kerberos协议的 AS-REP Roasting 攻击,该攻击截获 AS-REP 数据包并采用离线手段对用户密钥进行暴力破解:
- 使用 Kerberos 协议过程中,共涉及到6类请求和响应(AS_REQ/AS-REP,TGS_REQ/TGS_REP,AP-REQ/AP-REP),这些请求和响应底层的 IP PACKET 数据包在网络传输过程中可能会被网络嗅探工具截获;
- 为了防止网络嗅探安全问题,KERBEROS在任何数据包中都不会明文传输用户密钥,而是采用特定算法对用户密钥的HASH值(附加一些时间戳和SALT数据)进行加密传输,接收端用相同的算法和密钥HASH解密后即可验证数据的有效性;
- 虽然没有明文传输密钥,但AS_REQ 数据包可以被截获以进行重放攻击(packet replay attack)从而从KDC获取新的AS_REP数据包;
- 虽然没有明文传输密钥,但AS_REP 数据包可以被截获,由于 AS-REP 数据包中包括了具体的加密算法和使用该加密算法对用户密码的HASH值进行加密处理后的衍生数据,如果加密算法弱且用户密码简单,攻击者完全可以基于获取的多个 AS-REP 数据包,采用离线手段暴力破解获取用户的原始密钥,这种攻击方式被称为 ASREP-Roasting;
- KDC返回的正常的 AS-REP 数据包格式如下:
- KDC开启了某 principal的Pre-authentication后,基于加密时间戳算法 PA-ENC-TIMESTAMP(目前使用最多的 pre-authentication 算法就是该密时间戳算法),可以有效防止基于 AS-REQ的重放攻击和基于 AS-REP的 ASREP-Roasting:因为此时客户端发送的 AS-REQ 数据中的padata(pre-authentication data)部分包含了使用特定算法和用户密钥加密的当前时间戳,KDC 收到 AS-REQ数据包后会基于协商的特定算法(AS-REQ数据包中包含具体算法)和用户密钥(KDC中存储了用户密钥)对收到的数据进行解密已获得原始时间戳,如果解密后的原始时间戳有效且跟KDC的当前时间戳差异不大(默认5分钟),即可判定该 AS-REQ 不是重放攻击,即可正常进行处理并最终返回 AS-REP数据包;如果解密后的原始时间戳无效或跟KDC的当前时间戳差异过大(默认5分钟),则会返回错误 krb-error且具体的错误信息是Preauthentication failed,此时KDC日志如下:
May 11 10:17:03 uf30-1 krb5kdc[6377](info): preauth (encrypted_timestamp) verify failure: Preauthentication failed May 11 10:17:03 uf30-1 krb5kdc[6377](info): AS_REQ (1 etypes {17}) 192.168.71.70: PREAUTH_FAILED: dap2@CDH.COM for krbtgt/CDH.COM@CDH.COM, Preauthentication failed
- Preauthentication failed 对应的 AS-REP 数据包格式如下:
- 事实上,客户端并不知道服务端是否开启了针对某 principal 的 Pre-authentication也不知道具体的Pre-authentication加密算法,所以同一客户端的首个 AS-REQ 请求并不会包含 padata(pre-authentication data),其接受的首个 AS-REP 数据包也肯定是krb-error且具体错误信息是 ERR_PREAUTH_REQUIRED,同时该数据包会告诉客户端可以使用的加密算法,后续客户端就可以使用协商的加密算法计算 padata 进而生成并发送第二个 AS-REQ 请求,服务端KDC验证通过后就会正常响应 AS-REP 了,该流程完整示意图如下:
- 该流程完整服务端KDC日志如下:
May 11 11:07:09 uf30-1 krb5kdc[6377](info): AS_REQ (1 etypes {17}) 192.168.71.70: NEEDED_PREAUTH: dap2@CDH.COM for krbtgt/CDH.COM@CDH.COM, Additional pre-authentication required May 11 11:07:09 uf30-1 krb5kdc[6377](info): closing down fd 13 May 11 11:07:09 uf30-1 krb5kdc[6377](info): AS_REQ (1 etypes {17}) 192.168.71.70: ISSUE: authtime 1683774429, etypes {rep=17 tkt=17 ses=17}, dap2@CDH.COM for krbtgt/CDH.COM@CDH.COM May 11 11:07:09 uf30-1 krb5kdc[6377](info): closing down fd 13
- 首个不包含 padata的 AS-REQ数据包如下:
- 首个 ERR_PREAUTH_REQUIRED 对应的 AS-REP数据包如下:
- 第二个包含 padata的 AS-REQ数据包如下:
- 第二个正常的AS-REP 数据包格式如下:
- AS-REP roasting is an attack against Kerberos for user accounts that do not require pre-authentication, which means that if the target user has pre-authentication disabled, an attacker can request authentication data for it and get a TGT that can be brute-forced offline, similarly to Kerberoasting;
- Kerberos pre-authentication is an account protection against offline password cracking. When enabled, a user requesting access to a resource initiates communication with the Domain Controller (DC) by sending an Authentication Server Request (AS-REQ) message with a timestamp that is encrypted with the hash of their password. If and only if the DC is able to successfully decrypt the timestamp with the hash of the user’s password, it will then send an Authentication Server Response (AS-REP) message that contains the Ticket Granting Ticket (TGT) to the user. Part of the AS-REP message is signed with the user’s password