Kerberos 101

**作者:**賴榮樞
http://www.goodman-lai.idv.tw

Kerberos 源自於麻省理工學院的雅典娜計劃,截至目前為止已經有十幾年的歷史,之前的版本僅供內部使用,第一次公開的版本是第四版,而目前的版本為第五版。

Kerberos 第五版是 Windows 2000 開始加入的預設認證協定,Windows Server 2003 也繼續採用 Kerberos 作為認證機制。Kerberos 是 Windows Server System 系統安全的核心,所有的網域使用者在登入 Windows 2000 Server 或 Windows Server 2003 時,都必須先經過 Kerberos 這一關來確認身份,接著系統才能根據使用者的身份授予相關的權限。

本頁內容

Kerberos 的歷史
對稱式加密法
一對一的認證方式
金鑰中心的認證方式
Ticket-Granting Ticket
跨轄區的認證方式
Kerberos 的基本協定
結論

Kerberos 的歷史

Kerberos 其實是希臘神話中看守地獄大門的三頭猛犬的名字,這頭猛犬除了比一般狗狗多出兩個狗頭外,還有噴火與噴硫酸的特異功能。總之呢,除非是像海格力士這號超級肌肉男,否則一般尋常百姓絕非 Kerberos 的對手。由於 Kerberos 象徵著看門、守衛的意思,也因此當初 MIT 雅典娜小組便以此來命名他們所開發的認證協定。

簡而言之,Kerberos 是一套認證的協定,利用「對稱式加密法」(或稱為「傳統式加密法」、「秘鑰加密法」)的原理,提供用戶端與伺服端之間相互認證的功能。也就是說,伺服端可透過此協定來確認用戶端的身份,而用戶端也可藉此確認伺服端的身份。

對稱式加密法

對稱式加密法的定義為加密與解密時,必須使用相同的秘鑰(secret key),以及相同或類似的演算法,也就是利用秘鑰將明文文字變成加密文字。

秘鑰通常是一串固定長度(例如,128個位元)的資料所組成。在實際應用上,一般是以雜湊函數(Hash function),將使用者的密碼加以運算求得雜湊值(Hash code),再以雜湊值作為為秘鑰。由於雜湊函數為單向運算的函數,也就是說,其他人無法利用秘鑰來反推原始的密碼。

對稱式加密法除了可用來對資料加密外,也可應用在認證的功能,其原理相當簡單,假設使用者 A 與 B 各自擁有一把相同的秘鑰 K,而且這兩人相信世界上不會有其他人擁有這一把 K。在實際進行認證時,可以有以下兩種方式:

  • 當使用者 A 利用 K 將某一段明文文字(PT)加密為加密文字(CT),若對方可將 CT 解密為 PT,則 A 即可確認具有此解密能力者為 B。

  • 當使用者 A 收到來自對方的一段加密文字 CT 時,若 A 能成功地利用 K 將 CT 解密為 PT,則 A 可確認對方為 B。

有關對稱式加密法的認證方式,許多人最常問的問題就是 A 與 B 如何共享秘鑰?要回答這個問題必須先澄清一個基本觀念,也就是秘鑰共享在對稱式加密法的認證方式中是一項預設的前提。秘鑰必須在事前透過其他的安全管道來交換。唯有 A 與 B 共享秘鑰的條件下,接下來才能進行對稱式加密法的認證。例如,在一般的企業網路中,無論使用何種網路系統,網管人員勢必需要以網路以外的安全管道(直接面告或傳小紙條等等),來告知新使用者的帳號/密碼。之後,使用者才能使用此帳號/密碼來登入網路進行認證。

雖然 Kerberos 的整個架構相當複雜,但其基本精神即是利用對稱式加密法來認證,所以請務必牢記對稱式加密法的認證原理。若讀者對後文中 Kerberos 協定的架構有任何疑惑,只要重新回歸到上述的基本原理,問題大概都可以迎刃而解。

一對一的認證方式

為了方便介紹,在此將假想一種簡化的一對一認證架構,並說明在此架構下,利用對稱式加密法來認證時,所需進行的步驟。

圖 1:一對一的認證方式

圖 1:一對一的認證方式

假設現在網路上有兩台電腦用戶端與伺服端。用戶端與伺服端各自擁有一把相同的密鑰 Kclt(當然,世界上不會有其他人擁有這一把 Kclt),而且雙方事先已經協調好要使用什麼樣的演算法。最後,用戶端與伺服端的時間誤差必須同步化(後文會說明為何需要將時間同步)。在上述條件下,若用戶端與伺服端要相互認證,其步驟如下:

  1. 用戶端送出 Msg1 訊息給伺服端:

    Msg1:"我是用戶端", {用戶端相關資訊, 時間戳記}Kclt

    "我是用戶端"表示雙引號中的資訊會以明文的方式來傳送。{用戶端相關資訊, 時間戳記} Kclt 則是表示將大括弧中的資訊以 Kclt 加密後再傳送。本文將延用此一表示法來描述 Kerberos 協定中訊息的內容。

    訊息中的{用戶端相關資訊, 時間戳記} Kclt 就是 Kerberos 中所謂的 Authenticator(可用來作為認證的一段加密文字)。Authenticator 是由認證雙方所共享的秘鑰加密而成,內容通常會包含多項資訊,其中最重要的資訊之一便是時間戳記,也就是建立 Authenticator 的時間。時間戳記的目的主要是為了防範重送攻擊(註2)。

  2. 伺服端收到 Msg1 訊息

    伺服端收到 Msg1 訊息之後,便可從訊息中明文的部份可知道對方電腦自稱為用戶端。伺服端從本身的安全資料庫中找出與用戶端共享的秘鑰 Kclt,再利用 Kclt 將 {用戶端相關資訊, 時間戳記} Kclt 解密。解密後,伺服端可比對 {用戶端相關資訊, 時間戳記} Kclt 中的用戶端與 "I am 用戶端" 的內容,若核對無誤,則伺服端可確認這個自稱為用戶端的傢伙果真是用戶端 (因為世界上除了伺服端外,只有用戶端才有使用 Kclt 來加密產生 Msg1 的能力)。伺服端可進一步比對 Msg1 訊息中的時間戳記與伺服端目前的時間,若兩者在合理的誤差範圍內(一般是 5 分鐘),則可排除重送攻擊的可能性。

  3. 伺服端送出 Msg2 訊息

    伺服端將解密 Msg1 訊息所得的時間戳記以 Kclt 加密後(只取時間戳記的意義在於,伺服端才能藉此向用戶端證明自己有解密 Msg1 的能力),建立 Msg2 訊息並傳送給用戶端:

    Msg2:{時間戳記} Kclt

  4. 用戶端收到 Msg2 訊息

    用戶端收到 Msg2 訊息後,利用 Kclt 解密 Msg2,取得 Msg2 中的時間戳記,並用來比對在步驟 1 中建立 Msg1 時的時間。若兩者相符,則用戶端即可確認伺服端的身份(因為除了用戶端外,只有伺服端才有使用 Kclt 來解密 Msg1 並建立 Msg2 的能力)。

    完成上述四個步驟之後,用戶端與伺服端之間即完成相互認證的動作。這種一對一的認證方式有一個先天的缺陷,也就是當網路中電腦的數目增加時,秘鑰的數目也會隨之暴增,而產生管理上的困難。這就有如點對點 (peer-to-peer) 的網路架構僅能用在小型的區域網路上。若要能應用在一般區域網路上,勢必要使用集中式的管理架構。

金鑰中心的認證方式

金鑰中心 (KDC,Key Distributed Center) 為集中式金鑰管理的核心機構。金鑰中心儲存了網路中每個主體(包括各種形式的用戶端與伺服端)的秘鑰,並負責這些秘鑰的管理與發送的工作。也就是說,當用戶端與伺服端之間需要相互認證時,必須透過金鑰中心來完成認證。

在實際的應用上,金鑰中心必須負責建立 Session Key (階段性的秘鑰) 與 Ticket (票證)。

  • Session Key:從先前對稱式加密法的認證方式中,我們可以知道,當用戶端與伺服端需要相互認證時,雙方必須要擁有相同的秘鑰。在金鑰中心認證方式的前提中,用戶端與金鑰中心共享用戶端的秘鑰,伺服端與金鑰中心共享伺服端的秘鑰,但 client 與伺服端卻沒有共享的秘鑰。解決的方法即是利用 Session Key。當用戶端向金鑰中心要求與伺服端認證時,金鑰中心會建立兩把相同的 Session Key,並透過 Ticket 的機制,安全地將 Session Key 分別傳送給用戶端與伺服端,以便兩者進行相互認證的工作。

  • Ticket:Ticket 顧名思義與我們日常生活所使用的公車票、電影票等類似,使用者必須透過某種管道(購買或申請)取得 Ticket,之後即可利用此 Ticket 來享受某種服務。同理,金鑰中心建立伺服端的 Ticket 後,即可將 Ticket 核發給經過認證的用戶端,用戶端稍後即可利用此 Ticket 向伺服端要求服務(或是進行認證)。

假設現在網路上有用戶端與伺服端兩台電腦,以及負責金鑰中心工作的電腦 KDC。用戶端與 KDC 各自擁有一把相同的密鑰 Kclt,且伺服端與 KDC 各自擁有一把相同的密鑰 Ksrv(其他條件與一對一認證方式的前提類似,在此不再贅述)。在上述條件下,若用戶端與伺服端要相互認證,其步驟如下:

  1. 用戶端首先必須與 KDC 進行相互認證的工作,此一工作即是使用一對一的認證方式。用戶端與 KDC 在確認彼此的身份之後,用戶端即送出 Msg1 訊息給 KDC:

    Msg1:“用戶端要與伺服端進行認證”

  2. KDC 收到 Msg1 後,首先建立兩把相同的 Kclt-srv (這就是 Session Key),這兩把 Kclt-srv 稍後將會交由用戶端與伺服端,用來進行兩者之間的相互認證。接下來,KDC 從本身的安全資料庫中找出與伺服端共享的秘鑰Ksrv,再利用 Ksrv 將一把 Kclt-srv 連同用戶端的相關資訊一起加密,即產生伺服端的 Ticket。Ticket 的內容如下:

    Ticket:{用戶端相關資訊, Kclt-srv}Ksrv

    KDC 建好伺服端的 Ticket 後,以 Kclt 將剩下的一把 Kclt-srv 加密,連同建好的 Ticket 一併放入 Msg2 訊息,再傳送給用戶端:

    Msg2:{Kclt-srv}Kclt, Ticket

  3. 用戶端收到 Msg2 訊息後,利用本身所擁有的 Kclt 來解密 Msg2,取得 Msg2 中的 Kclt-srv 與 Ticket (由於 Ticket 是以 Ksrv 加密,因此用戶端無法對 Ticket 進行解密)。用戶端再利用 Kclt-srv 來建立 Authenticator:

    Authenticator:{用戶端相關資訊, 時間戳記} Kclt-srv

    然後將 Authenticator 與 Ticket 一起傳送給伺服端:

    Msg3:Authenticator, Ticket

  4. 伺服端收到 Msg3 後,首先利用本身所擁有的 Ksrv 來解密 Ticket,取得 Kclt-srv 以及用戶端相關資訊。接著再以 Kclt-srv 解開 Authenticator,再核對 Authenticator 中的時間戳記與用戶端的相關資訊。若核對無誤,伺服端則可確認 Msg3 來自用戶端 (因為只有用戶端與伺服端才會有 Kclt-srv),且此用戶端已經通過 KDC 的認證。至此,伺服端即可確認用戶端的身份。接下來,伺服端將 Authenticator 中的時間戳記以 Kclt-srv 加密後傳送給用戶端:

    Msg4:{時間戳記} Kclt-srv

  5. 用戶端收到 Msg4 訊息後,利用 Kclt-srv 解密取得其中的時間戳記,並用來比對在建立 Msg3 的時間。若兩者相符,則用戶端即可確認伺服端的身份。

    圖 2:金鑰中心的認證方式

    圖 2:金鑰中心的認證方式

以上即為金鑰中心的認證方式。整個架構看起來似乎有點複雜,但其主要的用意只有兩點:

  • 原先用戶端與伺服端之間並無共享任何秘鑰:透過上述步驟,KDC 將兩把相同的 Kclt-srv 分送給用戶端與伺服端,使兩者之間共享 Kclt-srv,以便進行相互認證(請回想一下對稱式加密法的認證方式)。在後續的作業中,用戶端與伺服端也可利用 Kclt-srv 來加密雙方之間所傳送的資料。

  • Kclt-srv 的管理完全由用戶端所負責:透過 Ticket 的機制,伺服端端只須管理一把 Ksrv,毋須保留與用戶端共享的 Kclt-srv,Kclt-srv 的管理完全由用戶端所負責。用戶端會視情況需要,將 Ticket 傳送給伺服端,以便伺服端取得 Kclt-srv。此外,由於用戶端可反覆使用 Ticket (在實作上,為了安全顧慮,會設定 Ticket 的使用期限),如此當用戶端重覆存取伺服端時,即可免去重覆向 KDC 要求認證,因而大量減輕 KDC 的工作負荷。

不過,金鑰中心的認證方式還是有如下列所述的小缺點:

  • 用戶端每次與不同的伺服端進行認證時,使用者必須重覆輸入密碼的動作。

  • 用戶端每次向金鑰中心要求某一伺服端的 Ticket 時,金鑰中心必須重覆從資料庫中找出用戶端的密碼,再以雜湊函數求出 Kclt。

Ticket-Granting Ticket

Kerberos 利用 TGT(Ticket-Granting Ticket,意思就是用來申請其他票證的票證)的機制,來解決上述的問題。TGT 可視為一種特殊的 Ticket,由金鑰中心核發給經過認證的用戶端。用戶端在後續的作業中,即可重覆利用 TGT 向金鑰中心申請其他伺服端的 Ticket。用戶端利用 TGT 向 KDC 申請 Ticket,就好比是用戶端利用 Ticket 向某一台伺服端要求服務。兩者不管在意義或實質的程序上,都沒有差別。使用 TGT 的認證程序如下:

  1. 用戶端首先與 KDC 進行相互認證的工作 (Msg1)。

  2. 認證完畢後,KDC 建立兩把相同的 Kclt-kdc (也就是用戶端與 KDC 之間的 Session Key)。KDC 利用一把 KDC 專屬的秘鑰 Kkdc,將一把 Kclt-kdc 連同用戶端的相關資訊一起加密,即產生 TGT:

    TGT:{用戶端相關資訊, Kclt-kdc}Kkdc

    KDC 建好 TGT 後,再以 Kclt 加密剩下的一把 Kclt-kdc,連同 TGT 一併放入 Msg2 訊息,並傳送給用戶端。之後,KDC 即可摧毀步驟 1 在 KDC 端利用密碼與雜湊函數所建立的 Kclt。

    Msg2:{Kclt-kdc}Kclt, TGT

  3. 用戶端收到 Msg2 訊息後,利用本身所擁有的 Kclt 來解密 Msg2,取得 Msg2 中的 Kclt-kdc 與 TGT (由於 TGT 是以 Kkdc 加密,因此用戶端無法對 TGT 進行解密)。用戶端會小心保管 Kclt-kdc 與 TGT,供後續作業使用,並摧毀步驟1在用戶端端利用密碼與雜湊函數所建立的 Kclt。

  4. 當用戶端需要與伺服端進行認證時,用戶端利用 Kclt-kdc 來建立 Authenticator,連同 TGT 一起傳送給 KDC:

    Msg3:Authenticator, TGT

  5. KDC 利用其專屬的 Kkdc 將 TGT 解密,取得 Kclt-kdc。然後再用 Kclt-kdc 來解密 Authenticator,並確認用戶端的身份。KDC 接下來便建立兩把相同的 Kclt-srv (也就是用戶端與伺服端之間的 Session Key),將一把 Kclt-srv 以 Kclt-kdc 加密,另一把 Kclt-srv 以 Ksrv 加密 (伺服端的 Ticket),再一起送回給用戶端。後續的步驟與金鑰中心的認證方式相同。

圖 3:使用 TGT 的步驟

圖 3:使用 TGT 的步驟

使用 TGT 的好處在於用戶端可反覆使用 TGT (當然,TGT 實際上也會設定使用期限),因此使用者便不需要頻頻輸入密碼,而 KDC 端也不用經常執行 Kclt 的建立動作。在實作上,一般是在用戶端每次作業開始時(例如,每天早上開機登入),KDC 即核發 TGT 給用戶端。用戶端在該次作業中,皆可使用同一張 TGT 向 KDC 要求其他伺服端的 Ticket。

跨轄區的認證方式

由先前的定義可知,每個金鑰中心有其管轄的轄區 (Realm),金鑰中心保有轄區內所有主體(包括全部的用戶端與伺服端)的秘鑰。假設現在有兩台 KDC,KDC-x 管轄 Realm-x,KDC-y 管轄 Realm-y,且 KDC-x 與 KDC-y 相互信任,也就是說 KDC-x 與 KDC-y 各自擁有一把相同的金鑰 Kx-y。當 Realm-x 中的用戶端欲存取 Realm-y 的伺服端時,則必須進行跨轄區的認證程序。以下為認證的步驟:

  1. 用戶端首先與 KDC-x 進行相互認證的工作,並取得 KDC-x 所核發的 TGT-x 以及 Kclt-x (用戶端與 KDC-x 之間的 Session Key)。

  2. 用戶端以 TGT-x 向 KDC-x 要求伺服端的 Ticket(Msg1)。KDC-x 檢視本身的安全資料庫,得知伺服端位於 KDC-y 所管轄的 Realm-y 轄區內,因此 KDC-x 準備建立 Referral Ticket (轉介票證)。Referral Ticket 的功能就好比是推薦函或介紹信。例如,A 與 B 互相認識,B 與 C 互相認識,但 A 與 C 互不相識。當 A 要與 C 建立關係時,A 會先向 B 取得介紹信,然後再拿著介紹信去見 C,以便取得 C 的信任。Referral Ticket 的功能也是如此,讓素未謀面的用戶端與 KDC-y 得以進行認證的工作。

  3. KDC-x 首先建立兩把相同的 Kclt-y (用戶端與 KDC-y 之間的 Session Key)。KDC-x 再利用與 KDC-y 共享的秘鑰 Kx-y 將一把 Kclt-y 連同用戶端的相關資訊一起加密,產生 Ticket-ref:

    Ticket-ref:{用戶端相關資訊, Kclt-y}Kx-y

    KDC-x 建好 Ticket-ref 後,再以 Kclt-x 加密剩下的一把 Kclt-y,連同 Tikcet-ref 一併傳送給用戶端:

    Msg2:{Kclt-y}Kclt-x, Ticket-ref

  4. 用戶端解開上列訊息,取得 Kclt-y 與 Ticket-ref,然後利用這兩者直接向 KDC-y 要求伺服端的 Ticket。後續的步驟與使用 TGT 向 KDC 申請 Ticket 的步驟相同。

    圖 4:跨轄區的認證方式

    圖 4:跨轄區的認證方式

使用跨轄區的認證機制有幾個優點:

  • 整個網路可分割成較易管理的小單位(Realm),各單位自行管理所轄的秘鑰,單位之間再以信任關係(也就是兩台 KDC 共享秘鑰)串連起來。

  • 用戶端可透過多台 KDC,與位於其他 Realm 的伺服端進行證認。

Kerberos 的基本協定

在 RFC 1510 中,詳細定義了 Kerberos 的數個基本協定。接下來便要介紹 Kerberos 的三個最重要的協定。透過這些協定,以及協定中所定義的訊息,即可執行之前所提及的 Kerberos 認證功能。

AS Exchange

AS (Authentication Service,認證服務) 主要負責讓 KDC 核發 TGT 與 Session Key (用戶端與 KDC 之間的 Session Key) 給用戶端。AS 主要有兩個訊息:

  • KRB_AS_REQ:這是用戶端在一開始登入時向 KDC 發出的認證要求,訊息內容包括了一些明文資訊與 Authenticator (以用戶端秘鑰來加密)。

  • KRB_AS_REP:KDC 確認用戶端的身份後,將 Kclt-kdc(用戶端與 KDC 之間的 Session Key) 與 TGT 傳送給用戶端。

TGS Exchange

TGS (Ticket-Granting Service,取票服務) 主要負責讓 KDC 核發伺服端的 Ticket 與 Session Key (用戶端與伺服端之間的 Session Key)。TGS 主要有兩個訊息:

  • KRB_TGS_REQ:用戶端利用 Kclt-kdc (用戶端與 KDC 之間的 Session Key) 與 TGT 向 KDC 要求伺服端的 Ticket。

  • KRB_TGS_REP:KDC 確認用戶端的身份後,將 Kclt-srv (用戶端與伺服端之間的 Session Key) 與伺服端的 Ticket 傳送給用戶端。

CS Exchange

CS (用戶端/伺服端) 主要負責讓用戶端與伺服端進行相互認證。

  • KRB_AP_REQ:用戶端利用 Kclt-srv 來建立 Authenticator。然後再利用 Authenticator 與 Ticket 向伺服端要求認證。

  • KRB_AP_REP:伺服端確認用戶端的身份後,以 Kclt-srv 加密 Authenticator 中的時間戳記資訊,然後送回給用戶端,供用戶端確認伺服端的身份。

從這三項協定中,我們可以知道 KDC 負責 AS 與 TGS 這兩項工作。其實,在原先 Kerberos 的架構中,AS 與 TGS 各自獨立,可由不同的電腦來提供 AS 與 TGS 的服務。不過,在實作上 AS 與 TGS 通常會放在一起,而構成所謂的金鑰中心(KDC)。

結論

Kerberos 整個架構雖然複雜,但卻是是相當完善的認證協定。與 Windows NT 4.0 的 NTLM 相比,Windows Server System 的認證架構顯然大有進步,尤其 Kerberos 具有相互認證的功能,並且具備代理認證的功能,更重要的是,Kerberos 是通用的標準,因此提高了 Windows Server System 與其他系統的相容性。

參考資料

  • The Kerberos Network Authentication Service (V5) / RFC 1510 Sep. 1993 / Kohl & Neuman

  • Designing an Authentication System:a Dialogue in Four Scenes / Massachusetts Institute of Technology / Bill Bryant

  • Exploring Kerberos, the Protocol for Distributed Security in Windows 2000 / Microsoft System Journal Aug. 1999 / David Chappell

  • Cryptography and Network Security / Prentice Hall 1999 / William Stallings