認證系統設計經典會話

来源:https://www.cnblogs.com/gaofeng-henu/archive/2020/05/16/12899392.html

Bill Bryant,首次寫與1988年2月 Theodore Ts'o與1997年2月整理並轉換成HTML,並且追加了 afterword 章節來描述V5版本的一些變化 前言 本文虛構了一個關於公網認證系統 Charon構建過程的對話,隨著對話的進行,Athena和Euripides探討了公共網 ...


Bill Bryant,首次寫與1988年2月
Theodore Ts'o與1997年2月整理並轉換成HTML,並且追加了 afterword 章節來描述V5版本的一些變化

前言

本文虛構了一個關於公網認證系統--Charon構建過程的對話,隨著對話的進行,Athena和Euripides探討了公共網路環境里普遍存在安全問題,併在Charon系統設計之初就考慮好了這些問題的解決方式。所以直到對話完成,Athena和Euripides才算真正的把系統設計好。

當系統設計好後,Athena把系統的名字從Charon改成了Kerberos。非常巧合的是,在MIT的一個項目--Athena中,設計和實現的認證系統名稱就叫做Kerberos。

對話中的“Kerberos”與1988年發表的“Kerberos:一個公共網路的認證系統“有著驚人的相似之處。

Scene I

在一個小隔間里,Athena和Euripides正在兩個相鄰的終端上工作

Athena:Rip,你們這個分時共用系統就是個累贅。因為其他人都登陸著,它慢的使我根本沒法成我的工作。

Euripides:這個不要向我抱怨,我只是個打工的。

Athena:難道你不知道我們的需求嗎?我們真正想要的是給每個人一個自己的工作站,之後再用網路鏈接所有的工作站,從而使大家能相互通信,這樣他們就不用擔心共用計算周期的問題。

Euripides:那麼我們需要多少工作站呢,1000個?

Athena:差不多

Euripides:哪你有沒有調研過普通工作站的磁碟,一般來講是沒有足夠的空間來安裝你在共用機器上所有的軟體的?

Athena:這個我已經想好了,我們可以把所需的軟體裝在不同的伺服器上,當你登陸到自己的工作站後,你可以通過網路向這些伺服器發請求來使用那些軟體服務。這樣還能使所有的工作站都使用相同的軟體版本,軟體升級也會很便捷,只用把伺服器上的軟體升級就可以了,不用到每個工作站上面去操作。

Euripides:好吧,但是你怎麼管理個人文件呢?在分時共用系統中,我可以通過任意一個和系統連接的終端登陸並訪問我自己的文件。你這樣設計後,我是否能通過任意工作站來獲取我的個人文件,還是說我要隨身帶個軟盤來保存我自己的文件呢?

Athena:我想我們可以用另外一臺伺服器來存儲私有文件,這樣你就可以登陸任意的工作站來獲取你自己的文件。

Euripides:那列印功能怎麼辦,難道讓每個工作站都要有自己的印表機嗎?你用誰的錢來買這些設備呢?還有電子郵件怎麼處理,怎麼把郵件分發到所有的工作站上呢?

Athena:嗯…,很明顯,我們沒有錢給每個工作站配置一臺印表機,但是我們可以用一臺機器專門用來做列印服務。你把你的列印任務發給列印服務機,由它來幫你列印。你也可以用同樣的思路來處理電子郵件,由一臺機器專門做郵件服務,如果你想要你的郵件,你連接這個服務,由他來把你的郵件挑揀出來。

Euripides:你的工作站系統聽起來是很好。當我有了自己的工作站,你知道我會做什麼嗎,我會找出你的名字,並使我的工作站認為我是你,這樣我就可以連接到郵件服務獲取你的郵件,我還可以連上文件伺服器來刪除你的文件,我還可以…

Athena:你真的會這樣做嗎?

Euripides:是的,那些服務怎麼能知道現在是我在操作而不是你呢?

Athena:呃,我不知道,我需要好好想想這個問題。

Euripides:聽起來是的。如果你知道怎麼做了請一定告訴我。

Scene II

第二天早上,在Euripides 的辦公室,Euripides正在他的辦公桌前讀他的點子郵件,Athena敲門進來

Athena:哈哈,我已經找到一種方式來加密網路環境,從而阻止像你這樣調皮的家伙不能偽裝成別人來使用那些服務。

Euripides:真的嗎,坐下來講吧。

Athena:在我開始之前,我能不能給我們的討論定下一個基本準則?

Euripides:什麼準則?

Athena:假如我說了下麵的話:“我想看我的電子郵件,所以我連接上郵件服務,告訴郵件服務把郵件發到我的工作站。”實際上,並不是我直接連接郵件服務,而是我使用了一個程式去連接郵件服務,一個稱作郵件服務客戶端的程式。
但是當我每次描述用戶和服務交互時,我不會說“客戶端做了什麼“,而是會說“我做了什麼”,所以請記住是客戶端作為我的代理做了這些事。我這樣講有沒有問題?

Euripides:沒有問題。

Athena:針對網路安全問題,最笨的方式是每次郵件服務都讓用戶提供密碼來證明用戶身份。

Euripides:這的確是夠笨的。在這樣一個系統中,需要每一個服務都知道你的密碼。如果網路裡面有一千個用戶,每個服務都要有一千個用戶的密碼;當你想要修改密碼時,你還得聯繫所有的服務去一個個修改。我想你的系統不會這麼笨吧。

Athena:我的系統不笨。他像這樣工作:不僅僅是用戶有密碼,服務也有密碼。每個用戶知道自己的密碼,每個服務也知道自己的密碼,並且還有一個認證服務知到所有的密碼,包括用戶的和服務的。認證服務把這些密碼存儲在一個中央倉庫中。

Euripides:你有給這個認證服務起好名字嗎?

Athena:我還沒有想好,你有什麼想法嗎?

Euripides:那個幫助死者過冥河的擺渡人名字怎麼樣?

Athena:Charon嗎?

Euripides:是的,就是他,除非你證明你的真實身份,否則他是不會擺渡你的。

Athena:Rip,你又來這一套,重新杜撰羅馬神話。Charon並不關係你的身份,他只確保你已經死掉就夠了。

Euripides:哪你有沒有一個更好的名字?

Athena:沒,還沒有。

Euripides:那就把這個認證服務叫“Charon ”吧。

Athena:好吧,那我就開始描述這個系統了。

我們假定你現在要用郵件服務。在這個系統里,你不能直接使用一個服務,除非Charon告訴那個服務你就是你所聲明的那個人。並且除非你先向Charon認證,否則你也不能獲取到那個服務。當你向Charon認證時,你同時得告訴Charon你想使用哪一個服務,就是說如果你想用郵件服務,你得明確告訴Charon。

接著,Charon要求你提供認證信息。你向Charon提供你的密碼,然後Charon和註冊在中央資料庫中的密碼進行對比,如果密碼時匹配的,Charon認為你證實了你的身份。

接下來,Charon要告訴郵件服務你就是你所聲明的那個人。因為Charon知道所有服務的密碼,當然也包括郵件服務的。很明顯Charon可以告訴你郵件服務的密碼,當你向郵件服務發起請求時你可以用這個密碼證明你已經向Charon認證過了。

現在的問題是,Charon不能直接給你密碼,因為你知道這個密碼後,下一次你想訪問郵件服務,你就可以繞過Charon不用再認證了,之後你仍可以偽裝別人,用別人的名字來訪問郵件服務獲取他的郵件了。

所以,Charon會給你一個郵件服務的票據(TICKET)而不是直接給你密碼。這個票據裡面包含了你的名字,並且會利用郵件服務的密碼進行加密。

TICKET = {username} K_server

  • {X}K_Y 表示 用K_Y對X進行加密。

拿到票據後,你現在可以向郵件服務請求你的郵件了,你告訴郵件服務你的名字,同時把票據發給郵件服務來證明你的身份。

郵件服務拿到票據後,首先用自己的密碼進行解碼,如果能正常解碼,郵件服務就能拿到Charon存放在票據中的名字。

郵件服務再用票據中的名字和你提供的名字進行對比,如果名字一致,郵件服務就認為你是你所聲明的人,就把你的郵件給你。

你覺得這個方法怎樣?

Euripides:我有幾個問題。

Athena:預料之中,你繼續講。

Euripides:當一個服務解碼一個票據,他如何判斷自己正確解碼了(這個票據是針對自己這個服務的,而不是用戶申請訪問別的服務對應的票據)?

Athena:這個我還沒考慮好。

Euripides:最好能把服務的名字也放到票據中。這樣當一個服務解碼票據後,他可以通過能不能在票據中正確找到自己的名字來判斷解碼是否成功。

Athena:聽起來不錯,那麼現在票據就變成了這樣

TICKET - {username: servicename} K_server

Euripides:這樣票據就包含用戶名和服務名。

Athena:再用服務的密碼進行加密。

Euripides:可是我還是不認為這些信息就能保證票據的安全性。

Athena:舉個例子呢。

Euripides:比如說,你向Charon要了一個郵件服務的票據。Charon準備好了票據,並把你的名字“tina”放了進去。假定在Charon通過網路把票據發給你的過程中我把這個票據複製了一份,然後我欺騙我的工作站說我就是tina,這樣工作在我工作站的郵件客戶端程式就會認為我就是你。利用你的名字,郵件客戶端再利用偷來的票據向郵件服務發請求。這樣郵件服務收到請求後解碼了票據,並會驗證通過,郵件服務就會把你的服務發給我。

Athena:嗯,是的,這個設計還是不完美。

Euripides:但是我知道一種方式來修複這個問題,或者說局部解決這個問題。我認為Charon需要在票據中包含更多的信息。除了用戶名,Charon還需要把用戶請求票據時的網路地址包含進去,這樣就可以多一個安全保證。

我用下麵的過程來證明:假如說我現在偷取了你的票據,這個票據裡面有你工作站的地址,這個地址和我工作站的地址是不一樣的。當我偽造你的名字和偷來的票據請求郵件服務時,郵件服務從票據中解碼出名字和地址並和請求中的用戶名和地址進行匹配,雖然用戶名匹配成功了,但是地址不匹配,很明顯這個票據被偷了,伺服器就拒絕這次請求。

Athena:太好了,我希望我也能想到這樣的方法。

Euripides:哈,這就是我的目的。

Athena:那麼修改後的票據就變成了

TICKET = {username:ws_address:servicename} K_server

Athena:我現在好興奮,讓我構建一個Charon系統來看看他是否能工作吧。

Euripides:還不能這麼快,我對這個系統還有幾個疑問。

Athena:好吧,繼續。

Euripides:目前來看,每次只要我想訪問一次服務,我都得獲取一個票據。如果我一整天都在工作,我肯定會多次要獲取我的郵件信息。如果每次訪問服務都得獲取一個票據,那我是不會喜歡這個系統的。
Athena:呃…,為什麼票據不能重覆使用呢,當你獲取一個票據後,你是可以重覆使用的。比方說,當郵件客戶端程式向服務請求時,他把票據複製一份,把這個副本發送到服務端。

Euripides:聽起來不錯,但是還是有問題。目前來看,當我要訪問一個我還沒有票據的服務時,我都得向Charon提供我的密碼。例如我想訪問我的文件,我得向Charon提供我的密碼來獲取一個票據,當我想向郵件服務獲取我的郵件時我還得向Charon提供我的密碼,假如我又想列印些什麼東西,我又得訪問Charon,你能想象到那個畫面的。

Athena:呃,是的。

Euripides:這還不是最糟的,目前你向Charon認證時,你以明文的形式在網路上傳播你的密碼。那些像你這樣聰明的人肯定可以通過模擬網路來偷取別人的密碼,如果我有了你的密碼,我又可以以你的名義使用任意服務。

Athena:這些都是嚴重的問題,我需要重新設計一下。

Scene III

隔天早上,Athena在咖啡間遇見了Euripides,併在他的接滿水後,把手搭在了他的肩膀上,一起向咖啡機走去

Athena:我想了一個新版本的Charon可以解決我們的問題。

Euripides:真的嗎,這麼快?

Athena:嗯,這個問題讓我想了一晚上。

Euripides:這一定是你的負罪感,讓我們找個小隔間再討論討論吧?

Athena:為什麼不呢?

兩人走向一個小隔間

Athena:作為開始部分,我會重新陳述一下我們的問題,看看我們的系統是不是真的需要這些功能。

Athena:第一個需求:用戶只用在他們登陸進工作站的時候輸入他們的密碼一次。這個需求指的是你不用在每次獲取其他服務的票據時都要輸入密碼。第二個需求:密碼不能以明文的形式在網路上傳播。

Euripides:是的

Athena:對於第一個需求:你只需要輸入一次你的密碼,為了滿足這個需求,我會引入一個新的服務,一個叫做“票據分發”(ticket-granting)服務,當用戶向Charon認證完成後,這個服務就會向這個用戶分發票據。如果你有這個票據分發服務的票據(TGT),你就可以使用這個票據分發服務。
票據分發服務可以簡單當作是Charon的一個變體,他也能訪問中央資料庫。Charon中的這個票據分發服務可以讓你用票據代替密碼來認證。

現在,認證系統將這樣工作:你登陸到你的工作站,然後利用Kinit這個程式來連接Charon服務,之後你向Charon提供憑據,Kinit從Charon服務獲取你對應的TGT。

假如現在你想要訪問郵件服務,而你還沒有郵件服務的票據,你就可以用TGT向Charon來獲取郵件服務的票據,而不是使用密碼來獲取這個票據。

Euripides:那我需要訪問其他服務時要不要每次都得獲取一個新的TGT呢?

Athena:不用,記不記得上次我們達成的共識,票據是可以重覆使用的。一旦你有一個TGT,你不需要再獲取一個,之後你就可以重覆使用這個TGT來獲取其他服務的票據。

Euripides:嗯,很有道理。因為你可以重覆使用票據,所以一旦票據分發服務給你一個針對特定服務的票據(ST),就不需要再獲取這票據了。

Athena:是的,這樣是不是比較簡潔。

Euripides:嗯,到目前為止還行,只要在獲取TGT時不通過明文在網路上傳輸我的密碼。

Athena:就像我說的,我這問題我也解決了。事實上,當向Charon請求TGT時,我表述的好像是我要通過網路發送你的密碼,但這並不是必須的。

真實情況是,當用Kinit程式向Charon獲取TGT時,kinit並不向Charon服務發送密碼,kinit只發送你的名字。

Euripides:好

Athena:Charon服務利用你的名字來查找你的密碼,接著Charon構造一個包含TGT的數據包,在Charon把這個數據包發給你之前,他會用你的密碼對數據包進行加密。

你的工作站收到這個數據包後,提示你輸入密碼,kinit會嘗試用你輸入的密碼來解碼這個數據包,如果解碼成功,預示著你認證成功,並且你會擁有TGT,然後你可以用這個票據來獲取你想要服務的票據。

這個是不是你所想要的?

Euripides:我還不清楚,我需要再考慮考慮。我認為你剛纔描述的那部分系統功能工作的相當好,它只需要我認證一次,此後Charon會自動的為我分發其他服務的票據也不用我再關心。但是關於票據的設計我還是有困惑,因為基於一個前提,那就是票據是可重覆用的,我同意票據可以重覆使用,但是可重覆用本質上講是危險的。

Athena:具體來說呢

Euripides:打比方來說,假如你使用了一個不安全的工作站,期間你獲取了郵件服務的票據、列印服務的、文件服務的,然後你退出了工作站。

現在假定我也登陸到了這個工作站,並且找到了這些票據。我呢,又比較喜歡製造麻煩,所以我把我的名字改成你的來欺騙工作站說我就是你,因為那些票據都是用你的名字生成的,所以我可以用郵件客戶端來獲取你的郵件,也能獲取你的文件,也能用你的賬號發送成千上萬的列印任務,所有的這一切都是因為你把票據忘在了這個工作站上。

並且也沒有什麼方法能阻止我把這些票據再複製下來,這樣我就可以一直使用它們了。

Athena:這個很好解決呀,我們可以寫一段程式在用戶登出時銷毀用戶的票據,這樣你就不能使用了。

Euripides:好吧,很明顯你的系統需要一個銷毀程式,但是讓用戶依賴於這樣一個程式是愚蠢的。你不能確保用戶在每一次使用完工作站登出時都執行這個銷毀程式,即便你依賴於用戶執行銷毀程式,在下麵的場景下也有問題

我寫了一個程式,它可以監聽網路,當有服務票據從網路上傳播時我就把它複製下來。假如我想陷害你,當你登陸進工作站時,我也把這個程式打開,從而能copy你的票據。

當你完成工作退出工作站並離開後,我把我的工作站地址篡改成你的地址,更改用戶名使我的工作站相信我就是你,這樣我就有了你的票據,你的名字,你的地址,我又可以以你的名義重新使用這些票據。

即便是你在登出時銷毀了你的票據也沒有關係,因為我偷的這些票據只要我想用就會一直有效,而這都是因為你現在的票據設計裡面並沒有對票據的使用次數或者使用時間做限制。

Athena:哦,我知道你所說的了,票據永久有效是一個大的安全隱患。我們必須限制一個票據可用的最大時長,也許我們可以給每個票據一些過期信息。

Euripides:實際上,我認為每個票據都得追加下麵的信息:一個有效期(lifespan)欄位,表明這個票據的最大有效時間;還有一個時間戳(timestamp)欄位,表明Charon創建這個票據的時間。所以現在票據信息就變成了

TICKET = {username:ws_address:servicename:lifespan:timestamp} K_server

Euripides:現在當一個服務解碼票據之後,首先檢查下票據裡面的用戶名和地址和用戶發過來的是否一致,接著再用有效期和時間戳欄位判斷這個票據是否過期。

Athena:很好,那這個有效期設置多久比較好呢?

Euripides:我也不清楚,設置成大多數工作站的會話時長怎麼樣,即8小時?

Athena:這也就是說,如果我在我的工作站工作超過8小時,我所有的票據都將失效,也包括票據分發票據,所以在8小時後,我必須再次向Charon認證。

Euripides:這個也不是難以接受的吧?

Athena:嗯,也是。那我們就定下來票據在8小時後過期。現在我有一個新的疑問了,假如我從網路上複製了你的票據..

Euripides:哦,Tina,你不會真的這樣做吧,對不對。

Athena:這隻是我們交談的一種假設情況。現在我複製了你的票據,並等著你退出你的工作站。可能是你和醫生有一個約談或者是要參加一個會議,所以你在兩個小時左右就退出了你的工作站。雖然你比較謹慎的在推出時銷毀了你的票據,但是我已經偷取了這些票據,並且在接下來的6個小時裡面它們是完好可用的,我將有足夠的時間來操作你的文件,以你的名義發送成千上萬的列印任務。

所以說,追加有效期和時間戳的方式對於票據過期後的攻擊是起作用的,但是如果在票據過期前攻擊那。。

Euripides:哦,是的,你是對的。

Athena:我想我們找到核心問題了。

Euripides:我猜你今天晚上又要忙活了,要去喝些咖啡嗎?

Athena:要的,走

Scene IV

隔天早上,在Euripides的辦公室,Athena敲門進來

Euripides:Tina,一大早就戴著個黑眼圈呀。

Athena:是啊,你知道又一個漫漫長夜。

Euripides:你找到解決問題的方法了嗎?

Athena:我想我找到了。

Euripides:坐下來慢慢說。

Athena:按慣例,首先我要重述下這個問題:票據都有一個有效期-8小時,如果在過期前其他人偷走了你的票據,那我們就沒有辦法阻止他了。

Euripides:正是這個問題

Athena:如果我們把票據設計成不可重覆使用,那我們可以修複這個問題

Euripides:但是這樣你就不得不在每次想要利用一個網路服務的時候都去請求一個票據了

Athena:是的,這算是一種粗暴的解決方案。哦,我該怎麼繼續我的論述呢?
好吧,讓我們從需求的角度再把問題重述一下:一個服務必須要證明現在用票據發起請求的人就是Charon分給票據的那個人。

讓我們再把認證過程推演一遍,看我能否想出一個合適的方法來表述我的解決方案。

當我想訪問一個特定的服務時,第一步,我在我的工作站上啟動一個客戶端程式,這個客戶端發送三個信息給服務,我的名稱、地址、以及相應的票據。其中票據中包含認證時的用戶名,認證時工作站對應的網路地址,還包含了票據的過期信息。所有這些信息在返回給客戶端時Charon都用對應服務的密碼進行了加密。

我們現在的認證模式基於下麵的測試:

  • 服務能否解碼對應的票據
  • 票據是否過期
  • 票據中的用戶名和網路地址是否和票據一起發送的用戶名和地址匹配

這些測試能證明什麼呢?

第一,這個票據是否是Charon分發的,如果票據不能正確解碼,那就不是從真正的Charon過來的。真正的Charon會使用服務對應的密碼加密,而只有Charon和服務知道這個服務的密碼。如果票據能正常解碼器,那服務就能確定票據是從真正的Charon過來的的,這樣就能防止攻擊者偽造Charon分發票據。

第二,這個票據是否過期,如果過期,服務端就拒絕這個請求,這樣能阻止攻擊者使用舊的票據,因為這些票據很有可能被偷走了。

第三,檢查票據中的用戶名和網路地址,如果檢查失敗,說明用戶在使用別人的票據(可能是偷偷在用),服務端肯定要拒絕這樣的請求。

如果用戶名和地址匹配上,那證明瞭什麼呢?什麼也沒有,攻擊者可以從網路上偷走票據,更改他的工作站地址和用戶名,從而偷竊別人的資源。就像我昨天說的,票據在過期之前是可以無限制的重用的。它們能被重用是因為服務端沒辦法區分現在請求的用戶是否是票據真正的擁有者。

服務端不能做區分是因為他和用戶之間沒有一個共用的機密信息。打比方來說,我在Elsinore(哈姆雷特裡面的城堡)站崗,現在你要來換下我,除非你告訴我正確的暗號,否則我是不會同意你替換我的,這就是我們兩個之間需要共用一個機密的例子,這個機密可能是某個人為所有的站崗者想出的暗號。
這就是我昨天晚上想的,為什麼不能讓Charon為票據真正的擁有者和服務生成一個共用的密碼呢?Charon把這個會話密鑰(session key 就是剛說的共用密碼)的一份拷貝發給服務端,再把另一份拷貝發給用戶,當服務端收到用戶的請求時,他可以用這個會話密鑰來驗證用戶。

Euripides:等一下,Charon怎麼給服務端和用戶發送這個密鑰呢?

Athena:Charon把會話密鑰作為返回值的一部分,像這樣:

CHARON REPLY = {sessionkey|ticket} K_user

服務端通過解碼票據來獲取會話密鑰,所以現在票據變成瞭如下的樣子

TICKET = {sessionkey:username:address:servicename:lifespan:timestamp}K_server

現在當你想要訪問一個服務時,你使用的客戶端程式會構建一個我們稱之為“認證對象”(AUTHENTICATOR),這個認證對象中包含你的用戶名和你工作站的網路地址。客戶端用Charon返回的會話密鑰對認證對象進行加密,就是他向Charon認證時對應的會話密鑰。

AUTHENTICATOR - {username:address} K_session

客戶端構造好認證對象後,和票據一起發送到服務端,這時服務端還不能解碼這個認證對象,因為他還沒有拿到回話密鑰,密鑰存放在票據中,所以第一步服務端必須先解碼票據

服務端解碼票據後將獲取下麵的信息:

  • 票據有效時間和創建時間
  • 票據擁有者的名字
  • 票據擁有者對應的網路地址
  • 會話密鑰

服務端先檢查票據是否過期,如果是好的,接著,服務端用會話密鑰解碼對應的認證對象,如果能順利解碼,服務端就會獲取到用戶名和網路地址,然後服務端把獲取到的用戶名和網路地址和票據中的對應信息比較,並且再和發送票據、認證對象時一起發送過來的用戶名和網路地址比較,如果一切都對比正確,則服務端就可以確認現在發送票據的人確實是票據的擁有者

我認為會話密鑰-認證對象能解決票據重用帶來的問題

Euripides:可能吧,我還是有困惑,要想用這個方式,我必須構建服務相應的認證對象

Athena:不,你不僅要有認證對象,還要有正確的票據。如果沒有票據只有認證對象是沒有任何意義的,因為沒有解碼票據前你是獲取不到會話密鑰的,而沒有會話密鑰你就沒法解碼認證對象。

Euripides:這個我知道,但是你也說了,當一個客戶端程式請求服務端時,他會把認證對象和票據一起發送過去

Athena:是的,我這樣說過

Euripides:如果真是這樣,那怎麼阻止我把認證對象和票據同時偷走呢?我可以確定通過程式我能做到這個。如果我能同時偷取到認證對象和票據,這樣在票據過期前我就可以用這兩個信息,改變我工作站的地址和用戶名來偽裝請求了,是不是?

Athena:是的,好失望

Euripides:等等,這沒什麼大不了的。票據在過期之前可以重覆使用,但這並不預示著認證對象也可以重覆使用。假如我們設計一個方案只允許認證對象使用一次,是不是就沒有問題了

Athena:是的,很有可能。我們再討論一下這個過程,客戶端程式構建了一個認證對象,然後把它和票據一起發送給服務端。你把票據和認證對象都複製一份偷走了,但是這個票據和認證對象在你能發給服務端之前已經到達了服務端。如果認證對象只能夠使用一次,那你複製下來的票據和認證對象就不起效了,當你嘗試認證時就會失敗

好了,總算放心了,所以現在需要做的事是用一種方式保證認證對象只能使用一次

Euripides:沒有問題,讓我們在認證對象裡面也存放一個有效期和生成時間。假如每一個認證對象的有效期只有幾分鐘。當你想使用一個服務時,你的客戶端程式構建一個認證對象,添加上當前的時間戳,接著把它發送到服務端。

服務端收到票據和認證對象後,先解碼票據獲取會話密鑰,然後用會話密鑰解碼認證對象,接著檢查認證對象是否過期,如果沒有,並且其他的檢查都通過,服務端通過認證。

假如現在我複製了你的票據和認證對象,為了使用它們,我需要在幾分鐘內修改好我的工作站網路和用戶名,這個要求是很高的,我不認為能做到,除非…

好吧,還有一個潛在的風險,假如我不是在當你向服務端認證時複製票據和認證對象,而是複製Charon發給你的原始數據包,就是你向Charon要票據時它返回給你的數據包

這個數據包,包含了兩份會話密鑰在裡面,一個給你,一個給服務端。給服務端的在票據裡面,我不能拿到,但是另一個呢,那個你用來生成認證對象的密鑰呢

如果我能拿到這個密鑰,我就可以構建自己的認證對象,這樣我就可以攻破這個系統

Athena:這個我昨晚上也想到過,但是我推演了一下獲取票據的過程,發現以這種方式偷取認證對象是不可能的。

你坐在你的工作站前,用kinit程式獲取你的票據分發票據(TGT),kinit需要你的名字,你輸入後,kinit把它發送到Charon。

Charon用你的名字到資料庫中查詢你的密碼,接著創建一個TGT。作為這個過程的一部分,Charon創建一個你和票據分發服務共用的會話密鑰。Charon把這個密鑰的一份拷貝放到TGT中,把另一個拷貝放到數據包中,在把這個數據包發送給你之前,Charon會用你的密碼把它加密。

CHARON REPLY = [sessionkey|TGT] K_user

Charon通過網路把加密後的數據發給你,如果有人偷取了這個數據包,沒有你的密碼他沒法解碼這個數據包,也就不能獲取到會話密鑰。

Kinit獲取到這個數據包之後,提示你輸入密碼,如果你輸入了正確的密碼,Kinit就會解碼這個數據包,給你對應的會話密鑰。

客戶端為票據分發請求創建一個認證對象,並使用會話密鑰對認證對象加密,接著客戶端把這個加密後的認證對象發送給Charon,同時把TGT,你的名字,工作站的網路地址還有你要訪問的-郵件服務的名稱一起發過去,

票據分發服務(TGS)收到這些信息,(其中TGT和普通的ST,也沒有區別,它就是票據分發服務對應的票據-ST,裡面也是包含了{sessionkey:username:address:servicename:lifespan:timestamp}這些信息,只不過服務名字就是固定的TGS的名字,並用票據分發服務對應的密碼進行了加密),就開始正常的認證檢查,(也是先用自己的密碼解碼TGT,看是否過期,再用裡面的會話密鑰解碼認證對象,驗證用戶名,地址)如果檢查通過,票據分發服務(TGS)就會拿到一個正確的會話密鑰,接著票據分發服務為你構建一個郵件服務的票據,併為你和郵件服務創建一個新的共用的會話密鑰。

接下來,票據分發服務會準備一個發往你工作站的票據數據包,這個數據包中包含了剛創建的郵件服務的票據和新建的你和郵件服務共用的會話密鑰,在發送數據包之前,票據分發服務會用你和票據分發服務之間共用的會話密鑰把數據包加密。

現在看下郵件服務的票據包的發送,假如有人在這個數據包在網路上傳輸的工程中複製了一份,由於數據包用數據分發服務的會話密鑰加密過,他也得不到裡面的內容,因而不能得到在數據包中的郵件服務的會話密鑰,沒有這個密鑰,他就不能創建認證對象,從而也不能使用TGS生成的並通過網路傳輸的郵件服務票據。

所以現在來看,我們安全了,你認為呢?

Euripides:可能吧

Athena:可能,你就只能說個這嗎

Euripides:別生氣,這隻是對我自己刻薄的說法,你為這個都搞了大半夜了

Athena:Pthhhhh!

Euripides:好吧,是3/4個晚上,現在,這個系統聽起來可以接受了,會話密鑰的方式解決了昨晚上我思考的一個問題,一個雙向認證的問題,介意我再說幾分鐘嗎?

Athena:當然

Euripides:你真和善。昨晚上當會話密鑰和認證對象跳入的大腦時,我嘗試著找到系統的新問題,最後還真找到了一個嚴重問題,接下來我會用一個例子慢慢說明它:

假如說你厭倦了你現在的工作,並且也找到了新的感興趣的想跳槽過去。你想在公司的印表機上列印你的簡歷,使獵頭或者潛在的雇主能註意到你的優點。

所以你點擊了列印功能,直接把你的簡歷發送給相應的印表機。如果你還沒有列印服務的票據,列印客戶端首先會獲取列印服務的票據,再以你的名義把票據發送給服務端,至少在你認為它是按照這樣的流程來工作的,你並不知道這個任務是否發給了正確的印表機。

假如現在有一些惡意的黑客--你的老闆--有一個轉換系統,利用這個系統,它能把你的請求和票據重定向到他辦公室的印表機上。如果他的這個印表機服務設計的不關心對應的票據和內容,它直接忽略掉票據,並返回給你的工作站一個信息說票據通過驗證,服務端也準備好為你提供列印服務了。你的列印客戶端發送列印命令給這個偽裝的印表機,這樣你的敵人就拿到了你的簡歷。

我用對比的方式重述下這個問題,就是在沒有會話密鑰和認證對象的時候,Charon能夠阻止服務端不被錯誤的用戶訪問,但是並不能阻止用戶訪問錯誤的服務端。系統需要一種方式能讓客戶端在發送敏感信息給服務端前先驗證服務端的正確性,也就是說系統必須能雙向認證。

利用會話密鑰,只要你能正確設計客戶端程式,就可以解決掉這個問題。讓我們再以列印服務為例,我們希望列印客戶端能確認它發的列印服務確實是被正確的列印服務接收到的。

那麼列印客戶端應該這樣做,我輸入一個列印任務和對應的列印文件名-我簡歷的名稱,假如我擁有列印服務的票據和會話密鑰,客戶端程式用會話密鑰構建一個認證對象,把認證對象和票據發給認為正確的印表機。這時客戶端並沒有發送要列印的簡歷,他要等待服務端返回信息。
現在正真的列印服務接收到票據和認證對象,首先解碼票據獲取會話密鑰,接著用會話密鑰解碼認證對象,之後做各種認證檢查;

假如認證通過,服務端返回給客戶端一個能證明自己身份的數據包給客戶端,並用會話密鑰把返回的數據包加密。

客戶端收到數據包後會嘗試用會話密鑰解碼數據包。如果數據包正確解碼,並且得到了正確的服務端返回信息,客戶端就可以判定現在返回信息的是正確的列印服務,接著才會把對應的列印簡歷任務發過去。
這樣假定你的老闆用轉換系統把他的印表機偽裝成我想用的那一臺,我的客戶端發送認證對象和票據給他並開始等待返回結果,而偽裝的印表機不能生成正確的返回信息,因為它不能解碼票據得到會話密鑰。這時我的客戶端收不到正確的返回信息,就不會把真正的列印任務發過去,最終客戶端等待超時並退出,雖然我的列印任務沒有完成,但至少我的簡歷沒有出現在敵人的辦公桌上。

你看,我們有一個堅實的理論依據來實現Charon認證系統了。

Athena:是的。可不管怎麼說,我並不喜歡Charon這個名字

Euripides:你不喜歡,從什麼時候開始的

Athena:我一直都不喜歡,因為這個名字沒有任何意義,我之前跟我的叔叔談起這個事,他建議我用另一名字,Charon的那隻有三個頭的狗

Euripides:哦,你是說“Cerberus”

Athena:註意你的發音,是“Cerberus”

Euripides:呃,是這個名字嗎?

Athena:是的,如果你是個羅馬人,我是一個希臘神,我有一個希臘看門狗,那麼它的名字會讀作“Kerberos”,首字母是K

Euripides:好了好了,不要再扔霹靂了,就用這個名字了,事實上,他有一個漂亮的黑眼圈。現在,再見,Charon,你好,Kerberos。

Afterword

這個對話是在1988年寫的,用來幫助讀者理解為什麼Kerberos V4版本設計成這個樣子,這麼多年,它很好的完成了任務。

當我把這個對話整理成HTML後,我驚訝的發現這個文檔也同樣適用於V5版本。雖然很多事情發生了變化,但是協議的核心還是一樣的。只有兩個地方在V5版本中做了調整。

第一個變化是意識到如果一個黑客用程式來抓取票據和認證對象,並立即將它們發送到服務端,這樣把認證對象的有效期設置成5分鐘並不能有效的阻止這種重放攻擊。

所以在V5版本中,認證對象被真正設計成“只能使用一次”,這通過在服務端設計一個緩存,用來保存最近發過來的認證對象的記錄來實現。攻擊者嘗試偷取認證對象並重用它,即便在5分鐘的視窗期里,服務端的緩存也能區分出來這個認證對象已經被提交過了。

第二個主要變化是當用戶用Kinit首次從Kerberos獲取服務的票據(TGT)時,在Kerberos把票據返回給客戶端時,票據不需要用用戶的密碼加密。因為這個票據已經用票據分發服務的密碼加密過了,之後用戶用這個票據再向Kerveros請求其他服務的票據時也是以未加密的形式直接在網路上傳播的。所以這個地方就沒有必要再用用戶的密碼去進行加密了(返回數據包中的其他部分如票據會話密鑰等還是要加密的)

票據分發服務(TGS)也做了同樣的修改,票據分發服務生成的票據,也不再用票據分發服務對應的會話密鑰加密,因為這個票據已經用服務對應的密碼加密過了。
例如在V4版本中,數據包是下麵這樣的

KDC_REPLY = {TICKET, client, server, K_session}K_user
TICKET = {client, server, start_time, lifetime, K_session}K_server

在V5版本中會變成下麵的樣子

KDC_REPLY = TICKET, {client, server, K_session}K_user

最終的請求過程如下

當然,Kerberos在V5版本中還加入了其他的新特性。用戶可以安全的分發他的票據,從而在其他的地方使用;用戶也可以把部分許可權授予一個伺服器,使這個伺服器可以作為自己的代理。其他的新特性包括用更加安全的加密演算法代替DES,例如triple-DES。讀者如果想瞭解更多關於V5和V4之間不同點的可以訪問【Kerberos系統的進化】,作者是 Cliff Neumann 和 Theodore Ts'o。

最後希望你能喜歡關於Kerveros的簡單介紹,祝你在之後的使用中一切順利。

Theodore Ts'o 1997.2


您的分享是我們最大的動力!

更多相關文章
  • <script> //簡單的封裝一個ajax /** * ajax: async javascript and json * 主要用來實現前後端的數據交流 * A要發送一個信息給B * 請求當中需要有的基本信息 * 1.B的地址 * 2.請求方式 * 3.請求數據 * 4.狀態碼(B是否正常接收數據 ...
  • 看到最後有驚喜哦! 曾經僅用 10 天開發而成的 JavaScript,在經歷了近 30 年的迭代輪迴中,終於成為了最受開發者喜愛的編程語言之一,而與之水漲船高的當然也包括了 JavaScript 開發者的薪酬,據 Indeed 的數據統計結果顯示,在美國,JavaScript 開發人員的平均基本工 ...
  • 網路全部筆記 # 向瀏覽器的地址欄中輸入一個url按回車之後,網路中都會發生什麼? 答: 1.看瀏覽器的緩存 2.看本機的host C:/windows/system32/drivers/etc/host 127.0.0.1 localhost 3.家裡路由器,上級路由,城市的LDNS伺服器,繼續向 ...
  • 所有三個操作系統都提供了應用程式向用戶發送通知的手段。 Electron允許開發者使用 "HTML5 Notification API" 發送通知,並使用當前運行的操作系統的本地通知 API 來顯示它。 HTML5 API,它只能在渲染器進程中使用 渲染進程 主進程 使用electron 類:Not ...
  • 一、if語句 1.基本語法同java語言 2.註意點: (1)如果只有一條語句的時候,if後面的大括弧可以省略。(也同Java) (2)分號“;“也是語句,是空語句。 (3)if else是一個整體,else匹配的if的時候是匹配最近的一個 (4)對於非boolean類型的值,會先轉換為boolea ...
  • 語雀入口 https://www.yuque.com/along-n3gko/ezt5z9 介紹 散列是一種常用的數據存儲技術,散列後的數據可以快速的插入或取用。散列所使用的數據結構叫散列表。 散列演算法的作用是儘可能的在數據結構中找到一個值。 基本特點:插入,刪除,取用數據都非常快,但是查詢效率很低 ...
  • 隨著近些年前端行業的崛起,前端人才也越來越供不應求。不少人都看到這個行業的巨大發展前景,因此目前零基礎開始學習前端的人也越來越多了。那麼,零基礎小白如何入門前端呢?為了讓大家快速入門前端,本文將從前端市場分析、前端應用場景、前端學習路線和前端入門建議幾方面講解最全面的前端入門必備知識。如果你對前端感 ...
  • 題庫管理 22. 圖片庫:創建文件目錄,維護圖片,供題庫選擇調用 23. 單選題:維護單選試題,試題題目,選項,答案,類型,級別,狀態,解析 24. 多選題:維護多選試題,試題題目,選項,答案,類型,級別,狀態,解析 25. 判斷題:維護判斷試題,試題題目,答案,類型,級別,狀態,解析 26. 填空 ...
一周排行
  • 上一篇(https://www.cnblogs.com/meowv/p/12974439.html)完成了全網各大平臺的熱點新聞數據的抓取,本篇繼續圍繞抓取完成後的操作做一個提醒。當每次抓取完數據後,自動發送郵件進行提醒。 在開始正題之前還是先玩一玩之前的說到卻沒有用到的一個庫PuppeteerSh ...
  • 搞學習 猿學:http://yuanxue365.com/簡書:https://www.jianshu.com/doyoudo:http://www.doyoudo.com/好知網:http://www.howzhi.com/學小易(大學生搜題)https://www.51xuexiaoyi.com ...
  • LINQ 的優勢並不是提供了什麼新功能,而是讓我們能夠用更新、更簡單、更優雅的方法來實現原有的功能。不過通常來講,這類功能所帶來的就是對性能上的影響——LINQ 也不例外。本篇文章的主要目的就是讓你瞭解 LINQ 查詢對性能的影響。我們將介紹最基本的 LINQ 性能分析方法,並提供一些數據。還會給出 ...
  • Elasticsearch 入門(三)使用Elasticsearch.Net & NEST作為elasticsearch客戶端 GitHub倉庫 https://github.com/elastic/elasticsearch-net 選擇 Elasticsearch.Net 作為客戶端 連接方式 ...
  • 1.我們要知道為啥用框架? 代碼可讀性提高,加快開發速度,提高代碼穩定性,重覆代碼的封裝。 2.用框架有啥好處 結構清晰,調用方便,能低代碼開發。 3.怎麼用框架 根據邏輯邏輯與功能現實,把不同分類的東西,按照一定的規則,區分好模塊,一個令你滿意的框架就出來了 註意點: 技術薄弱的學員,不要著急學框 ...
  • 今天在學習winform項目時,看到同時是這樣解決text文本框變換值的: winform界面是這樣的 於是我在想,為什麼不直接進行賦值來進行變換,而通過替換局部字元串來變換呢?兩者之間有什麼區別?到底哪一種的性能會好點?於是帶著種種疑問,設計瞭如下實驗: using System; using S ...
  • HttpClient 中 FormUrlEncodeContent 的 bug ...
  • static void FileStreamSDemo() { DateTime dtNow = DateTime.Now; DateTime dtEnd = dtNow.AddSeconds(60); using(FileStream fs=new FileStream("FileStream.t ...
  • 用戶許可權驗證源碼剖析,和用戶登錄驗證有點相似,但是為了增加記憶,有必要再一次添加, 註意:一定要跟著博主的解說再看代碼的中文註釋及其下麵的一行代碼!!! 1、準備一個路由和視圖類,全局路由配置暫時忽略,當流程執行到下麵的url:groupsSelectAll——> GroupsView的視圖類下的a ...
  • 作者:勿念先生 https://blog.csdn.net/moHedong/java/article/details/79687878 GC的歷史比Java還有久遠,我們在思考GC時候需要思考三個問題: 哪些記憶體需要回收? 什麼時候回收? 如何回收? 在Java中程式計數器、虛擬機棧、本地方法棧這 ...