Kerberos介绍
Kerberos是一种计算机网络授权(身份验证)协议,旨在通过秘钥加密技术为客户端/服务器应用程序提供身份验证,用来在非安全网络中,对个人通信以安全的手段进行身份认证,主要应用在域环境下的身份验证。
下图为大概的认证流程,共包含有三个重要的角色:Client、Server和KDC 相关名词介绍:
- 访问服务的Client
- 提供服务的Server
- KDC(Key Distribution Center) 密钥分发中心,在KDC中又分为两个部分:Authentication Service(AS,身份验证服务)和Ticket Granting Service(TGS,票据授权服务)
- DC是Domain Controller的缩写,即域控制器,对于一个Windows Domain来说,Domain Controller扮演着KDC的角色,AD是Active Directory的缩写,即活动目录。
DC中有一个特殊用户叫做:krbtgt,它是一个无法登录的账户,是在创建域时系统自动创建的,是域控中用来管理发放票据的用户,在整个kerberos认证中会多次用到它的Hash值去做验证。 AD会维护一个Account Database(账户数据库),它存储了域中所有账户的名称、派生于该Account Password的Master Key(密码进行hash运算得到一个Hash code)和白名单。只有账户密码都在白名单中的Client才能申请到TGT。 - Long-term Key/Master Key:长期不会进行变化的Key、以及由此派生的Key被称为Long-term Key,对于Long-term Key的使用有这样的原则:被Long-term Key加密的数据不应该在网络上传输。因为一旦这些被Long-term Key加密的数据包被恶意的网络监听者截获,理论上不变化总会被破解的。但是密码又是证明身份的凭据,所以必须通过基于密码的派生信息来证明用户的真实身份,在这种情况下,一般将你的密码进行Hash运算得到一个Hash code,被称为Master Key。由于Hash Algorithm是不可逆的,同时保证密码和Master Key是一一对应的,这样既保证了你密码的保密性,又同时保证你的Master Key和密码本身在证明你身份的时候具有相同的效力。
- Short-term Key/Session Key:由于被Long-term Key加密的数据包不能用于网络传送,所以我们使用另一种Short-term Key来加密需要进行网络传输的数据。由于这种Key只在一段时间有效,即使被加密的数据包被截获,等破解出来早过期了。
大致流程介绍: 当Client想要访问Server上的某个服务时,需要先向AS证明自己的身份,验证通过后AS会发放的一个TGT,随后Client再次向TGS证明自己的身份,验证通过后TGS会发放一个ST,最后Client向Server发起认证请求,这个过程分为三块:
- Client 与 AS 的交互,申请TGT(Ticket Granting Ticket):首先Client向KDC发起对TGT的申请,申请的内容大致可以这样表示:“我需要一张TGT用以申请获取用以访问所有Server的Ticket”。KDC在收到该申请请求后,生成一个用于该Client和KDC进行安全通信的Session Key(SKDC-Client)。为了保证该Session Key仅供该Client和自己使用,KDC使用Client的Master Key和自己的Master Key对生成的Session Key进行加密,从而获得两个加密的SKDC-Client的Copy。对于后者,随SKDC-Client一起被加密的还包含以后用于鉴定Client身份的关于Client的一些信息。最后KDC将这两份Copy一并发送给Client。这里有一点需要注意的是:为了免去KDC对于基于不同Client的Session Key进行维护的麻烦,就像Server不会保存Session Key(SServer-Client)一样,KDC也不会去保存这个Session Key(SKDC-Client),而选择完全靠Client自己提供的方式,将这两个被加密的Copy一并发送给Client,属于Server的那份由Client发送给Server。
- Client 与 TGS 的交互,申请用于访问Server的Ticket:当Client收到KDC的两个加密数据包之后,先使用自己的Master Key对第一个Copy进行解密,从而获得KDC和Client的Session Key(SKDC-Client),并把该Session 和TGT进行缓存。有了Session Key和TGT,Client自己的Master Key将不再需要,因为此后Client可以使用SKDC-Client向KDC申请用以访问每个Server的Ticket,相对于Client的Master Key这个Long-term Key,SKDC-Client是一个Short-term Key,安全保证得到更好的保障,这也是Kerberos多了这一步的关键所在。同时需要注意的是SKDC-Client是一个Session Key,他具有自己的生命周期,同时TGT和Session相互关联,当Session Key过期,TGT也就宣告失效,此后Client不得不重新向KDC申请新的TGT,KDC将会生成一个不同Session Key和与之关联的TGT。
Client在获得自己和KDC的Session Key(SKDC-Client)之后,生成自己的Authenticator以及所要访问的Server名称的并使用SKDC-Client进行加密。随后连同TGT一并发送给TGS。TGS使用自己的Master Key对TGT进行解密,提取Client Info和Session Key(SKDC-Client),然后使用这个SKDC-Client解密Authenticator获得Client Info,对两个Client Info进行比较进而验证对方的真实身份。验证成功,生成一份基于Client所要访问的Server的Ticket给Client,注意,TGS在接收到这个请求的时候,生成一个Session Key(SServer-Client),为了保证这个Session Key仅仅限于发送请求的Client和他希望访问的Server知晓,TGS会为这个Session Key生成两个Copy,分别被Client和Server使用。然后从Account database中提取Client和Server的Master Key分别对这两个Copy进行对称加密。对于后者,和Session Key一起被加密的还包含关于Client的一些信息。 - Client 与 Server 的交互,提交Ticket完成认证:Client通过自己的Master Key对TGS加密的Session Key进行解密从而获得Session Key(SServer-Client),随后创建Authenticator(Client Info + Timestamp)并用Session Key对其加密。最后连同从TGS获得的被Server的Master Key加密过的数据包(Client Info + Session Key)一并发送到Server端。我们把通过Server的Master Key加密过的数据包称为Session Ticket。
当Server接收到这两组数据后,先使用他自己的Master Key对Session Ticket进行解密,从而获得Session Key。随后使用该Session Key解密Authenticator,通过比较Authenticator中的Client Info和Session Ticket中的Client Info从而实现对Client的认证。
第一步:AS(Authentication Service)Exchange
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。
- Server Name:注意这里的Server Name并不是Client真正要访问的Server的名称,而我们也说了TGT是和Server无关的(Client只能使用Ticket,而不是TGT去访问Server)。这里的Server Name实际上是KDC的Ticket Granting Service的Server Name。
Time Synchronization的重要性 基于Timestamp的认证机制只有在Client和Server端的时间保持同步的情况才有意义。所以保持Time Synchronization在整个认证过程中显得尤为重要。在一个Domain中,一般通过访问同一个Time Service获得当前时间的方式来实现时间的同步。
AS(Authentication Service)通过它接收到的KRB_AS_REQ验证发送方的是否是在Client name & realm中声称的那个人,也就是说要验证发送放是否知道Client的Password。所以AS只需从Account Database中提取Client对应的Master Key对Pre-authentication data进行解密,如果是一个合法的Timestamp(一般不超过5min,否则会拒绝请求),则可以证明发送放提供的是正确无误的密码。验证通过之后,AS将一份Authentication Service Response(KRB_AS_REP)发送给Client。KRB_AS_REQ主要包含两个部分:本Client的Master Key加密过的Session Key(SKDC-Client:Logon Session Key)和被自己(KDC)加密的TGT。而TGT大体又包含以下的内容:
- Session Key: SKDC-Client:由于Client Log off也导致SKDC-Client的失效,所以SKDC-Client又被称为Logon Session Key。
- Client name & realm: 简单地说就是Domain name\Client。
- End time: TGT到期的时间。
Client通过自己的Master Key对第一部分解密获得Session Key(SKDC-Client:Logon Session Key)之后,携带着TGT便可以进入下一步:TGS(Ticket Granting Service)Exchange。
第二步: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和自己的Session Key(SKDC-Client: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是通过Logon Session Key(SKDC-Client)进行加密的,而自己并没有保存这个Session Key。所以TGS先得通过自己的Master Key对Client提供的TGT进行解密,从而获得这个Logon Session Key(SKDC-Client),再通过这个Logon Session Key(SKDC-Client)解密Authenticator进行验证。验证通过向对方发送Ticket Granting Service Response(KRB_TGS_REP)。这个KRB_TGS_REP有两部分组成:使用Logon Session Key(SKDC-Client)加密过用于Client和Server的Session Key(SServer-Client)和使用Server的Master Key进行加密的Ticket。该Ticket大体包含以下一些内容:
- Session Key:SServer-Client。
- Client name & realm: 简单地说就是Domain name\Client。
- End time: Ticket的到期时间。
Client收到KRB_TGS_REP,使用Logon Session Key(SKDC-Client)解密第一部分后获得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。
第三步:CS(Client/Server )Exchange
Client通过TGS Exchange获得Client和Server的Session Key(SServer-Client),随后创建用于证明自己就是Ticket的真正所有者的Authenticator,并使用Session Key(SServer-Client)进行加密。最后将这个被加密过的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(SServer-Client)进行加密,并将其发送给Client用于Client验证Server的身份。
User2User Sub-Protocol:有效地保障Server的安全
对于上面这三个过程,还是有点不安全的。上面提到过Long-term Key加密的数据不应该在网络中传递。对于3个Sub-Protocol中的C/S Exchange,Client携带的Ticket却是被Server Master Key进行加密的,这显现不符合我们提出的原则,降低Server的安全系数。
解决方案:在AS Exchange和TGS Exchange之间增加一个步骤,Client还得对Server进行请求已获得Server和KDC之间的Session Key(SKDC-Server)。
这个Session Key怎么来的,就是Server通过AS Exchange获得他和KDC之间的Session Key(SKDC-Server)和一个封装了这个Session Key并被KDC的Master Key进行加密的TGT,一旦获得这个TGT,Server会缓存它,以待Client对它的请求。 然后大概的步骤变成这样:
- AS Exchange:Client通过此过程获得了属于自己的TGT,有了此TGT,Client可凭此向KDC申请用于访问某个Server的Ticket。
- 这一步的主要任务是获得封装了Server和KDC的Session Key(SKDC-Server)的属于Server的TGT。如果该TGT存在于Server的缓存中,则Server会直接将其返回给Client。否则通过AS Exchange从KDC获取。
- TGS Exchange:Client通过向KDC提供自己的TGT,Server的TGT以及Authenticator向KDC申请用于访问Server的Ticket。KDC使用先用自己的Master Key解密Client的TGT获得SKDC-Client,通过SKDC-Client解密Authenticator验证发送者是否是TGT的真正拥有者,验证通过再用自己的Master Key解密Server的TGT获得KDC和Server 的Session Key(SKDC-Server),并用该Session Key加密Ticket返回给Client。
- C/S Exchange:Client携带者通过KDC和Server 的Session Key(SKDC-Server)进行加密的Ticket和通过Client和Server的Session Key(SServer-Client)的Authenticator访问Server,Server通过SKDC-Server解密Ticket获得SServer-Client,通过SServer-Client解密Authenticator实现对Client的验证。
文章来源: https://blog.csdn.net/sky_jiangcheng/article/details/81070240 https://www.jianshu.com/p/23a4e8978a30
|