Kerberos协议分析

近日给公司搭建KDC认证服务,简单总结了一下Kerberos协议,便于理解。个人习惯,把一个东西条理清晰地表述出来,更容易掌握。

一、背景

分布式环境下,传统端到端加密框架的局限性:

  1. 各节点两两之间需要互相持有密钥
  2. 密钥长期不更新,一旦密钥被解出就相当于明文通信
  3. 更新密钥需要走网络交换,有泄露密钥的风险
  4. 更新信任关系需要更新所有节点
  5. 认证消息包可能被截获

使用Kerberos协议的好处:

  1. 可以实现范围内的节点互信
  2. 更新密钥不通过网络交换
  3. 各节点之间的信任关系基于节点与KDC共享各自的密钥
  4. 各节点可以缓存通用票据,在票据失效之前可用于访问其他节点(单点登录)
  5. 认证消息带时间戳,避免被伪造

Kerberos协议的局限性:

  1. 各节点与KDC之间需要相对同步的时间(最大时间相位差的默认值为5分钟)

二、协议分析

认证过程示意图

网络数据包内容

KDC保障以下场景的节点互信:

  1. 客户端和服务端之间互信(例如hbase/hdfs的客户端和服务端)
  2. 服务端节点之间互信(hbase/hdfs的服务端节点)

本文将互信定义为使用同一份密钥来通信。这里将通信请求方定义为client,被请求方定义为server。client定期从KDC请求到一份新的密钥,发往server,server确认密钥可信之后使用这份密钥与client通信。

获取TGT和TGS Session Key

Client明文[1] 给KDC的Authentication Server(简称AS)发送自己的用户名(Client’s principal)、时间戳、申请ticket时长

AS Reply用Client和KDC共享的密钥(紫色,保障返回给真的Client)加密,内容包含:

  1. Client和TGS通信用的TGS Session Key(黄色)
  2. ticket有效期
  3. TGT(使用KDC的krbtgt Key(红色)密钥加密,Client不可解,包含Client信息与TGS Session Key(黄色),保障AS和TGS同属于一个KDC集群,可以是不同机器)

这里TGT的意义是AS给Client和TGS分发的临时Ticket,假的Client无法解开来修改里面的Client信息,假的TGS没有krbtgt Key也无法解密TGT。只有真正的Client和TGS可以用TGS Session Key加密通信内容。

获取TGS和Service Session Key

Client将自己的信息和需要访问的服务、连同TGT一起打包发送给KDC的Ticket Granting Server(简称TGS),数据包内容为:

  1. Client用户名和时间戳(用TGS Session Key加密,保障Client是真的)
  2. Client想访问的服务名(service’s principal)
  3. 请求的ticket有效期
  4. TGT(KDC的krbtgt(红色)密钥加密,保障Client是真的)

TGS Reply用TGS Session Key(黄色)加密,内容如下:

  1. 服务名(service’s principal)
  2. Client和Server通信用的Service Session Key(粉色)
  3. Service Ticket有效期
  4. TGS(即Service Ticket,Client不可解,包含Client信息与Service Session Key,保障返回给真的Client)

使用Service Ticket与Server请求认证

Client用Service Session Key加密Client用户名和时间戳,把它和TGS一起打包发往想要访问的Server,包内容为:

Server先解开TGS,检查Client是否有权限,如果未授权可以直接拒绝访问。否则用TGS里的Service Session Key加密服务名和时间戳返回给Client

Client收到AP Reply,解出服务名,验证是自己想要访问的服务,互信完成。在有效期内使用Service Session Key加密通信内容

注意KDC只是完成了身份认证和密钥分发,不包含ACL和通信内容加密。完整的加密传输还要依赖SASL、GSSAPI、SPNEGO等其他框架

抓包分析

以Wireshark抓的一些数据包为例,来看两次KDC请求的实际内容

蓝色部分是Wireshark尝试用我提供的包含Client、Server密钥的Keytab解出来的内容
可以看到黄色部分的TGT的密钥由KDC保管,无法解密
蓝色部分,TGS Session Key是Client可读,Service Ticket是Server可读。Service Session Key两者都可读

AS_REQ

AS_REP

TGS_REQ

TGS_REP

可以看到,数据包内容和上面官方介绍基本一致

注意事项

根据如果明文,攻击者可以伪造AS_REQ,拿到TGT进行离线破解获取用户密钥。为了防止AS_REQ攻击,建议打开预认证,详情见 Kerberos概述及常见攻击场景

参考资料
  1. MIT Kerberos官网
  2. Introduction to SPNEGO/Kerberos Authentication in Spring