談談基於Kerberos的Windows Network Authentication[上篇]

 

Content:

基本原理
引入Key Distribution: KServer-Client從何而來
引入Authenticator : 爲有效的證明自己提供證據
引入Ticket Granting  Service:如何獲得Ticket
Kerberos的3個Sub-protocol:整個Authentication的流程
User2User Protocol: 有效地保障Server的安全
Kerberos的優點的優點

前幾天在給人解釋Windows是如何通過Kerberos進行Authentication的時候,講了半天也別把那位老兄講明白,還差點把自己給繞進去。後來想想原因有以下兩點:對於一個沒有完全不瞭解Kerberos的人來說,Kerberos的整個Authentication過程確實不好理解——一會兒以這個Key進行加密、一會兒又要以另一個Key進行加密,確實很容易把人給弄暈;另一方面是我講解方式有問題,一開始就從Kerberos的3個Sub-protocol全面講述整個Authentication 過程,對於一個完全不瞭解Kerberos的人來說要求也忒高了點。爲此,我花了一些時間寫了這篇文章,儘量以由淺入深、層層深入的方式講述我所理解的基於Kerberos的Windows Network Authentication,希望這篇文章能幫助那些對Kerberos不明就裏的人帶來一絲幫助。對於一些不對的地方,歡迎大家批評指正。

一、 基本原理

Authentication解決的是“如何證明某個人確確實實就是他或她所聲稱的那個人”的問題。對於如何進行Authentication,我們採用這樣的方法:如果一個祕密(secret)僅僅存在於A和B,那麼有個人對B聲稱自己就是A,B通過讓A提供這個祕密來證明這個人就是他或她所聲稱的A。這個過程實際上涉及到3個重要的關於Authentication的方面:

  • Secret如何表示。
  • A如何向B提供Secret。
  • B如何識別Secret。

基於這3個方面,我們把Kerberos Authentication進行最大限度的簡化:整個過程涉及到Client和Server,他們之間的這個Secret我們用一個Key(KServer-Client)來表示。Client爲了讓Server對自己進行有效的認證,向對方提供如下兩組信息:

  • 代表Client自身Identity的信息,爲了簡便,它以明文的形式傳遞。
  • 將Client的Identity使用KServer-Client作爲Public Key、並採用對稱加密算法進行加密。

由於KServer-Client僅僅被Client和Server知曉,所以被Client使用KServer-Client加密過的Client Identity只能被Client和Server解密。同理,Server接收到Client傳送的這兩組信息,先通過KServer-Client對後者進行解密,隨後將機密的數據同前者進行比較,如果完全一樣,則可以證明Client能過提供正確的KServer-Client,而這個世界上,僅僅只有真正的Client和自己知道KServer-Client,所以可以對方就是他所聲稱的那個人。


Keberos大體上就是按照這樣的一個原理來進行Authentication的。但是Kerberos遠比這個複雜,我將在後續的章節中不斷地擴充這個過程,知道Kerberos真實的認證過程。爲了使讀者更加容易理解後續的部分,在這裏我們先給出兩個重要的概念:

  • Long-term Key/Master Key:在Security的領域中,有的Key可能長期內保持不變,比如你在密碼,可能幾年都不曾改變,這樣的Key、以及由此派生的Key被稱爲Long-term Key。對於Long-term Key的使用有這樣的原則:被Long-term Key加密的數據不應該在網絡上傳輸。原因很簡單,一旦這些被Long-term Key加密的數據包被惡意的網絡監聽者截獲,在原則上,只要有充足的時間,他是可以通過計算獲得你用於加密的Long-term Key的——任何加密算法都不可能做到絕對保密。

在一般情況下,對於一個Account來說,密碼往往僅僅限於該Account的所有者知曉,甚至對於任何Domain的Administrator,密碼仍然應該是保密的。但是密碼卻又是證明身份的憑據,所以必須通過基於你密碼的派生的信息來證明用戶的真實身份,在這種情況下,一般將你的密碼進行Hash運算得到一個Hash code, 我們一般管這樣的Hash Code叫做Master Key。由於Hash Algorithm是不可逆的,同時保證密碼和Master Key是一一對應的,這樣既保證了你密碼的保密性,有同時保證你的Master Key和密碼本身在證明你身份的時候具有相同的效力。

  • Short-term Key/Session Key:由於被Long-term Key加密的數據包不能用於網絡傳送,所以我們使用另一種Short-term Key來加密需要進行網絡傳輸的數據。由於這種Key只在一段時間內有效,即使被加密的數據包被黑客截獲,等他把Key計算出來的時候,這個Key早就已經過期了。

二、引入Key Distribution: KServer-Client從何而來

上面我們討論了Kerberos Authentication的基本原理:通過讓被認證的一方提供一個僅限於他和認證方知曉的Key來鑑定對方的真實身份。而被這個Key加密的數據包需要在Client和Server之間傳送,所以這個Key不能是一個Long-term Key,而只可能是Short-term Key,這個可以僅僅在Client和Server的一個Session中有效,所以我們稱這個Key爲Client和Server之間的Session Key(SServer-Client)。

現在我們來討論Client和Server如何得到這個SServer-Client。在這裏我們要引入一個重要的角色:Kerberos Distribution Center-KDC。KDC在整個Kerberos Authentication中作爲Client和Server共同信任的第三方起着重要的作用,而Kerberos的認證過程就是通過這3方協作完成。順便說一下,Kerberos起源於希臘神話,是一支守護着冥界長着3個頭顱的神犬,在keberos Authentication中,Kerberos的3個頭顱代表中認證過程中涉及的3方:Client、Server和KDC

對於一個Windows Domain來說,Domain Controller扮演着KDC的角色。KDC維護着一個存儲着該Domain中所有帳戶的Account Database(一般地,這個Account Database由AD來維護),也就是說,他知道屬於每個Account的名稱和派生於該Account Password的Master Key。而用於Client和Server相互認證的SServer-Client就是有KDC分發。下面我們來看看KDC分發SServer-Client的過程。

通過下圖我們可以看到KDC分發SServer-Client的簡單的過程:首先Client向KDC發送一個對SServer-Client的申請。這個申請的內容可以簡單概括爲“我是某個Client,我需要一個Session Key用於訪問某個Server ”。KDC在接收到這個請求的時候,生成一個Session Key,爲了保證這個Session Key僅僅限於發送請求的Client和他希望訪問的Server知曉,KDC會爲這個Session Key生成兩個Copy,分別被Client和Server使用。然後從Account database中提取Client和Server的Master Key分別對這兩個Copy進行對稱加密。對於後者,和Session Key一起被加密的還包含關於Client的一些信息。

KDC現在有了兩個分別被Client和Server 的Master Key加密過的Session Key,這兩個Session Key如何分別被Client和Server獲得呢?也許你 馬上會說,KDC直接將這兩個加密過的包發送給Client和Server不就可以了嗎,但是如果這樣做,對於Server來說會出現下面 兩個問題:

  • 由於一個Server會面對若干不同的Client, 而每個Client都具有一個不同的Session Key。那麼Server就會爲所有的Client維護這樣一個Session Key的列表,這樣做對於Server來說是比較麻煩而低效的。
  • 由於網絡傳輸的不確定性,可能出現這樣一種情況:Client很快獲得Session Key,並將這個Session Key作爲Credential隨同訪問請求發送到Server,但是用於Server的Session Key確還沒有收到,並且很有可能承載這個Session Key的永遠也到不了Server端,Client將永遠得不到認證。

爲了解決這個問題,Kerberos的做法很簡單,將這兩個被加密的Copy一併發送給Client,屬於Server的那份由Client發送給Server。


可能有人會問,KDC並沒有真正去認證這個發送請求的Client是否真的就是那個他所聲稱的那個人,就把Session Key發送給他,會不會有什麼問題?如果另一個人(比如Client B)聲稱自己是Client A,他同樣會得到Client A和Server的Session Key,這會不會有什麼問題?實際上不存在問題,因爲Client B聲稱自己是Client A,KDC就會使用Client A的Password派生的Master Key對Session Key進行加密,所以真正知道Client A 的Password的一方纔會通過解密獲得Session Key。 

三、引入Authenticator - 爲有效的證明自己提供證據

通過上面的過程,Client實際上獲得了兩組信息:一個通過自己Master Key加密的Session Key,另一個被Sever的Master Key加密的數據包,包含Session Key和關於自己的一些確認信息。通過第一節,我們說只要通過一個雙方知曉的Key就可以對對方進行有效的認證,但是在一個網絡的環境中,這種簡單的做法是具有安全漏洞,爲此,Client需要提供更多的證明信息,我們把這種證明信息稱爲Authenticator,在Kerberos的Authenticator實際上就是關於Client的一些信息和當前時間的一個Timestamp(關於這個安全漏洞和Timestamp的作用,我將在後面解釋)。

在這個基礎上,我們再來看看Server如何對Client進行認證:Client通過自己的Master Key對KDC加密的Session Key進行解密從而獲得Session Key,隨後創建Authenticator(Client Info + Timestamp)並用Session Key對其加密。最後連同從KDC獲得的、被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 InfoSession Ticket中的Client Info從而實現對Client的認證。


爲什麼要使用Timestamp?

到這裏,很多人可能認爲這樣的認證過程天衣無縫:只有當Client提供正確的Session Key方能得到Server的認證。但是在現實環境中,這存在很大的安全漏洞。

我們試想這樣的現象:Client向Server發送的數據包被某個惡意網絡監聽者截獲,該監聽者隨後將數據包座位自己的Credential冒充該Client對Server進行訪問,在這種情況下,依然可以很順利地獲得Server的成功認證。爲了解決這個問題,Client在Authenticator中會加入一個當前時間的Timestamp

在Server對Authenticator中的Client Info和Session Ticket中的Client Info進行比較之前,會先提取Authenticator中的Timestamp,並同當前的時間進行比較,如果他們之間的偏差超出一個可以接受的時間範圍(一般是5mins),Server會直接拒絕該Client的請求。在這裏需要知道的是,Server維護着一個列表,這個列表記錄着在這個可接受的時間範圍內所有進行認證的Client和認證的時間。對於時間偏差在這個可接受的範圍中的Client,Server會從這個這個列表中獲得最近一個該Client的認證時間,只有當Authenticator中的Timestamp晚於通過一個Client的最近的認證時間的情況下,Server採用進行後續的認證流程。

Time Synchronization的重要性

上述 基於Timestamp的認證機制只有在Client和Server端的時間保持同步的情況纔有意義。所以保持Time Synchronization在整個認證過程中顯得尤爲重要。在一個Domain中,一般通過訪問同一個Time Service獲得當前時間的方式來實現時間的同步。

雙向認證(Mutual Authentication)

Kerberos一個重要的優勢在於它能夠提供雙向認證:不但Server可以對Client 進行認證,Client也能對Server進行認證

具體過程是這樣的,如果Client需要對他訪問的Server進行認證,會在它向Server發送的Credential中設置一個是否需要認證的Flag。Server在對Client認證成功之後,會把Authenticator中的Timestamp提出出來,通過Session Key進行加密,當Client接收到並使用Session Key進行解密之後,如果確認Timestamp和原來的完全一致,那麼他可以認定Server正式他試圖訪問的Server。

那麼爲什麼Server不直接把通過Session Key進行加密的Authenticator原樣發送給Client,而要把Timestamp提取出來加密發送給Client呢?原因在於防止惡意的監聽者通過獲取的Client發送的Authenticator冒充Server獲得Client的認證。


談談基於Kerberos的Windows Network Authentication - Part II

相關內容:
[原創]談談基於Kerberos的Windows Network Authentication - Part I
[原創]談談基於Kerberos的Windows Network Authentication - Part II
[原創]談談基於Kerberos的Windows Network Authentication - Part III

發佈了0 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章