1. 前言
为什么要有Kerberos这样一个中央认证机制?
假设有A,B,C三个服务器,分别提供不同的服务,user要访问ABC都需要输入用户名密码,但是ABC没必要都存一份user的密码,所以就衍生出一个中央服务器D来专门存储用户名密码;如果user通过了D的认证,那就是合法的身份,就可以使用ABC任何一个服务,所以user需要告诉ABC它通过了D的认证。如何证明这个事情,以及信息在网络传输过程如何防止被截获篡改而假冒等等,解决这些问题就靠kerberos。
Kerberos是Windows域首选的一种认证协议,优于NTLM认证机制。虽然Kerberos认证机制较为复杂,但红队、渗透测试人员以及实际攻击者经常会用到该协议。理解Kerberos的工作原理非常重要,这样才能理解针对Kerberos的潜在攻击方式,澄清攻击者如何利用该协议攻击域环境。
2. 概述
Kerberos简单来说就是一个用于安全认证第三方协议,它采用了传统的共享密钥的方式,实现了在网络环境不一定保证安全的环境下,client和server之间的通信,适用于client/server模型,由MIT开发和实现。
Kerberos并不要求通信双方所在的网络环境是安全的,即使通信过程中数据被截取或者篡改依然不会影响它的正常工作,它提供的认证是双向的,不仅能保证Server不被错误的Client使用,同时也能保证Client不使用错误的Server。同时Kerberos又严重依赖于时间,时间戳也是Kerberos用来保证通信安全的重要手段,这个一般通过通信双方同时访问同一个时间服务器来实现。Kerberos也能达到单点登录的效果,即当Client通过了Kerberos server的认证后,便可以访问多个Real Server。
3. 原理
3.1. 名词解释
名词 | 解释 |
---|---|
DC(Domain Controller) | 域控制器,一台计算机实现用户、计算机的统一管理 |
KDC(key distribution center) | 是一个网络服务,提供ticket和临时会话密钥,是 Kerberos 的核心组件,主要由三个部分组成: - Kerberos Database: 包含了一个 Realm 中所有的 principal、密码与其他信息。(默认:Berkeley DB) - Authentication Service(AS): 进行用户信息认证,为客户端提供 Ticket Granting Tickets(TGT) - Ticket Granting Service(TGS): 验证 TGT 与 Authenticator,为客户端提供 Service Tickets |
AS(Authentication Server) | 认证服务器 |
TGS(Ticket Grantion Server) | 票据授权服务器 |
TGT(Ticket-Granting-Ticket) | 票据授予票据 |
TGS(Ticket-Granting Service) | 票据授予服务 |
principal | 大致可以认为是 Kerberos 世界的用户名,用于标识身份。principal 主要由三部分构成:primary,instance(可选) 和 realm。包含 instance 的principal,一般会作为server端的principal,如:NameNode,HiverServer2,Presto Coordinator等;不含有 instance 的principal,一般会作为客户端的principal,用于身份认证 |
realm name | 包含KDC和许多客户端的Kerberos网络,类似于域,俗称为领域;也是principal的一个“容器”或者“命名空间”。相对应的,principal的命名规则是”what_name_you_like@realm”。在kerberos,大家都约定俗成用大写来命名realm,比如“EXAMPLE.COM” |
password | 某个用户的密码,对应于kerberos中的master_key。password可以存在一个keytab文件中。所以kerberos中需要使用密码的场景都可以用一个keytab作为输入 |
keytab | keytab是包含principals和加密principal key的文件。keytab文件对于每个host是唯一的,因为key中包含hostname。keytab文件用于不需要人工交互和保存纯文本密码,实现到kerberos上验证一个主机上的principal。因为服务器上可以访问keytab文件即可以以principal的身份通过kerberos的认证,所以,keytab文件应该被妥善保存,应该只有少数的用户可以访问 |
credential | credential是“证明某个人确定是他自己/某一种行为的确可以发生”的凭据。在不同的使用场景下,credential的具体含义也略有不同:对于某个principal个体而言,他的credential就是他的password;在kerberos认证的环节中,credential就意味着各种各样的ticket |
authenticator | 验证者,是服务器用于验证客户机用户主体的信息。验证者包含用户的主体名称、时间标记和其他数据。与票证不同,验证者只能使用一次,通常在请求访问服务时使用 |
Ticket | 一个记录,客户用它来向服务器证明自己的身份,包括服务的主体名称、用户的主体名称、用户主机的ip地址、时间标记、会话密钥、定义票证生命周期的时间戳 |
3.2. 工作过程分析
Client从KDC获取TGT,Client利用获取的TGT向KDC请求其他Service的Ticket(通过获取的session进行访问)。
步骤详解:
1. 客户端与 Authentication Server,获得TGT
第一步,客户端通过kinit USERNAME或其他方式,将客户端ID, 目标HTTP服务ID, 网络地址(可能是多个机器的IP地址列表,如果想在任何机器上使用,则可能为空),以及TGT有效期的寿命等信息发送给 Authentication Server。
第二步,Authentication Server 将检查客户端ID是否在KDC数据库中。如果 Authentication Server 检查操作没有异常,那么KDC将随机生成一个 key,用于客户端与 Ticket Granting Server(TGS) 通信。这个Key,一般被称为 TGS Session Key。随后 Authentication Server 将发送两条信息给客户端:其中一条信息被称为TGT,由TGS的密钥加密,客户端无法解密,包含客户端ID, TGS Session Key等信息。另一条信息由客户端密钥加密,客户端可以正常解密,包含目标 HTTP 服务ID,TGS Session Key等信息。
第三步,客户端利用本地的密钥解密出第二条信息。如果本地密钥无法解密出信息,那么认证失败。
2. 客户端与 Ticket Granting Server,获得SGT
这时候,客户端有了 TGT(由于本地没有TGS的密钥,导致无法解密出其数据)与 TGS Session Key。
第四步,客户端将发送两条消息给TGS,一是“无脑”将 AS 发送过来的TGT(由TGS密钥加密)转发给TGS,二是将包含自身信息的Authenticator(由TGS Session Key加密)发送给TGS
第五步,TGS 将利用自身的密钥从TGT中解密出TGS Session Key,然后利用TGS Session Key从 Authenticator 中解密出客户端的信息。TGS 解密出所有信息后,将进行身份检查,进行认证:
- 将客户端ID与TGT的客户端ID进行比较
- 比较来自 Authenticator 的时间戳和TGT的时间戳 (典型的Kerberos系统的容忍度是2分钟,但也可以另行配置)
- 检查TGT是否过期
- 检查Authenticator是否已经在TGS的缓存中(为了避免重放攻击)
当所有检查都通过后, TGS 随机生成一个 Key 用于后续客户端与 HTTP 服务交互时进行通信加密使用,即 HTTP Session Key。同样地,TGS 将发送两条信息给客户端: 其中一条是 HTTP Ticket(SGT),由 HTTP 服务的密钥进行加密;另一条则由TGS Session Key加密,包含了客户端信息与时间戳。
第六步,客户端将利用TGS Session Key解密出其中一条信息,另一条信息由于是由目标HTTP服务加密,无法解密。
3. 客户端与 HTTP Server,获得服务
这时候,客户端有了HTTP Ticket(由于本地没有HTTP服务的密钥,导致无法解密出其数据)与 HTTP Session Key。
第七步,客户端将发送两条信息给HTTP服务:一是“无脑”将 AS 发送过来的 HTTP Ticket(由HTTP 密钥加密)转发给目标 http 服务。二是将包含自身信息的Authenticator(由HTTP Session Key加密)发送给 http 服务。
第八步,HTTP服务首先利用自身的密钥解密出 HTTP Ticket 的信息,得到 HTTP Session Key;随后,利用HTTP Session Key解密出用户的Authenticator信息。信息解密完成后,HTTP 服务同样需要做一些信息检查:
- 将 Authenticator 中的客户端ID与HTTP Ticket中的客户端ID进行比较
- 比较来自 Authenticator 的时间戳和 HTTP Ticket 的时间戳 (典型的 Kerberos 系统对差异的容忍度是 2 分钟,但也可以另行配置)
- 检查Ticket是否过期
- 检查 Authenticator 是否已经在HTTP服务器的缓存中(为了避免重播攻击)
至此,所有的认证过程通过,客户端即可与远程HTTP服务完成了身份认证,可以进行后续的信息通信。
4. 存在漏洞
4.1. Kerberoasting
当发送TGS时,KDC会使用时间戳+服务账户的密码哈希来加密TGS。由于目标服务通常为计算机控制的某个服务(比如HOST或者CIFS),因此这里会使用主机账户密码哈希。在某些情况下,用户账户也会被创建为“服务账户”,注册为SPN。由于KDC不负责服务的授权工作(该工作由服务自己负责),因此任何用户都可以请求任何服务的TGS。这意味着如果某个用户“服务账户”被注册为SPN,那么任何用户都可以请求该用户对应的TGS,而该TGS使用用户账户密码哈希加密,攻击者可以从票据中提取哈希,离线破解。
4.2. 黄金票据
当发送TGT时,该票据会使用KRBTGT的账户密码哈希来加密。KRBTGT的密码默认情况下不会被手动设置,因此与主机账户密码一样复杂。当攻击者成功获取KRBTGT密码,伪造TGT时,这种攻击技术称为黄金票据攻击。Mimikatz可以使用KRBTGT密码的RC4哈希来伪造任何用户的票据,并且该过程不需要知道用户密码。
4.3. 白银票据
黄金票据对应的是TGT伪造,而白银票据则是TGS伪造。攻击者使用黄金票据时会有安全上的考虑:攻击过程涉及KDC,KDC会发布一个TGT,因此防御方可能会收到警报,捕捉到黄金票据攻击。白银票据更为隐蔽,攻击过程不涉及到KDC。由于这里伪造的是服务票据,因为攻击者需要知道目标服务的密码哈希,而大多数情况下,该哈希对应的是主机账户的密码哈希。对于设置了SPN的服务账户,攻击者也可以针对该SPN生成白银票据。
举个例子,如果用户名MSSQLServiceAcct创建了一个服务账户,注册了MSSQLSVC主体,那么对应的SPN则为MSSQLSVC/MSSQLServiceAcct。如果攻击者获取了账户的密码哈希(通过Kerberoasting或者其他方法),就可以利用该哈希来伪造针对该SPN的TGS,访问对应的服务(这里为MSSQLSVC)。
对于某些服务(如CIFS),如果使用了用户账户来创建SPN(如CIFS/Alice),此时攻击者无法使用该用户的密码来构造CIFS对应的白银票据,这是因为用户并不控制该服务的访问权限,这是主机账户负责的工作。
白银票据存在的安全风险在于,如果设置了PAC验证功能,票据就会发送到KDC进行验证,此时攻击将以失败告终。
参考文章
https://zhuanlan.zhihu.com/p/266491528
https://www.anquanke.com/post/id/200680 (含委派攻击)
https://www.cnblogs.com/luxianghao/p/5269739.html
https://www.cnblogs.com/swordfall/p/12009716.html