Bootstrap

详解Kerberos中的preauth参数

一 介绍

Kerberos preauth(Kerberos 预认证)是 Kerberos 协议的一个重要特性。简单来说,它是 Kerberos V5 版本对 V4 版本在安全方面的增强,可抵御针对 Kerberos 协议的 AS-REP Roasting 攻击。在使用 Kerberos 协议时,涉及到多种请求和响应,这些数据包在网络传输过程中可能被截获。为防止网络嗅探问题,Kerberos 不会明文传输用户密钥,而是采用特定算法对用户密钥的哈希值(附加一些时间戳和 salt 数据)进行加密传输,接收端用相同算法和密钥哈希解密后验证数据有效性。虽然没有明文传输密钥,但 AS-REQ 数据包可被截获进行重放攻击,AS-REP 数据包被截获后,若加密算法弱且用户密码简单,攻击者可基于此进行离线暴力破解获取用户原始密钥,这种攻击方式即 AS-REP Roasting。

KDC 开启某 principal 的 Pre-authentication 后,基于加密时间戳算法 PA-ENC-TIMESTAMP(目前使用最多的预认证算法),能有效防止基于 AS-REQ 的重放攻击和基于 AS-REP 的 AS-REP Roasting。客户端发送的 AS-REQ 数据中的 padata(预认证数据)部分包含使用特定算法和用户密钥加密的当前时间戳,KDC 收到后基于协商的特定算法和用户密钥(KDC 中存储)进行解密获得原始时间戳。若解密后的原始时间戳有效且与 KDC 当前时间戳差异不大(默认 5 分钟),则判定该 AS-REQ 不是重放攻击,可正常处理并返回 AS-REP 数据包;若原始时间戳无效或差异过大,则返回错误 krb-error,具体错误信息是 Preauthentication failed。


客户端不知道服务端是否开启预认证及具体加密算法,所以同一客户端的首个 AS-REQ 请求通常不包含 padata,其收到的首个 AS-REP 数据包肯定是 krb-error 且具体错误信息是 ERR_PREAUTH_REQUIRED,同时该数据包会告知客户端可用的加密算法,后续客户端可使用协商的加密算法计算 padata 并生成发送第二个 AS-REQ 请求,服务端 KDC 验证通过后就会正常响应 AS-REP。

官方文档:KDC preauthentication interface (kdcpreauth) — MIT Kerberos Documentation

二 影响

预认证是一种额外的安全措施,用于增强认证的安全性。通过要求客户端进行预认证,可以确保客户端的身份更加可靠。而服务端要求客户端具有带有预认证位的TGT,也是为了增加服务访问的安全性,确保只有经过适当预认证的客户端才能获得服务票证并访问相应的服务。这种机制有助于防止未经授权的访问,并提高Kerberos认证系统的整体安全性。具体的实现和配置可能会涉及到Kerberos服务器的相关设置(例如kdc.conf文件)以及客户端和服务端的应用程序配置。

由此可知,如果需要开启该属性,服务端和客户端使用的principal都需要开启该参数。如果服务端配置了但是客户端没有配置,客户端会有证相关的报错。

例如,当使用了一个keytab进行认证后通过hdfs客户端访问hdfs,发现有如下报错。

报错明显地是指向了kerberos认证相关,但是很明确的是 在访问前有进行kinit认证,并且如果不进行认证报错应如下所示

为了进一步追究问题原因,可以为hadoop配置kerberos相关的详细日志

export HADOOP_OPTS="-Dsun.security.krb5.debug=true

从详细的日志可以看出,首先keytab认证没有问题,因为客户端已经拿到了ticket去向服务端请求。问题出在了和服务端的交互过程中,同时日志中打印出了认证使用的客户端和服务端使用的principal,结合下面No preauth的报错,怀疑应该是preauth的问题,那就去看一看这两个principal具体的信息

果然,客户端使用的principal是没有preauth的,而服务使用的principal中是包含Attributes: REQUIRES_PRE_AUTH,那么根据kerberos官方的说法,是不支持的。解决方法,自然就是为客户端的principal增加preauth属性。

三 配置

根据上面的问题排查,可以知道preauth这个参数对principal自身向kdc认证不会产生影响,但对向开启了kerberos认证的服务发起请求会产生影响,那么需要知道在哪里可以配置、如何配置该参数

kdc端默认配置

在kdc.conf文件中的default_principal_flags参数可以配置是否默认开启preauth

解释

# 开启 default_principal_flags = +preauth # 关闭 default_principal_flags = -preauth # 参考https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/kdc_conf.html?highlight=default_principal_flags

如下图所示,在kdc.conf文件中指定了default_principal_flags指定配置+preauth,新建principal时不指定相关参数,建出来的princpal是默认带preauth

如下图所示,在kdc.conf文件中指定了default_principal_flags指定配置-preauth,新建principal时不指定相关参数,建出来的princpal是默认不带preauth

新增principal时手动配置

如下图所示,在addprinc时可以通过+/-requires_preauth来控制是否给principal设置preauth属性

四 进一步了解

可以通过对kinit过程的打印,进一步加深对preauth参数的理解。

下面两张图分别是加了preauth和没加preauth的principal认证过程:

直观的感受是,带preauth参数的principal认证过程更长,详细对比看,多的便是preauth的过程,对应了官方文档中的

If this flag is enabled on a client principal, then that principal is required to preauthenticate to the KDC before receiving any tickets.

;