[ffffffff0x] Windows认证原理:Kerberos认证

2021-01-11 10:10:20 浏览数 (1)

前言

在之前的文章中,我们介绍了windows域环境的结构和组成部分。本文,我们将介绍域环境中使用的kerberos认证协议,并着手分析认证过程。


Kerberos

Kerberos 协议

Kerberos 是一种计算机网络授权协议,用来在非安全网络中,对个人通信以安全的手段进行身份认证。软件设计上采用客户端/服务器结构,并且能够进行相互认证,即客户端和服务器端均可对对方进行身份认证。可以用于防止窃听、防止重放攻击、保护数据完整性等场合,是一种应用对称密钥体制进行密钥管理的系统。支持 SSO、Kerberos 的扩展产品也使用公开密钥加密方法进行认证。

当有 N 个人使用该系统时,为确保在任意两个人之间进行秘密对话,系统至少保存有它与每个人的共享密钥,所需的最少会话密钥数为 N 个。

Kerberos 协议基于对称密码学,需要一个值得信赖的第三方。Kerberos 协议的扩展可以为认证的某些阶段提供公钥密码学支持。

Kerberos 认证所参与的角色

  • 访问服务的 Client
  • 提供服务的 Server
  • KDC(Key Distribution Center,密钥分发中心) = DC(Domain Controller)

其中 KDC 服务默认安装在一个域的域控中,而 Client 和 Server 为域内的用户或者是服务,如 HTTP 服务、SQL 服务。在 Kerberos 中 Client 是否有权限访问 Server 端的服务由 KDC 发放的票据来决定。

接下来,我们大致概括一下Kerberos的认证过程。


简要概括认证过程

Kerberos 认证用于域环境中,它是一种基于票据(Ticket)的认证方式。该认证过程的实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求网络上所有主机的物理安全,并假定网络上传送的数据包可以被任意地读取、修改和插入数据。在以上情况下, Kerberos 作为一种可信任的第三方认证服务,是通过传统的密码技术(如:共享密钥)执行认证服务的。

客户端要访问服务器的资源,首先需要购买服务端认可的 ST 服务票据。也就是说,客户端在访问服务器之前需要预先买好票,等待服务验票之后才能入场。但是这张票不能直接购买,需要一张 TGT 认购权证(Ticket Granting Ticket)。也就是说,客户端在买票之前必须先获得一张 TGT 认购权证。这张 TGT 认购权证和 ST 服务票据均由 KDC 发售。

他的整个认证过程涉及到三方:客户端、服务端和 KDC(Key Distribution Center)。在 Windows 域环境中,由 DC(域控)来作为 KDC。

Kerberos 认证过程如下:

  1. client 向 kerberos 服务请求,希望获取访问 server 的权限。 kerberos 得到了这个消息,首先得判断 client 是否是可信赖的,也就是白名单黑名单的说法。这就是 AS 服务完成的工作,通过在 AD 中存储黑名单和白名单来区分 client。成功后,返回 AS 返回 TGT 给 client。
  2. client 得到了 TGT 后,继续向 kerberos 请求,希望获取访问 server 的权限。kerberos 又得到了这个消息,这时候通过 client 消息中的 TGT,判断出了 client 拥有了这个权限,给了 client 访问 server 的权限 ticket。
  3. client 得到 ticket 后,终于可以成功访问 server。这个 ticket 只是针对这个 server,其他 server 需要向 TGS 申请。

获得认购权证

首先,我们来看看客户端如何获得 TGT 认购权证。TGT 是 KDC 的 KAS 认证服务(Kerberos Authentication Service)发放的。

  1. 当某个用户通过输入域账号和密码试图登录某台主机的时候,本机的 Kerberos 服务会向 KDC 的 KAS 认证服务发送一个认证请求。该请求主要包括两部分内容,明文形式的用户名和用户秘钥加密原始 Authenticator 后得到的加密后 Authenticator(Authenticator 是客户端和服务端可以用于验证对方身份的一个东西)。
  2. 当 KDC 接收到请求之后,通过 AD 查询该用户名得到该用户的信息。通过查询得到的密码信息对 Authenticator 进行解密得到原始的 Authenticator。如果解密后的 Authenticator 和已知的 Authenticator 一致,则证明请求者提供的密码正确,即确定了登录者的真实身份。KAS 成功认证对方的身份之后,会生成一个用户密码加密后的用于确保该用户和 KDC 之间通信安全的 Logon Session Key 会话秘钥。KAS 接着为该用户创建 TGT 认购权证TGT 主要包含两方面的内容:用户相关信息和原始 Logon Session Key,而整个 TGT 则通过 KDC 自己的密钥进行加密。最终,被不同密钥加密的 Logon Session KeyTGT 返回给客户端。

获得 ST 服务票据

经过上面的步骤,客户端获取了进入同域中其他主机入场券的 TGT 认购权证和 Logon Session Key,然后用自己的密钥解密 Logon Session Key 得到原始的 Logon Session Key。然后它会在本地缓存此 TGT 和原始 Logon Session Key。如果现在它需要访问某台服务器的资源,它就需要凭借这张 TGT 认购凭证向 KDC 购买相应的入场券。这里的入场券也有一个专有的名称——ST 服务票据(Service Ticket)。具体来说,ST 是通过 KDC 的另一个服务 TGS(Ticket Granting Service)出售的。

  1. 客户端先向 TGS 发送一个 ST 购买请求,该请求主要包含如下的内容:客户端用户名、通过 Logon Session Key 加密的 AuthenticatorTGT 和访问的服务器名(其实是服务)。
  2. TGS 接收到请求之后,通过自己的秘钥解密 TGT 并得到原始 Logon Session Key,然后通过 Logon Session Key 解密 Authenticator,进而验证对方的真实身份。TGS 完成对客户端的认证之后,会生成一个用 Logon Session Key 加密后的用于确保客户端-服务器之间通信安全的 Service Session Key 会话秘钥。然后为该客户端生成 ST 服务票据ST 服务票据主要包含两方面的内容:客户端用户信息和原始 Service Session Key,整个 ST 通过服务器密码派生的秘钥进行加密。最终两个被加密的 Service Session KeyST 回复给客户端。

用 ST 服务票据双向认证

  1. 客户端接收到 TGS 回复后,通过缓存的 Logon Session Key 解密得到原始 Service Session Key,同时它也得到了进入服务器 ST 服务票据。该 Serivce Session KeyST 服务票据 会被客户端缓存。客户端访问某服务器资源,将 ST 服务票据Service Session Key 加密的 Authenticator 发送给服务端。
  2. 服务器收到客户端发来的 ST 服务票据。但是,服务端如何确保客户端发来的 ST 服务票据 是通过 TGS 购买,而不是自己伪造的呢?这很好办,不要忘了 ST 是通过服务器自己密码派生的秘钥进行加密的。具体的操作过程是这样的,服务器在接收到请求之后,先通过自己密码派生的秘钥解密 ST,并从中提取 Service Session Key。然后通过提取出来的 Service Session Key 解密 Authenticator,进而验证了客户端的真实身份。实际上,到目前为止,服务端已经完成了对客户端的验证,但是,整个认证过程还没有结束。谈到认证,很多人都认为只是服务器对客户端的认证,实际上在大部分场合,我们需要的是双向验证(Mutual Authentication),即访问者和被访问者互相验证对方的身份。现在服务器已经可以确保客户端是它所声称的那么用户,客户端还没有确认它所访问的不是一个钓鱼服务呢。为了解决客户端对服务器的验证,服务端需要将解密后的 Authenticator 再次用 Service Session Key 进行加密,并发挥给客户端。客户端再用缓存的 Service Session Key 进行解密,如果和之前的内容完全一样,则可以证明自己正在访问的服务器和自己拥有相同的 Service Session Key。双向认证过后,开始了服务资源的访问。

接下来,通过详细的交互过程描述kerberos的认证原理。


详细概括认证过程

当 Client 想要访问 Server 上的某个服务时,需要先向 AS 证明自己的身份,然后通过 AS 发放的 TGT 向 Server 发起认证请求,这个过程分为三块:

  • The Authentication Service Exchange: Client 与 AS 的交互
    • AS_REQ
    • AS_REP
  • The Ticket-Granting Service (TGS) Exchange: Client 与 TGS 的交互
    • TGS_REQ
    • TGS_REP
  • The Client/Server Authentication Exchange: Client 与 Server 的交互
    • AP_REQ
    • AP_REP

整体过程如图

用户登录

用户登录阶段,通常由用户(AA)输入用户名信息,在客户端侧,用户输入的密码信息被一个单向 Hash 函数生成 Client 密钥,即 AA 的 NTLM Hash:

请求身份认证

客户端向 AS 发送请求认证

KRB-AS-REQ:Client 发送明文 用户名 AAAuthenticator1 信息到 KDC (Key Distribution Center)。Authenticator1 的内容为使用 Client 密码哈希加密的时间戳、Client ID、网络类型、加密类型等。

AS 确认客户端登陆者身份

KRB-AS-REP:AS 收到用户认证请求后,AS 根据请求中的 用户名 AA 信息,从数据库中查找用户名是否存在。如果 用户名 AA 存在,则从 KDC 中可以获取 用户 AA 的密码,使用单向函数为该密码生成一个 Client 密钥(即NTLM Hash)。

AS 生成随机字符串 Client/TGS Session Key,使用 Client 密钥(用户 AA 的密码 NTLM Hash)对 Client/TGS Session Key 加密得到 sessionkey_as

再使用 TGS 密钥(krbtgt 用户的 NTLM Hash)对 Client/TGS Session KeyClient InfoTimestamp 加密,得到 TGT(TGT票据)。

sessionkey_asTGT 一起返回给 Client。

Client 收到 AS 的响应消息后,利用自身的 Client 密钥(AA 的 NTLM Hash)对 sessionkey_as 解密,这样就获取到 Client/TGS Session Key

  • AS 的响应消息中有一条是属于 Client 的,有一条是 TGS 的。
  • TGT 的到期时间为 8 小时,如果超过了 8 小时,还需要重新申请 TGT,不能之间进入下一步获取 Ticket。
  • KDC 返回的 TGT 客户端是无法解密的,因为它没有 KDC Hash,如果有,我们就可以伪造黄金票据

请求授权访问服务

客户端向 TGS 发送请求服务授权请求

KRB-TGS-REQ:Client 收到 sessionkey_asTGT 后,使用 Client 密钥(AA 的 NTLM Hash)对 sessionkey_as 解密就能得到 Client/TGS Session Key,然后使用 Client/TGS Session Key 对 Client Info 和 timestamp 加密得到 Authenticator2

Authenticator2TGTService ID(要请求的服务 ID)发送给 KDC 中的 TGS。

  • 由于 TGT 是使用 TGS 密钥(krbtgt 的 NTLM Hash)加密的,Client 无法对 TGT 解密。
  • 如果假设这个数据被中间人窃取到,也无法在短时间内破解,因为 KDC 会校验时间戳。

TGS 为 Client 响应服务授权票据

TGS-REP:TGS 收到请求后,检查 KDC 数据库中是否存在所请求的服务(Service ID)。如果存在,TGS 使用 TGS 密钥(krbtgt 的 NTLM Hash)解密 TGT,得到 Client/TGS Session Key、timestamp、Client info;同时使用从 TGT 中解密得到的 Client/TGS Session Key 去解密 Authenticator2,得到 Client info 和 timestamp。 比对 Authenticator2TGT 的解密内容以验证通过。

  • TGS 比对 Authenticator2 包含的 Client IDTGT 中的 Client ID
  • 比较时间戳(误差范围在2分钟)
  • 通过生命周期字段检查 TGT 是否过期
  • 检查 Authenticator2 已经不再 TGS 的缓存中
  • 若原始请求中的网络地址不为 NULL,比较 TGT 中的 IP 和请求的 IP

验证成功后,随机生成 Client 所请求服务的会话密钥 Client/Server Session Key

使用 Server 密钥(即服务器计算机的NTLM Hash)对 Client/Server Session KeyClient Info(包含 Client ID)、TimeStamp 加密得到 Client-To-Server Ticket(也称为 ST 票据);

使用 Client/TGS Session KeyClient/Server Session Key 加密得到 sessionkey_tgs

最终将 Client-To-Server Ticketsessionkey_tgs 返回给 Client。

请求服务

Client 向 SS(Service Server)发送服务请求

AP-REQ:Client 收到 Client-To-Server Ticketsessionkey_tgs 之后,使用 Client/TGS Session Keysessionkey_tgs 解密得到 Client/Server Session Key,然后使用 Client/Server Session Key 对 Client Info 和 timestamp 加密得到 Authenticator3

Authenticator3Client-To-Server Ticket 发送给所请求服务的服务器(Service Server)。

Service Server 响应 Client

AP-REP:Service Server 收到客户端的服务访问请求之后,利用 Server 密钥(Server 的 ntlm Hash)对 Client-To-Server Ticket 解密,提取出 Client/Server SessionKey、Client ID 等信息。

Service Server 使用 Client/Server SessionKeyAuthenticator3 解密得到 Client ID 和 TimeStamp。

Service Server 发送最后的验证消息——用 Client/Server SessionKey 加密的 Timestamp 和 Service ID 数据包给 Client。

Client 收到之后,使用缓存的 Client/Server SessionKey 解密提取 Timestamp 信息,然后确认该信息与 Client 发送的 Authenticator3 中的 Timestamp 信息是否一致。验证通过后,在定义的通讯周期内,Client 可以使用票据请求 Service。

由此完成了 Client 和 Service Server 的双向认证。


总结

本文介绍了域环境中使用的Kerberos认证协议,通过解剖每一步认证的过程来介绍认证原理。在实际应用中,Kerberos不仅用于windows域的环境,linux机器也可以配置进行认证,但关键的流程是一致的。


本文作者 r0fus0d

0 人点赞