RFC2617- HTTP Authentication自譯本-(4) (轉)

worldblog發表於2007-12-05
RFC2617- HTTP Authentication自譯本-(4) (轉)[@more@] 

  但它還是比在[10]、POP及IMAP(見2195[9])上用的CRAM-MD5要強許多。它將被用來替代薄弱的危機四伏的基本機制。

 

  分類鑑別只提供對實際口令的保護。請求或回應的所有其它內容都可以被。

 

  對雙向傳遞的訊息,分類鑑別方案只提供有限的完整性保護。如果使用了qop=auth-int機制,訊息中參與計算WWW-鑑別和授權標題域中的回應指示值(見上面的3.2節)的部分將受到保護。大多數標題域及其值都可被修改,從而成為中間層的組成部分。

 

  分類鑑別方案不足以滿足許多HTTP事務的需要。為此,TLS或SHTTP成為更適合的。分類鑑別尤其不能用於許多需要加密保護的事務處理上。儘管如此,許多功能仍得以保留,所以分類鑑別仍然可以繼續使用。任何現存的對基本鑑別方案的服務都應根據實際情況儘早轉到分類鑑別方案上。

 :namespace prefix = o ns = "urn:schemas--com::office" />

4.3 受限的nonce值使用(Limited Use Nonce Values)

 

  分類方案使用指定的nonce值為種子生成請求-分類(request-digest)值(見前面3.2.2.1)。如3.2.1節例子所示的nonce,伺服器可任意構造它,而它只能用於指定的客戶、指定的資源、有限的時間段或使用數量及其它限制。這樣做會增強保護機制,比如可以抵抗回放式攻擊(relay attack,見4.5)。然而,應當看到,選擇生成或檢測nonce的方法也存在些問題及資源消耗。例如,伺服器可以透過記錄列表檢查最近發出的nonce是否返回,並在每個回應的Authentication-Info標題域中傳送next-nonce指示,從而實現每個nonce值只能使用一次。這種措施可以抵擋哪怕是立即方式的回放攻擊,但是用於檢查nonce值的開銷也非常高,甚至可能造成管道式請求的鑑別失敗(假設返回nonce過期指示)。類似情況,要合併請求指定的元素,如資源的Etag值,也將限制對應版本資源中nonce的使用,從而導致管道失敗。因而,此種方案雖然看來有時很有效,但從效能上看,對沒采用此方案的一方來說,將是不可接受的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Franks, et al.  Standards Track  [Page 21]


 

4.4 基本鑑別與分類鑑別的比較(Comparison of Digest with Basic Authentication)

 

  分類鑑別和基本鑑別都是處於安全體系的薄弱端,兩者比較的意義在於可在必要時用分類鑑別替代基本鑑別。

 

  事務在協議輸的最大危脅在於網路監聽。這些事務可能包含一些與交易相關的線上訪問。基本鑑別方案下,偷聽者可以得到的口令,這樣,他就可以在資料庫中做任何操作,而且更糟糕的是,該使用者使用相同口令保護的一切資源都將受到危脅。

 

  與上面相應,如果採用分類鑑別方案,偷聽者最多隻能得到事務的訪問權而得不到使用者口令。偷聽者所得到的資訊將允許他進行回放式攻擊,但只能請求同一個,而如果伺服器端對nonce的選項進行限制的話,他的請求將不能得逞。

 

4.5 回放式攻擊(Replay Attacks)

 

  對簡單的GET請求而言,對分類鑑別方案實行回放式攻擊是沒有什麼意義的,因為偷聽者早已透過回放得到了他所能得到的唯一檔案。這是因為被請求檔案的URI已經在客戶端請求中進行了分類,伺服器將只傳遞這個指定檔案。而在基本鑑別方案下則不同,偷聽者會得到使用者的口令,從而得到受此口令保護的任何檔案。

 

  因而,從某種目的上看,防範回放式攻擊還是必要的。一個好的分類鑑別的實現可以透過多種方式來解決這個問題。伺服器產生nonce值是與實現無關的,但是如果它包含了客戶IP、時間戳、資源的Etag及私有伺服器金鑰(如上面所建議的),將增大回放式攻擊的難度。攻擊方必須必須讓伺服器相信請求是來自一個錯誤的,從而導致伺服器將要傳送的檔案發到偷聽者指定的IP而不是原來的IP地址。 攻擊方只有在時間戳過期前才有可能取得成功。對nonce中的客戶IP及時間戳進行分類將允許實現不必對事務間的狀態進行維護。

 

  對應用程式而言,如果無法容忍可能存在的回放式攻擊,可使用時間少於1秒的一次性nonce值。當然,這會增加伺服器的額外開銷,如,伺服器  要記住在nonce時間戳(用來進行分類的)過期前,哪些nonce值已經用過了。不過對於回放式攻擊,該方法很有效。

 

 

 

 

 

 

 

 

 

 

 

 

Franks, et al.  Standards Track  [Page 22]


 

  實現程式要防範可能存在的、使用POST或PUT請求進行的回放式攻擊。如果伺服器沒有使用一次性或限制性的nonce或(和)用qop=auth-int的完整性保護,攻擊方仍然可以透過假冒表格資料(fodata)或其它訊息主體的方式來構造一個帶有合法信任資訊的請求,從而成功地實現回放攻擊。即使採用完整性保護,標題域中的大多數後設資料仍不在保護範圍之內。實踐中,正確產生nonce,並對提供的保護進行檢查,可以有效防範利用先前用過的合法信任來進行的回放式攻擊。見4.8。

 

4.6 由多方鑑別方案產生的弱點(Weakness Created by Multiple Authentication Schemes)

 

  HTTP/1.1伺服器可能在401(鑑別)回應訊息中返回多個質詢(challenge),每個質詢可以使用不同的auth-scheme。使用者(agent)必須從該質詢中選用它所能理解的最強auth-scheme及請求信任。

 

  注意,許多隻能識別基本鑑別方案,而且要求該方案處於auth-scheme列表中的第一項。伺服器如提供最小支援,只應包括基本鑑別方案。

 

  當伺服器提供數種使用WWW-Authenticate標題的鑑別方案以供選擇時,其安全性與最弱的鑑別方案沒有什麼不同。參見4.8節使用多種鑑別方案進行精確攻擊的討論內容。

 

4.7 線上字典攻擊(Online dictionary attacks)

 

  如果攻擊方可以偷聽的話,他可以用常見的單詞列表組成nonce/回應對來測試。該列表比起全部可能在口令中出現的單詞要少很多。按列表中每一個口令計算回應,並可在每次質詢(challenge)時得到回報。

 

  伺服器可以採取措施,不允許使用者使用字典中的單詞做為口令,這樣可以降低這種攻擊的危險。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Franks, et al.  Standards Track  [Page 23]


 

4.8 中間人(Man in the Middle)

 

  基本鑑別方案和分類鑑別方案都容易受到‘中間人’(man in the middle,MITM)的攻擊。例如,懷有敵意或不安全的代理()。可以肯定地說,它與所有偷聽類問題相關。而且,它還為攻擊者提供了一些額外的機會。

 

  ‘中間人’攻擊可能從一組鑑別方案中的薄弱環節入手,並希望客戶端使用了已經暴露的使用者信任(如口令)。出於這種原因,客戶端應儘可能從提供的選項中選擇它所支援的最強鑑別方案。

 

  更高階的‘中間人’攻擊可能會刪除提供的鑑別方案選項,而替換成一個採用基本鑑別方案的質詢,這樣使用者和原始伺服器互動的信任將使用明文來傳輸。還有個更陰險的方法,就是採用‘免費’代理快取服務來欺騙使用者。

 

  當透過鑑別的信任請求被使用時,使用者代理(agent)應當考慮其介面顯示的尺度,而且應記著當發現伺服器要求高階別而回應是低階別時,向使用者發出報警資訊。另一個不錯的主意是,將使用者代理成分類鑑別方式,或轉接到其它安全站點上。另外,有敵意的代理(proxy)還可以偽裝成客戶端發出請求,當然,和基本鑑別方案相比,還是有一定難度的。

 

4.9 選擇純文字攻擊(Chosen plaintext attacks)

 

  分類鑑別方案下,‘中間人’或有惡意的伺服器可以任意選擇客戶用來計算回應的nonce值。這種方式被稱為‘選擇純文字’攻擊。選擇已知的nonce可以使密碼分析更加容易[8]。

 

  實際上,對採用純文字進行分類的功能進行單向分析是不可能的。

 

  客戶端對抗此攻擊的對策是,在配置中要求使用”cnonce”指示;這將允許客戶對輸入值按照自己的方式而不是攻擊者指定的方式進行雜湊變換。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Franks, et al.  Standards Track  [Page 24]


 

4.10 預先計算的字典攻擊(Precomputed dictionary attacks)

 

  分類鑑別方案下,如果攻擊方可純文字攻擊,攻擊方可事先按照常見單詞參照nonce的值,計算出一個字典,其中包含回應-口令(response, pass)對。這種計算可以在許多機器上並行展開。透過對字典中的口令進行嘗試,攻擊方可能獲得某個質詢的回應。雖然字典中的大多數口令可能沒有,但是總會有幾個成功的。攻擊方在挑選質詢(challenge),及計算每個口令回應中所付出的代價,終將因許多口令的破譯而得到回報。一個含有100萬個口令/回應(password/response)對的字典可能要佔3.2G的空間。

 

  客戶端防範此攻擊的對策也是使用”connce”指示。

 

4.11 批方式暴力攻擊(Batch brute force attacks)

 

  在分類鑑別方案下,‘中間人’可以執行純文字攻擊,並從多個使用者處收集對應同一個nonce的回應。透過該方法,攻擊方可以得到口令集中的能生成有效nonce/response對的全部口令資訊。同時,該方法也減少了完全匹配nonce/response對所需要的時間。這種攻擊也可在多個機器上同時進行,甚至單機也可進行的口令搜尋――已有報告證實,6個或6個以下字元組成的密碼可在幾個小時內。

 

  客戶端的對抗策略是使用”cnonce”指示。

 

4.12 假冒伺服器欺騙(Spoofing by Counterfeit Servers)

 

  基本鑑別方案容易受到假冒伺服器攻擊。當使用者堅信他正與一臺受基本鑑別方案保護的主機相連時,他也許不會想到,此時他可能正與懷有敵意的伺服器相連。攻擊者可截獲口令,並將其儲存起來備用,同時假裝返回一個錯誤。在分類鑑別方案下,這種攻擊實現下來要難一些,但前提是客戶端必須要求使用分類鑑別方案,或採用上面提到的一些技術來統計‘中間人’攻擊。另外,使用者使用的鑑別機制也會在發現這種攻擊時給使用者提個醒。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Franks, et al.  Standards Track  [Page 25]


 

4.13 口令(Storing passwords)

 

  分類鑑別方案需要鑑別代理(通常是伺服器)將與使用者名稱、口令相關的資訊儲存到一個由給定的realm引數指定的口令檔案中。透過,它包含由使用者名稱和H(A1)組成的對。H(A1)是對使用者名稱、realm、口令進行分類的結果。見上面。

 

  這種機制的隱患在於,一旦口令檔案被破解,攻擊方就可透過該realm得到本伺服器上對指定文件的訪問。和標準口令檔案不同,不需要對伺服器的realm引數進行,就可以訪問與其相關的檔案。另一方面,解密或更確切說是暴力攻擊對於獲取使用者口令是必須的。這就是realm做為分類資料的組成部分儲存在口令檔案中的原因。這意味著即使一個分類鑑別的口令檔案被破譯,即使用者名稱和口令己被暴力攻擊所破解,也不會危及其它使用相同使用者名稱及口令的檔案。

 

  有兩個重要結論:

第一,  如果口令檔案中包含未加密的口令,則此檔案必須受到保護。因為訪問檔案所需要的許可資訊都在realm中,它理當受到看管,事實上這也容易做到。

第二,  任何單獨使用者使用的realm引數都應當是獨一無二的。尤其是realm字串應當包括進行鑑別操作的主機名。分類鑑別的弱點是客戶端無法對伺服器進行鑑別。

 

4.14 摘要(Summary)

 

  從現代密碼字來看,分類鑑別無疑很脆弱。但從一定範圍上看,它在取代基本鑑別方面還是有一定價值的,它能從一定程度(不是全部)上補救基本鑑別方案的不足。分類鑑別方案的強壯程度取決於其實際的實現方式。特別是,依賴伺服器實現的nonce結構更易受到回放式攻擊,對此,大多數伺服器提供的選項還是恰當的,如由伺服器方來承擔使用一次性nonce或分類的開銷來防範可能的回放式攻擊。另外,還可對nonce中的資訊進行限制,如限制單一的IP地址、單一的Etag或限制nonce的壽命週期等等,來滿足安全方面的需求。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Franks, et al.  Standards Track  [Page 26]


 

  密碼安全的極限,或說底線(bottom line)是:任何(*any*)己實現的應用與密碼標準相比都要稍弱一些,但是任何(*any*)己實現的應用都遠比基本鑑別方案高階。

 

5 例子實現(Sample implementation)

 

  下面的程式碼實現了了計算請求-分類(request-digest)和回應-分類(response-digest)的H(A1)、H(A2),還將提供一個測試程式以用來計算3.5節中例子所用到的值。它使用MD5實現(RFC1321)。

 

File "digcalc.h":

#define HASHLEN 16

typedef char HASH[HASHLEN];

#define HASHHEXLEN 32

typedef char HASHHEX[HASHHEXLEN+1];

#define IN

#define OUT

/* 計算每個HTTP分類H(A1)值,即calculate H(A1) as per HTTP Digest spec*/

void DigestCalcHA1(

  IN char * pszAlg,     //計算方式:md5-sess或md5

  IN char * pszUserName,   //使用者名稱

  IN char * pszRealm,      //realm

  IN char * pszPassword,  //口令

  IN char * pszNonce,      //nonce

  IN char * pszCNonce,      //cnonce

   OUT HASHHEX SessionKey  //會話金鑰

  );

/* 計算每個HTTP分類的請求-分類/回應-分類值,即

calculate request-digest/response-digest as per HTTP Digest spec */

void DigestCalcResponse(

  IN HASHHEX HA1,  /* H(A1) */

  IN char * pszNonce,      /*nonce from server(來自伺服器的nonce)*/

  IN char * pszNonceCount,  /* 8 hex digits(八個16進位制數字)*/

  IN char * pszCNonce,    /* client nonce(客戶端的nonce)*/

  IN char * pszQop,    /* qop-value(qop值): "", "auth", "auth-int" */

  IN char * pszMethod,    /* method from the request(請求方法)*/

  IN char * pszDigestUri,   /* requested URL(請求URL)*/

  IN HASHHEX HEntity,    /* H(entity body) if qop="auth-int" */

  OUT HASHHEX Response  /* request-digest or response-digest */

  );

File "digcalc.c":

#include

#include

 

Franks, et al.   Standards Track  [Page 27]


 

#include

#include "digcalc.h"

/*將二進位制轉換成16進位制*/

void CvtHex(  IN HASH Bin,

      OUT HASHHEX Hex)

{

unsigned short i;

unsigned char j;

for (i = 0; i < HASHLEN; i++)

{

j = (Bin[i] >> 4) & 0xf;

if (j <= 9)    Hex[i*2] = (j + '0');

else      Hex[i*2] = (j + 'a' - 10);

j = Bin[i] & 0xf;

if (j <= 9)    Hex[i*2+1] = (j + '0');

else    Hex[i*2+1] = (j + 'a' - 10);

 };

Hex[HASHHEXLEN] = '';

};

/* 計算H(A1),calculate H(A1) as per spec */

void DigestCalcHA1(

IN char * pszAlg,      //計算方式:md5-sess或md5

IN char * pszUserName,  //使用者名稱

IN char * pszRealm,     //realm

IN char * pszPassword,  //口令

IN char * pszNonce,     //nonce

IN char * pszCNonce,    //cnonce

OUT HASHHEX SessionKey  //會話金鑰

)

{

MD5_CTX Md5Ctx;

HASH HA1;

 

MD5Init(&Md5Ctx);

MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));

MD5Update(&Md5Ctx, ":", 1);

MD5Update(&Md5Ctx, pszRealm, strlen(pszRealm));

MD5Update(&Md5Ctx, ":", 1);

MD5Update(&Md5Ctx, pszPassword, strlen(pszPassword));

MD5Final(HA1, &Md5Ctx);

if (stricmp(pszAlg, "md5-sess") == 0) {

 

Franks, et al.  Standards Track  [Page 28]


MD5Init(&Md5Ctx);

MD5Update(&Md5Ctx, HA1, HASHLEN);

MD5Update(&Md5Ctx, ":", 1);

MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce));

MD5Update(&Md5Ctx, ":", 1);

MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce));

MD5Final(HA1, &Md5Ctx);

};

CvtHex(HA1, SessionKey);

};

/*計算每個HTTP所指定的request-digest/response-digest */

void DigestCalcResponse(

IN HASHHEX HA1,    /* H(A1) */

IN char * pszNonce,     /* nonce from server */

IN char * pszNonceCount,  /* 8 hex digits */

IN char * pszCNonce,  /* client nonce */

IN char * pszQop,    /* qop-value: "", "auth", "auth-int" */

IN char * pszMethod,  /* method from the request */

IN char * pszDigestUri,  /* requested URL */

IN HASHHEX HEntity,    /* H(entity body) if qop="auth-int" */

OUT HASHHEX Response  /* request-digest or response-digest */

)

{

MD5_CTX Md5Ctx;

HASH HA2;

HASH RespHash;

HASHHEX HA2Hex;

// calculate H(A2)

MD5Init(&Md5Ctx);

MD5Update(&Md5Ctx, pszMethod, strlen(pszMethod));

MD5Update(&Md5Ctx, ":", 1);

MD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri));

if (stricmp(pszQop, "auth-int") == 0) {

MD5Update(&Md5Ctx, ":", 1);

MD5Update(&Md5Ctx, HEntity, HASHHEXLEN);

};

MD5Final(HA2, &Md5Ctx);

CvtHex(HA2, HA2Hex);

// calculate response

MD5Init(&Md5Ctx);

MD5Update(&Md5Ctx, HA1, HASHHEXLEN);

MD5Update(&Md5Ctx, ":", 1);

MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce));

MD5Update(&Md5Ctx, ":", 1);

if (*pszQop) {

Franks, et al.  Standards Track   [Page 29]

MD5Update(&Md5Ctx, pszNonceCount, strlen(pszNonceCount));

MD5Update(&Md5Ctx, ":", 1);

MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce));

MD5Update(&Md5Ctx, ":", 1);

MD5Update(&Md5Ctx, pszQop, strlen(pszQop));

MD5Update(&Md5Ctx, ":", 1);

};

MD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN);

MD5Final(RespHash, &Md5Ctx);

CvtHex(RespHash, Response);

};

File "digtest.c":

 

#include

#include "digcalc.h"

 

void main(int argc, char ** argv) {

char * pszNonce = "dcd98b7102dd2f0e8b11d0f600bfb0c093";

char * pszCNonce = "0a4f113b";

char * pszUser = "Mufasa";

char * pszRealm = "testrealm@host.com";

char * pszPass = "Circle Of Life";

char * pszAlg = "md5";

char szNonceCount[9] = "00000001";

char * pszMethod = "GET";

char * pszQop = "auth";

char * pszURI = "/dir/index.html";

 

HASHHEX HA1;

HASHHEX HA2 = "";

HASHHEX Response;

 

DigestCalcHA1(pszAlg, pszUser, pszRealm, pszPass, pszNonce,pszCNonce, HA1);

DigestCalcResponse(HA1, pszNonce, szNonceCount, pszCNonce, pszQop,

pszMethod, pszURI, HA2, Response);

 

printf("Response = %sn", Response);

};

 

 

 

 

 

 

Franks, et al.  Standards Track  [Page 30]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-988652/,如需轉載,請註明出處,否則將追究法律責任。

相關文章