这篇文章以由浅入深、层层深入的方式讲述基于Kerberos的Windows Network Authentication,希望这篇文章能帮助那些对Kerberos不明就里的人带来一丝帮助。对于一些不对的地方,欢迎大家批评指正。
1 术语
KDC
全称:key distributed center
作用:整个安全认证过程的票据生成管理服务,其中包含两个服务,AS和TGS
AS
全称:authentication service
作用:为client生成TGT的服务
TGS
全称:ticket granting service
作用:为client生成某个服务的ticket
AD
全称:account database
作用:存储所有client的白名单,只有存在于白名单的client才能顺利申请到TGT
TGT
全称:ticket-granting ticket
作用:用于获取ticket的票据
client
想访问某个server的客户端
server
提供某种业务的服务
session key (SK)
用户和域控通信的加密密钥
logon session key -- PreMarsterKey
用于保护通信密钥的密钥
MasterKey
MasterKey包含两个一个是用户的记为MK_Client,一个是KDC的MK_kdc,生成方式是口令的散列值。
2 kerberos的背景
相比kerberos,https可能更为熟悉一点,通过证书和非对称加密的方式,让客户端可以安全的访问服务端,但这仅仅是客户端安全,通过校验,客户端可以保证服务端是安全可靠的,而服务端却无法得知客户端是不是安全可靠的。这也是互联网的一种特性。而kerberos可以支持双向认证,就是说,可以保证客户端访问的服务端是安全可靠的,服务端回复的客户端也是安全可靠的。
想证明client和server都是可靠的,必然要引入第三方公证平台,这里就是AS和TGS两个服务。
- client向kerberos服务请求,希望获取访问server的权限。kerberos得到了这个消息,首先得判断client是否是可信赖的,也就是白名单黑名单的说法。这就是AS服务完成的工作,通过在AD中存储黑名单和白名单来区分client。成功后,返回AS返回TGT给client。
- client得到了TGT后,继续向kerberos请求,希望获取访问server的权限。kerberos又得到了这个消息,这时候通过client消息中的TGT,判断出了client拥有了这个权限,给了client访问server的权限ticket。
- client得到ticket后,终于可以成功访问server。这个ticket只是针对这个server,其他server需要像TGS申请。
图1展示了kerberos的认证流程,总体分为3步。
- client与AS交互
- client与TGS交互
- client与server交互
通过这3步,一次请求就完成了。当然这里会有个问题,这样也没比https快啊。解释一下
- 整个过程TGT的获取只需要一次,其中有超时的概念,时间范围内TGT都是有效的,也就是说一般情况访问server只需要直接拿到ticket即可
- 整个过程采用的是对称加密,相对于非对称加密会有性能上的优势
- kerberos的用户管理很方便,只需要更新AD中的名单即可
3 基本原理
3.1 Long-term Key/Master Key 主密钥
在Security的领域中,有的Key可能长期内保持不变,比如你在密码,可能几年都不曾改变,这样的Key、以及由此派生的Key被称为Long-term Key。对于Long-term Key的使用有这样的原则:被Long-term Key加密的数据不应该在网络上传输。原因很简单,一旦这些被Long-term Key加密的数据包被恶意的网络监听者截获,在原则上,只要有充足的时间,他是可以通过计算获得你用于加密的Long-term Key的——任何加密算法都不可能做到绝对保密。
在一般情况下,对于一个用于来说,口令往往仅仅限于该用户知晓,甚至对于任何Domain的Administrator,口令仍然应该是保密的。但是口令却又是证明身份的凭据,所以必须通过基于你口令的派生的信息来证明用户的真实身份,在这种情况下,一般将你的密码进行Hash运算得到一个Hash code, 我们一般管这样的Hash Code叫做Master Key。由于Hash Algorithm是不可逆的,同时保证密码和Master Key是一一对应的,这样既保证了你密码的保密性,有同时保证你的Master Key和密码本身在证明你身份的时候具有相同的效力。
3.2 Short-term Key/Session Key 会话密钥
由于被Long-term Key加密的数据包不能用于网络传送,所以我们使用另一种Short-term Key来加密需要进行网络传输的数据。由于这种Key只在一段时间内有效,即使被加密的数据包被黑客截获,等他把Key计算出来的时候,这个Key早就已经过期了
3.3 基本原理
Kerberos Authentication的基本原理:客户端和KDC有自己主密钥,通过第一阶段AS形成PreMaskerKey,用于和TGS进行通信,第二阶段通过PreMasterKey协商生成SK。第三阶段通过SK,与AD进行通信。顺便说一下,Kerberos起源于希腊神话,是一支守护着冥界长着3个头颅的神犬,在keberos Authentication中,Kerberos的3个头颅代表中认证过程中涉及的3方:AS、TGS和AD。也代表三个阶段
对于一个Windows Domain来说,Domain Controller扮演着KDC的角色。KDC维护着一个存储着该Domain中所有帐户的Account Database(一般地,这个Account Database由AD来维护),也就是说,他知道属于每个Account的名称和派生于该Account Password的Master Key。而用于Client和Server相互认证的SK就是有KDC分发。下面我们来看看KDC分发SK的过程。
4 kerberos过程
Kerberos整个认证过程通过3个sub-protocol来完成。这个3个Sub-Protocol分别完成上面列出的3个子过程。这3个sub-protocol分别为:
- Authentication Service Exchange
- Ticket Granting Service Exchange
- Client/Server Exchange
4.1 Authentication Service Exchange
目标是生成logon session key我们称之为PreMasterKey,和PreMasterKey票据TGT。
通过这个Sub-protocol,KDC(确切地说是KDC中的Authentication Service)实现对Client身份的确认,并颁发给该Client一个TGT。具体过程如下:
Client向KDC的Authentication Service发送Authentication Service Request(KRB_AS_REQ), 为了确保KRB_AS_REQ仅限于自己和KDC知道,Client使用自己的Master Key对KRB_AS_REQ的主体部分进行加密(KDC可以通过Domain 的Account Database获得该Client的Master Key)。KRB_AS_REQ的大体包含以下的内容:
- Pre-authentication data:包含用以证明自己身份的信息。说白了,就是证明自己知道自己声称的那个account的Password。一般地,它的内容是一个被Client的Master key加密过的Timestamp。
- Client name & realm: 简单地说就是Domain name\Client
- TGS Server Name:是KDC的Ticket Granting Service的Server Name。
AS(Authentication Service)通过它接收到的KRB_AS_REQ验证发送方的是否是在Client name & realm中声称的那个人,也就是说要验证发送放是否知道Client的Password。所以AS只需从Account Database中提取Client对应的Master Key对Pre-authentication data进行解密,如果是一个合法的Timestamp,则可以证明发送放提供的是正确无误的密码。验证通过之后,AS将一份Authentication Service Response(KRB_AS_REP)发送给Client。KRB_AS_REQ主要包含两个部分:本Client的Master Key加密过的PreMasterKey(Logon Session Key)和被自己(MK_KDC)加密的TGT,这个票据又称黄金票据。而黄金票据TGT大体又包含以下的内容:
- PreMasterKey:Logon Session Key
- Client name & realm: 简单地说就是Domain name\Client
- End time: TGT到期的时间。
Client通过自己的Master Key对第一部分解密获得PreMasterKey(Logon Session Key)之后,携带着TGT便可以进入下一步:TGS(Ticket Granting Service)Exchange。Client看不了TGT内容,因为被KDC的主密钥加密。
4.2 TGS(Ticket Granting Service)Exchange
TGS(Ticket Granting Service)Exchange通过Client向KDC中的TGS(Ticket Granting Service)发送Ticket Granting Service Request(KRB_TGS_REQ)开始。KRB_TGS_REQ大体包含以下的内容:
- TGT:Client通过AS Exchange获得的Ticket Granting Ticket,TGT被KDC的Master Key进行加密。
- Authenticator:用以证明当初TGT的拥有者是否就是自己,所以它必须以TGT的办法方和自己的PreMasterKey(Logon Session Key)来进行加密。
- Client name & realm: 简单地说就是Domain name\Client。
- Server name & realm: 简单地说就是Domain name\Server,这回是Client试图访问的那个Server。
TGS收到KRB_TGS_REQ在发给Client真正的Ticket之前,先得整个Client提供的那个TGT是否是AS颁发给它的。于是它不得不通过Client提供的Authenticator来证明。但是Authentication是通过PreMasterKey(Logon Session Key)进行加密的,而自己并没有保存这个Session Key。所以TGS先得通过自己的Master Key对Client提供的TGT进行解密,从而获得这个PreMasterKey(Logon Session Key),再通过这个PreMasterKey(Logon Session Key)解密Authenticator进行验证。验证通过后向对方发送Ticket Granting Service Response(KRB_TGS_REP)。这个KRB_TGS_REP有两部分组成:使用PreMasterKey(Logon Session Key)加密过用于Client和Server的Session Key和使用Server的Master Key进行加密的Ticket,这个票据又称白银票据。该白银票据Ticket大体包含以下一些内容:
- Session Key:通信密钥。
- Client name & realm: 简单地说就是Domain name\Client。
- End time: Ticket的到期时间。
Client收到KRB_TGS_REP,使用PreMasterKey解密第一部分后获得Session Key(SServer-Client)。有了Session Key和Ticket,Client就可以之间和Server进行交互,而无须在通过KDC作中间人了。所以我们说Kerberos是一种高效的认证方式,它可以直接通过Client和Server双方来完成,不像Windows NT 4下的NTLM认证方式,每次认证都要通过一个双方信任的第3方来完成。
我们现在来看看 Client如果使用Ticket和Server怎样进行交互的,这个阶段通过我们的第3个Sub-protocol来完成:CS(Client/Server )Exchange。
4.3 CS(Client/Server )Exchange
这个已经在本文的第二节中已经介绍过,对于重复发内容就不再累赘了。Client通过TGS Exchange获得Client和Server的Session Key,随后创建用于证明自己就是Ticket的真正所有者的Authenticator,并使用Session Key进行加密。最后将这个被加密过的Authenticator和Ticket作为Application Service Request(KRB_AP_REQ)发送给Server。除了上述两项内容之外,KRB_AP_REQ还包含一个Flag用于表示Client是否需要进行双向验证(Mutual Authentication)。
Server接收到KRB_AP_REQ之后,通过自己的Master Key解密Ticket,从而获得Session Key(SServer-Client)。通过Session Key(SServer-Client)解密Authenticator,进而验证对方的身份。验证成功,让Client访问需要访问的资源,否则直接拒绝对方的请求。
对于需要进行双向验证,Server从Authenticator提取Timestamp,使用Session Key进行加密,并将其发送给Client用于Client验证Server的身份。
4.4 Kerberos协议的小结
- 密钥有三类四个,主密钥分客户端和服务器,预主密钥和通信密钥。
- 客户端两次申请临时密钥
客户端最初只有自己的MK_Client,通过向AS获取了PreMasterKey,然后向TSG获取了CK,因此最后,客户端有三个密钥。我们分别称为客户端主密钥,预主密钥和通信密钥。客户端不产生中间密钥,只做中间密钥的搬运工,还帮助TSG和AP传递票据。 - 服务器产生2个临时密钥
由于客户端太多了,服务器不存每个客户端的临时密钥,预主密钥和通信生成后给客户端一份,用自己的主密钥打包一份,已被将来使用。服务器最开始掌握两个主密钥客户端和服务器主密钥,用户KRB_AS_REQ后生成PreMasterKey,用户KRB_TGS_REQ后生成CK。
4 TGT是服务器主密钥的密文
用途是,服务器只管产生,不存储临时密钥,因此每次用主密钥打包,放到接下来的通信中(往返都需要)。客户端只知道是服务器给的票据,并不能解开内容,只有服务器能看(不看不行,里面有密钥),因为密钥使用的是服务器主密钥。
4.5 微软对kerberros的改造
在 Kerberos 最初设计的几个流程里说明了如何证明 Client 是 Client 而不是由其他人来冒充的,但并没有声明 Client 有没有访问 Server 服务的权限,因为在域中不同权限的用户能够访问的资源是有区别的。
所以微软为了解决这个问题在实现 Kerberos 时加入了 PAC 的概念,PAC 的全称是 Privilege Attribute Certificate(特权属性证书)。可以理解为火车有一等座,也有二等座,而 PAC 就是为了区别不同权限的一种方式
4.5.1.PAC 的实现
当用户与 KDC 之间完成了认证过程之后,Client 需要访问 Server 所提供的某项服务时,Server 为了判断用户是否具有合法的权限需要将 Client 的 User SID 等信息传递给 KDC,KDC 通过 SID 判断用户的用户组信息,用户权限等,进而将结果返回给 Server,Server 再将此信息与用户所索取的资源的 ACL 进行比较,最后决定是否给用户提供相应的服务。
PAC 会在 KRB_AS_REP 中 AS 放在 TGT 里加密发送给 Client,然后由 Client 转发给 TGS 来验证 Client 所请求的服务。
在 PAC 中包含有两个数字签名 PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM,这两个数字签名分别由 Server 端主密钥和预主密钥加密。
同时 TGS 解密之后验证签名是否正确,然后再重新构造新的 PAC 放在 ST 里返回给客户端,客户端将 ST 发送给服务端进行验证。
4.5.2 Server 与 KDC
PAC 可以理解为一串校验信息,为了防止被伪造和串改,原则上是存放在 TGT 里,并且 TGT 由 服务器主密钥加密。同时尾部会有两个数字签名,分别由 服务器主密钥和 server 密码加密,防止数字签名内容被篡改。
同时 PAC 指定了固定的 User SID 和 Groups ID,还有其他一些时间等信息,Server 的程序收到 ST 之后解密得到 PAC 会将 PAC 的数字签名发送给 KDC,KDC 再进行校验然后将结果已 RPC 返回码的形式返回给 Server。