Artech

Develop every application as an art using the most suitable technologies!

常用链接

统计

积分与排名

CnBlogs

专家的Blog|主页

最新评论

[原创]谈谈基于Kerberos的Windows Network Authentication - Part II

Content:

基本原理
引入Key Distribution: KServer-Client从何而来
引入Authenticator : 为有效的证明自己提供证据
引入Ticket Granting  Service:如何获得Ticket
Kerberos的3个Sub-protocol:整个Authentication的流程
User2User Protocol: 有效地保障Server的安全
Kerberos的优点的优点

谈谈基于Kerberos的Windows Network Authentication - Part I

四、引入Ticket Granting  Service

通过上面的介绍,我们发现Kerberos实际上一个基于Ticket的认证方式。Client想要获取Server端的资源,先得通过Server的认证;而认证的先决条件是Client向Server提供从KDC获得的一个有Server的Master Key进行加密的Session Ticket(Session Key + Client Info)。可以这么说,Session Ticket是Client进入Server领域的一张门票。而这张门票必须从一个合法的Ticket颁发机构获得,这个颁发机构就是Client和Server双方信任的KDC, 同时这张Ticket具有超强的防伪标识:它是被Server的Master Key加密的。对Client来说, 获得Session Ticket是整个认证过程中最为关键的部分。

上面我们只是简单地从大体上说明了KDC向Client分发Ticket的过程,而真正在Kerberos中的Ticket Distribution要复杂一些。为了更好的说明整个Ticket Distribution的过程,我在这里做一个类比。现在的股事很火爆,上海基本上是全民炒股,我就举一个认股权证的例子。有的上市公司在股票配股、增发、基金扩募、股份减持等情况会向公众发行认股权证,认股权证的持有人可以凭借这个权证认购一定数量的该公司股票,认股权证是一种具有看涨期权的金融衍生产品。

而我们今天所讲的Client获得Ticket的过程也和通过认股权证购买股票的过程类似。如果我们把Client提供给Server进行认证的Ticket比作股票的话,那么Client在从KDC那边获得Ticket之前,需要先获得这个Ticket的认购权证,这个认购权证在Kerberos中被称为TGT:Ticket Granting Ticket,TGT的分发方仍然是KDC。

我们现在来看看Client是如何从KDC处获得TGT的:首先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自己提供的方式。


当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 Log off也导致SKDC-Client的失效,所以SKDC-Client又被称为Logon Session Key

接下来,我们看看Client如何使用TGT来从KDC获得基于某个Server的Ticket。在这里我要强调一下,Ticket是基于某个具体的Server的,而TGT则是和具体的Server无关的,Client可以使用一个TGT从KDC获得基于不同Server的Ticket。我们言归正传,Client在获得自己和KDC的Session Key(SKDC-Client)之后,生成自己的Authenticator以及所要访问的Server名称的并使用SKDC-Client进行加密。随后连同TGT一并发送给KDC。KDC使用自己的Master Key对TGT进行解密,提取Client Info和Session Key(SKDC-Client),然后使用这个SKDC-Client解密Authenticator获得Client Info,对两个Client Info进行比较进而验证对方的真实身份。验证成功,生成一份基于Client所要访问的Server的Ticket给Client,这个过程就是我们第二节中介绍的一样了。 


五、Kerberos的3个Sub-protocol:整个Authentication

通过以上的介绍,我们基本上了解了整个Kerberos authentication的整个流程:整个流程大体上包含以下3个子过程:

  1. Client向KDC申请TGT(Ticket Granting Ticket)。
  2. Client通过获得TGT向DKC申请用于访问Server的Ticket。
  3. Client最终向为了Server对自己的认证向其提交Ticket。

不过上面的介绍离真正的Kerberos Authentication还是有一点出入。Kerberos整个认证过程通过3个sub-protocol来完成。这个3个Sub-Protocol分别完成上面列出的3个子过程。这3个sub-protocol分别为:

  1. Authentication Service Exchange
  2. Ticket Granting Service Exchange
  3. Client/Server Exchange

下图简单展示了完成这个3个Sub-protocol所进行Message Exchange。


1. Authentication Service Exchange

通过这个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
  • Server Name:注意这里的Server Name并不是Client真正要访问的Server的名称,而我们也说了TGT是和Server无关的(Client只能使用Ticket,而不是TGT去访问Server)。这里的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加密过的Session Key(SKDC-Client:Logon Session Key)和被自己(KDC)加密的TGT。而TGT大体又包含以下的内容:

  • Session Key: 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。

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的办法方和自己的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

3. 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的身份。

 

到此为止,Kerberos的整个过程大体上已经介绍完毕。不知道他们有没有意识到这其中有什么安全隐患?我在一开始在介绍Long-term Key和Short-term Key的时候就已经强调过:被Long-term Key加密的信息最好不要在网络中传递,然后Client从KDC获得的Ticket确是通过Server的Master Key加密的,这显然对Server来说是不安全的,为了解决这个问题,Kerberos引入了第4个Sub-protocol: User2User。关于User2User Protocol,敬请关注本Blog的第三部分

相关内容:
[原创]谈谈基于Kerberos的Windows Network Authentication - Part I
[原创]谈谈基于Kerberos的Windows Network Authentication - Part II
[原创]谈谈基于Kerberos的Windows Network Authentication - Part III

posted on 2007-07-07 15:15 Artech 阅读(2795) 评论(26)  编辑 收藏

评论

#1楼  2007-07-07 15:48 A Lin [未注册用户]

写得好,期待Part III。   回复  引用    

#2楼  2007-07-07 15:49 WWW [未注册用户]

感觉比很多专栏文章都不逊色,LZ强人啊!   回复  引用    

#3楼 [楼主] 2007-07-07 15:51 Artech      

@A Lin
谢谢关注!
@WWW
真是过奖了!   回复  引用  查看    

#4楼  2007-07-07 23:55 发条木偶      

收藏   回复  引用  查看    

#5楼 [楼主] 2007-07-07 23:57 Artech      

@发条木偶
:)   回复  引用  查看    

#6楼  2007-07-08 00:22 Anytao      

愈发愈勇:-)   回复  引用  查看    

#7楼 [楼主] 2007-07-08 00:41 Artech      

@Anytao
写文章,同时也是学习的过程嘛。谢谢捧场:)   回复  引用  查看    

#8楼  2007-07-08 17:39 ks [未注册用户]

非常深奥, 读了几次就了解了。 谢谢。
你的文章帮助我了解LINUX的kerberos.

  回复  引用    

#9楼 [楼主] 2007-07-08 18:16 Artech      

@ks
Kerberos的过程也算复杂,就是有点绕,第一次看很容易就被弄晕掉了,多看几遍就很容易理解了。
kerberos是MIT首创,现在已经成为一个厂商独立的标准,无论是Windows和Linux都大同小异.   回复  引用  查看    

#10楼  2007-07-10 14:34 Bird [未注册用户]

对于最后所说的最好不要把Sever端的Long-term Key在网络中传输表示认同,同时提出一点疑问:
既然这个时候Client端已经拥有了从KDC获得的Logon Session Key(SKDC-Client),并且KDC就是用它来加密SServer-Client的。那为何不用这个Logon Session Key也同样把Ticket做一下加密呢,这样的话Server的long-term Key就不会以明文方式在网络中传播了,而且Client端也可以用Logon Session Key来解密,之后才传给Server端。   回复  引用    

#11楼  2007-07-10 14:38 Bird [未注册用户]

想通了,因为一会这个Ticket还是要被Client以明文形式传送给Server的。   回复  引用    

#12楼 [楼主] 2007-07-10 14:46 Artech      

@Bird
其实在真正的Kerberos,Ticket并不是以明文传递。Ticket对于Client来说是保密的,Ticket是属于Server的Session Key。所以不能通过Logon Session Key进行加密。而Logon Session Key是属于Client和KDC的Session,对于Server是保密的,Server如何通过Logon Session Key解密Ticket呢。

所以Ticket之能被属于Server的Key进行加密,所以选择Server Master Key(Long-term Key)或者是Server和KDC的Session Key(Short-term Ket)   回复  引用  查看    

#13楼  2007-07-11 10:48 Bird [未注册用户]

@Artech
已经从你的第三篇里获得结果,谢谢!   回复  引用    

#14楼  2007-07-11 10:57 Bird [未注册用户]

还有一个疑问,就是你在本文的3个步骤的第一个里面提到的,当Client向KDC的Authentication Service发送Authentication Service Request(KRB_AS_REQ)时,会用自己的Master Key加密一个Timestamp?这样的话不是违背了经Long-term Key加密的数据不能在网络上传输的原则了吗?   回复  引用    

#15楼 [楼主] 2007-07-11 12:27 Artech      

@Bird
因为这一步完成的KDC对Client的身份进行鉴定,确定Client就是他所声称的那个人,而Client提供证明的方式只能是:它知道他所声称的那个人的Password,所以他必须提供Client的Password派生的Master Key。

这也是不能避免的,因为这个时候Client还没有和KDC进行交互,所以他无法获得一个Session Key。为了让KDC对自己进行认证,必须时候一个KDC和自己知道的Key,那就是Client的Master Key。

实际上,这样做确实有一点点安全问题,但是在实际情况下还是可以接受的:Client使用自己的Master Key获取TGT,他就可以在有效期内一直用,所使用Client的Master Key的次数很少的;此外Client仅限于对自己所在Domain的KDC进行TGT的申请,安全也会得到一定的保障。   回复  引用  查看    

#16楼  2007-07-12 09:56 Bird [未注册用户]

@Artech
其实不光是这里,在你的第三篇中加入的User2User Protocol中,Server要获取KDC的SKDC-Server,也要像Client这样先用自己的Master Key加密一个TimeStamp。我的理解是为了获取一个能用来加密并在网络上传播的与KDS交互用的Session Key,原则上Server和Client都不得不先“暴露”自己的Master Key于网络之中?虽然这样的“暴露”是很少发生的(仅当每个Session Key过期,需要创建新的Session Key的时候才发生)。
另外只要我破解了某域用户的的Master Key,我就一直可以冒充该用户端来和任何Server端进行Kerberos认证了。
  回复  引用    

#17楼 [楼主] 2007-07-12 10:47 Artech      

@Bird
其实这是一个很简单的道理,Password是用户身份的唯一证明,但用户,无论是Client还是Server,当他向KDC获取所需的Session Key的时候,KDC必须要验证他是否是他所声称的那个人,所以向KDC提供自己的Master Key是必须的。   回复  引用  查看    

#18楼  2007-07-12 15:55 Bird [未注册用户]

@Artech
确实是这样,对于对称密钥来说这个过程是必须的。   回复  引用    

#19楼 [楼主] 2007-07-12 16:02 Artech      

@Bird
:)   回复  引用  查看    

#20楼  2007-07-13 14:32 1 [未注册用户]

作者真是高产,文章质量也不错。
  回复  引用    

#21楼 [楼主] 2007-07-13 14:36 Artech      

@1
我算不上高产,比起园子里的活跃的Blogger们,我差远了:)   回复  引用  查看    

#22楼  2008-01-08 15:25 飞扬跋扈      

请问:
client向kdc申请tgt的时候,kdc使用了自己的master key对session key + client info进行加密然后发给client作为tgt。这里是不是仍然违背了“以某个Entity的Long-term Key加密的数据不应该在网络中传递”? 理论上,client可以算出来kdc的master key。容易想到的一个解决方案是kdc不使用自己的mater key,而是同样为本次请求创建一个short term key,缓存之,将其用于加密。但是这样是不是就违背了kdc不缓存sessino key的那一条?   回复  引用  查看    

#23楼 [楼主] 2008-01-09 17:07 Artech      

@飞扬跋扈
这是一个很好的问题、这样对于DKC来说,具有一定的安全隐患。不过我也不知道该如何回答你这个问题^_^   回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-07-10 17:22 编辑过


相关链接: