kerberos定義
- Kerberos 是一種網絡認證協議,其設計目標是經過密鑰系統爲客戶機、服務器應用程序提供強大的認證服務。
- Kerberos 做爲一種可信任的第三方認證服務,是經過傳統的密碼技術(如:共享密鑰)執行認證服務的。
- Kerberos也能達到單點登陸的效果,即當Client經過了Kerberos server的認證後,即可以訪問多個Real Server。
kerberos幾個重要組件
- KDC又稱Kerberos服務器:負責管理髮放Ticket和記錄受權的中心服務器,包含兩部分:AS認證服務器(Authentication Server),TGS服務受權服務器(Ticket Granting Server)
- Client 客戶端:須要使用kerbores服務的客戶端
- AppServer 服務端:提供具體服務的服務端
- Client在Kerberos註冊用戶名c,密碼Kc;Kerberos服務器將用戶的用戶名及密碼存放在它的數據庫中,所以密碼Kc只有Client和Kerberos才擁有。
- AppServer在Kerberos註冊用戶名s,密碼Ks;同理密碼Ks只有AppServer和Kerberos才擁有。
- TGS在Kerberos註冊用戶名tgs,密碼Ktgs;同理密碼Ktgs只有TGS和Kerberos才擁有。
![image.png image.png](http://static.javashuo.com/static/loading.gif)
kerberos中幾個重要概念
- 用戶principal的命名:相似elis/admin@EXAMPLE.COM,形式是用戶名/角色/realm域。
- 服務principal的命名相似ftp/station1.example.com@EXAMPLE.COM,形式是服務名/地址(提供者)/realm域;
- principal(認證的主體即簡稱「用戶名」):每添加一個服務或者用戶就要添加一條principal,每一個principal都有一個密碼。用戶principal的密碼用戶本身記住,服務的principal密碼服務本身記錄在硬盤上(keytab文件中);
- realm(Kerberos的域):有點像編程語言中的namespace。在編程語言中,變量名只有在某個"namespace"裏纔有意義。一樣的,一個principal只有在某個realm下才有意義。因此realm能夠當作是principal的一個"容器"或者"空間"。相對應的,principal的命名規則是"what_name_you_like@realm"。
在kerberos, 你們都約定成俗用大寫來命名realm, 好比"EXAMPLE.COM"算法
- Kerberos的進程:有krb5kdc(主進程,也就是KDC)、kadmind(用於遠程管理principal數據庫)、kpropd(slave同步數據用)。配置文件在/etc/krb5.conf和/var/kerberos/krb5kdc/下,數據庫在/var/kerberos/krb5kdc/princical;
- Kerberos只提供一種功能——在網絡上安全的完成用戶的身份驗證。它並不提供受權功能或者審計功能。
kerberos認證交互過程
kerberos認證交互過程能夠簡要歸納爲如下圖片中的三次通訊
shell
- 每次通訊,消息包含兩部分,一部分可解碼,一部分不可解碼;
- 服務端不會直接與KDC通訊
- KDC保存全部機器的帳戶名和密碼
- KDC自己具備一個密碼
第一次通訊
client-->AS(Authentication Service)認證服務數據庫
- 想要訪問http服務,首先要向KDC表名本身的身份,經過未加密的信息發送至KDC獲取Ticket Granting Ticket (TGT)。
- 信息包含(你的用戶名/ID、你的IP地址、TGT的有效時間);
- Authentication Server收到你的請求後,會去數據庫中驗證,你是否存在。注意!僅僅是驗證是否存在,不會驗證對錯。
- 若是存在,Authentication Server會產生一個隨機的Session key(能夠是一個64位的字符串),這個key用於你和Ticket Granting Server (TGS)之間通訊。Authentication Server會發送兩部分信息給你,一部分信息爲TGT,經過KDC本身的密碼進行加密,包含(你的name/ID、TGS的name/ID、時間戳、你的IP地址、TGT的生命週期、TGS session key),另一部分經過你的密碼進行加密,包含的信息(TGS的name/ID、時間戳、生命週期、TGS session key)
- 若是不存在會報出:client not found in Kerberos databases while getting initial這樣的錯誤,意思就是KDC的數據庫中沒有找到你這用戶。
- 使用你的密碼解密第二部分信息,獲取到TGS session key。若是密碼不正確,沒法解密,則認證失敗。第一部分信息TGT,你是沒法解密的,但須要暫時緩存起來。
![image.png image.png](http://static.javashuo.com/static/loading.gif)
第二次通訊
client-->TGS(Ticket Granting Service)票據授予服務器編程
若是第一步認證成功了,說明此時你已經擁有了一個沒法解密的TGT和一個經過本身密碼解密第二部分信息獲取到的TGS Session Key。緩存
- 請求信息包含三部分:1.經過TGS Session Key加密的認證器部分(你的name/ID、時間戳)2.明文傳輸部分:(請求的Http服務名(就是請求信息)、HTTP Service的Ticket生命週期)3.TGT部分
- Ticket Granting Server收到信息後,首先檢查數據庫中是否包含有你請求的Http服務名。
- 若是無,直接返回錯誤信息。
- 若是存在,則經過KDC的密碼解密TGT,這個時候。咱們就能獲取到TGS Session key。而後,經過TGS Session key去解密你傳輸的第一部分認證器,獲取到你的用戶名和時間戳。
- TGS再次進行驗證:
- 對比TGT中的用戶名與認證器中的用戶名
- 比較時間戳(認證器中的時間戳和系統的時間戳),不能超過必定範圍(一般30分鐘),時間戳用於防止重放攻擊,因此全部的機器都必需使用安全的相似NTP的機制把時間同步好。
- 檢查是否過時
- 檢查IP地址是否一致
- 檢查認證器是否已在TGS緩存中(避免應答攻擊)
- 驗證經過後TGS會發送兩部分信息給你:1.經過Http服務的密碼進行加密的信息(ST):(你的name/ID、Http服務name/ID、你的IP地址、時間戳、ST的生命週期、Http Service Session Key)和 經過TGS Session Key加密的信息(Http服務name/ID、時間戳、ST的生命週期、Http Service Session Key)
- 你收到信息後,經過TGS Session Key解密,獲取到了Http Service Session Key,可是你沒法解密ST。
![image.png image.png](http://static.javashuo.com/static/loading.gif)
第三次通訊
client-->Http服務安全
前面兩步成功後,之後每次獲取Http服務,在Ticket沒有過時,或者無更新的狀況下,均可直接進行這一步。省略前面兩個步驟。服務器
- 向Http Server發送請求信息,包含兩部分:1.經過Http Service Session Key,加密部分(你的name/ID、時間戳),2.ST
- Http服務端經過本身的密碼解密ST(KDC是用Http服務的密碼加密的),這樣就可以獲取到Http Service Session Key,解密第一部分。
- 服務端解密ST後,進行檢查
- 對比ST中的用戶名(KDC給的)與認證器中的用戶名
- 比較時間戳(認證器中的時間戳和系統的時間戳),不能超過必定範圍
- 檢查是否過時
- 檢查IP地址是否一致
- 檢查認證器是否已在HTTP服務端的緩存中(避免應答攻擊)
- Http Server應答信息:經過Http Service Session Key加密的信息(Http服務name/ID、時間戳)
![image.png image.png](http://static.javashuo.com/static/loading.gif)
- 你經過緩存的Http Service Session Key解密這部分信息,而後驗證是不是你想要的服務器發送給你的信息。完成你的服務器的驗證。
至此,整個過程所有完成。網絡
kerberos疑問
- 上面有個數據包是KDC經Client轉發給Server的,爲何不直接發給Server?
- 由於Server可能給多個Client提供服務,這樣Server須要維護一個Client和會話密鑰的對應表,這對Server是一個負擔。
- 爲何要發兩份關於Client的信息給Server?
- 經過這兩份數據的對比,Server就能判斷出是否是對的Client在訪問服務。
- Client是如何判斷本身在訪問對的Server呢?
- 由於Client給Server的一個數據包是用Server的master key來加密的因此只有對的Server才能解密。
- 爲何要用會話密鑰
- 通訊方的master key是長期有效的,若是在網絡上傳輸,一旦被截取,理論上來講只要有足夠的時間是能夠破解的。
- 因此咱們才用臨時的會話密鑰來通訊,一段時間後會話密鑰會過時,同時時間戳也防止了,惡意用戶重複使用同一個數據包。
- 爲何要用時間戳?
- 若是Client向Server傳送的數據包被其餘的Client截取,而後本身拿來向Server請求服務這,這樣就會出問題
- Server收到請求後將從解密後的數據包中得到的時間戳和當前時間對比,一旦超過必定範圍將直接拒絕請求
kerberos自身的安全工做如何作?
- kerberos的安全是創建在主機都是安全的而網絡不是安全的假定之上的。因此kerberos的安全其實就在於把主機的安全作好;
- 尤爲是KDC那臺機器的安全。出於安全的考慮,跑KDC的機器上不能再跑別的服務,若是KDC被攻陷了,那麼全部的密碼就所有泄露了;
- 若是隻是服務的機器被攻陷了,那麼更改服務的principal的密碼便可;
- 若是是用戶的機器被攻陷了,那麼在ticket超時(通常是數小時的時間裏)以前,用戶都是不安全的,攻擊者還有可能嘗試反向用戶的密碼;
- Kerberos依賴其它的服務來存放用戶信息(登陸shell、UID、GID啥的),所以須要注意到這些信息依然是很容易遭受攻擊而且泄露的;
- 因爲任何人均可以向KDC請求任何用戶的TGT(使用用戶密碼加密的session key),那麼攻擊者就有可能請求一個這樣的包下來嘗試解密,他們有充足的時間離線去作這個工做,一旦解開了,他們也就拿到了用戶的密碼。簡單密碼幾乎一解就開,因此不能設置簡單密碼,也不能在字典裏。另外還能夠打開Kerberos的預驗證機制來防護這種攻擊,預驗證機制就是在KDC收到用戶請求TGT的請求以後,要求用戶先發一個用本身密碼加密的時間戳過來給KDC,KDC若是確實能夠用本身存儲的用戶密碼解密,才發TGT給用戶,這樣攻擊者在沒有用戶密碼的時候就拿不到可用於反向的包含用戶密碼的TGT包了。在MIT kerberos中在配置文件中default_principal_flags = + preauth能夠打開這個機制。但這個機制也並非無懈可擊的,攻擊者依然能夠經過嗅探的方式在正經常使用戶請求TGT時拿到上述的那個包(這個難度顯然就高了一些);
- 還有一個問題是攻擊者可能僞造一個KDC,而後用一個僞造的實際不存在的用戶向這個KDC請求驗證,經過後他就獲得了一個用戶登陸系統的shell。這種攻擊須要在客戶端防護,須要客戶端主動去驗證一下KDC是不是正確的KDC。具體來講就是客戶端在獲得TGT後進一步要求KDC給一個本物理機的principal(也就是一個用物理機密鑰加密的串),而後嘗試用物理機存儲的密碼去解密,因爲僞造的KDC沒有物理機(host/hostname)的principal密碼,因此它沒法給出這個包,也就被客戶端認定爲是僞造的KDC,認證失敗。這個機制須要在客戶端開啓(認證服務器端麼),默認是關閉的,在krb5.conf裏[appdefaults]章節裏pam的部分中設置validate=true來開啓;
Kerberos能夠在不一樣的realm之間創建信任關係
這樣用戶在一個realm中登陸後就能夠享用多個realm中的服務。簡單的創建互信的方法是在2個域名都創建一條共享密碼的名爲krbtgt的principal。更好的創建互信的方法是多個realm都創建一條信任到本身的父realm,這樣在子realm之間也能創建起信任;session
Kerberos還能向SSL幫助網絡流量套上一層加密
好比說telnet這種明文協議就可能能用上。可是跟SSL或者SSH比起來安全性仍然略低,由於它的session key是用對稱加密傳輸的(若是TGT被盜取了,流量的加密也就失效了),這在理論上增長了被嗅探破解的可能。而SSH和SSL協商session key採用的DH算法是理論安全的(被稱爲PFS即Perfect forward secrecy,詳見http://en.wikipedia.org/wiki/..._forward_secrecy)。還有一個問題是Kerberos採用的一些加密算法是已經不安全的了(如CRC32和DES),而另外一些加密算法(AES)並無被其餘的kerberos實現普遍使用,因此會有一些兼容性的麻煩,選擇加密算法時要避開這些算法;app
若是將princical密碼設置爲random
那麼每次將其dump到本地keytab中時,都會random新的密碼並dump到本地(可用於更新密碼);