加密 UNIX 口令

作爲Internet上最流行的服務器操作系統,UNIX安全性倍受關注。Unixd的安全性主要靠口令實現,因此,Unix口令加密算法幾度改進,現在普遍採用DES算法對口令文件進行25次加密,而對每次DES加密產生的結果,都要用2的56次方次查找與匹配才能進行一次遍歷,要破解這樣的口令,其工作量是巨大的,所以從理論上說這種口令是相當安全的。然而不幸的是我們仍然不時聽道口令被攻破的消息。這些口令是如何被攻破的,我們又怎樣才能保證口令的安全呢。下面將對這一問題進行探討。

 
Unix 口令文件的格式及安全機制


Unix的口令文件passwd是一個加密後的文本文件,儲存在/etc目錄下。該文件用於用戶登錄時校驗用戶的口令,僅對root權限可寫。口令文件中每行代表一個用戶條目,格式爲:LOGNAME : PASSWORD : UID : GID : USERINFO : HOME : SHELL。每行的頭兩項是登錄名和加密後的口令,UID和GID是用戶的ID號和用戶所在組的ID號,USERINFO是系統管理員寫入的有關該用戶的信息,HOME是一個路徑名,是分配給用戶的主目錄,SHELL是用戶登錄後將執行的shell(若爲空格則缺省爲/bin/sh)。目前多數Unix系統中,口令文件都做了Shadow變換,即把/etc/passwd文件中的口令域分離出來,單獨存在/etc/shadow文件中,並加強對shadow的保護,以增強口令安全。
Unix系統使用一個單向函數crypt()來加密用戶的口令。Crypt()是基於DES的加密算法,它將用戶輸入的口令作爲密鑰,加密一個64bit的0/1串,加密的結果又使用用戶的口令再次加密;重複該過程,一共進行25次。最後的輸出爲一個13byte的字符串,存放在/etc/passwd的PASSWORD域。單向函數crypt()從數學原理上保證了從加密的密文得到加密前的明文是不可能的或是非常困難的。當用戶登錄時,系統並不是去解密已加密的口令,而是將輸入的口令明文字符串傳給加密函數,將加密函數的輸出與/etc/passwd文件中該用戶條目的PASSWORD域進行比較,若匹配成功,則允許用戶登錄系統。

 
口令破解原理


口令破解通常有蠻力攻擊和字典攻擊兩種方式。Unix中一共有 [0x00~0xff] 共128個字符,其中 95個字符(10(數字)+33(標點符號)+26*2(大小寫字母) )可作爲口令的字符。假設m爲可能使用的字符集的大小,n爲口令的長度,則可生成的口令數爲m的n次冪,隨着字符集的擴大與口令長度的增加,口令攻擊嘗試次數將迅速增加。 如口令長度爲6,取字母和數字組合,可能性是62 的6次冪56,800,235,584。但如果5個字母是一個常用漢字的拼音或英文單詞,估算一下常用詞約爲10000條, 從10000個常用詞中取一個詞與任意一個數字字符組合成口令,則僅10000* 10 = 100000 (10萬種可能)。在口令的設置過程中,還有許多個人因素在起作用,爲使自己的口令容易記憶,許多人往往將個人的姓名、生日、電話號碼、街道的號碼等作爲口令,這樣便爲口令的破解留下了方便之門。

 
貝爾實驗室的計算機安全專家R.Morris和K.Thompson提出了這樣一種攻擊的可能性:可以根據用戶的信息建立一個他可能使用的口令的字典。比如:他父親的名字、女朋友的生日或名字,街道的名字等等。然後對這個字典進行加密,每次拿出一個經過加密計算的條目與口令文件比較,若一致,口令就被猜到了。
也許有人認爲口令毫無規律可言,字典中不會有,計算機是破譯不了的,那就大錯特錯了。有很多專門生成字典的程序,比如:Dictmake、txt2dict、xkey等等。以dictmake爲例:啓動程序後,計算機會要求輸入最小口令長度、最大口令長度、口令包含的小寫字符、大寫字符、數字、有沒有空格、含不含標點符號和特殊字符等一系列的問題。當回答完了計算機提出的問題後,計算機就會按照給定的條件自動將所有的組合方式列出來並存到文件中,而這個文件就是資料字典。目前,在因特網上,有一些數據字典可以下載,包含的條目從1萬到幾十萬條。數據字典一般囊括了常用的單詞。攻擊者一旦通過某種途徑獲得了passwd文件,破譯過程便只需一個簡單的C程序即可完成。


Unix中有一組子程序可對/etc/passwd文件進行方便的存取。getpwuid()函數可從/etc/passwd文件中獲取指定的UID的入口項。getpwnam()函數可在/etc/passwd文件中獲取指定的登錄名入口項。這兩個子程序返回一指向passwd結構的指針,該結構定義在
/usr/include/pwd.h中,定義如下:
struct passwd {
char * pw_name; /* 登錄名 */
char * pw_passwd; /* 加密後的口令 */
uid_t pw_uid; /* UID */
gid_t pw_gid; /* GID */
char * pw_age; /* 代理信息 */
char * pw_comment; /* 註釋 */
char * pw_gecos;
char * pw_dir; /* 主目錄 */
char * pw_shell; /* 使用的shell */
char * pw_shell; /* 使用的shell */
}
getpwent(),setpwent(),endpwent()等函數可對口令文件作後續處理。首次調用getpwent()可打開/etc/passwd文件並返回指向文件中第一個用戶條目的指針,再次調用getpwent()便可順序地返回口令文件中的各用戶條目,setpwent() 可把口令文件的指針重新置爲文件的開始處,endpwent() 可關閉口令文件。
由此可見,攻擊者只需建立一個字典文件,然後調用現成的cryp()加密例程來加密字典文件中的每一條目,再用上述函數打開口令文件,進行循環比較就很容易破解密碼了。
實際上Internet網上有很多現成的密碼破解軟件工具,過於簡單的口令很容易破解。那麼,我們用什麼方法來保證用戶口令是一個安全的口令呢?運用CrackLib來構建安全的Unix口令是一個較好的辦法。

 
CrackLib原理及應用


CrackLib是一個用於UNIX系統下的函數庫, 它可以用於編寫和口令有關的程序。 其基本思想就是通過限制用戶使用使用過於簡單、容易被猜測出來或容易被一些工具搜索到的密碼,來提高系統的安全性。 
CrackLib並不是一個可以直接運行使用的程序, 它只是一個函數庫, 可以利用其中的函數寫自己的程序或是加入其它程序中以提高安全性,如可以改寫passwd 使用戶在選擇密碼時受到限制。CrackLib使用一個字典, 它查找字典以判斷用戶所選密碼是不是安全的密碼。用戶也可以加入其它信息, 使用自己的字典。CrackLib通過建立索引和二元查找,效率非常高,其字典大小通常只有同等字典數的一半。下面介紹如何運用CrackLib。
1、構建cracklib字典
CrackLib可以很容易的在Internet上找到, 現在使用的版本多是2.7, 首先要確定字典安裝的路徑,即給DICTPATH賦值,形式爲:目錄+字典文件名(不包括後綴),如:
DICTPATH=/usr/local/lib/pw_dict.。該變量值將在所有調用CrackLib函數的程序中用到,字典文件通常包括 /usr/local/lib/pw_dict.pwd,/usr/local/lib/pw_dict.pwi,/usr/local/lib/pw_dict.hwm三個文件。
CrackLib 字典可直接從網上下載,也可以用它提供的工具生成。如果想加入其它信息, 使用自己的字典,可將含有新詞的文件放到SOURCEDICT目錄如"/usr/dict/words"下,CrackLib會將所有文件合併起來,刪除多餘的詞,將其壓縮成字典文件,通常只有原文件
40%-60%的大小。
2、在程序中調用函數
CrackLib函數可以被應用於很多地方, 只需加入簡單的幾行源碼, 就可以得到非常好的效果。 char *FascistCheck(char *pw, char *dictpath) 是CrackLib中最常用的函數。其中 pw是用戶選擇的密碼, 將被驗證是不是安全的,dictpath是字典所在路徑。
FascistCheck() 返回一個空指針,說明口令很安全,否則返回診斷出的字符串。下面是一個口令設置的簡單示例, 用以說明CrackLib函數用法.

#ifndef CRACKLIB_DICTPATH
#define CRACKLIB_DICTPATH "/usr/local/lib/pw_dict"
#endif
...
...
...
char *msg;

while(1) {
passbuf = getpass("請設定新密碼:";
if (!*passbuf) {
(void)printf("密碼設定取消, 繼續使用舊密碼/n";
break;
}

if (strlen(pussbuf) <= 4 ││ !strcmp( passbuf, newuser.userid ) ) {
(void)printf("密碼太短或與使用者代號相同, 請重新輸入/n ";
continue;
}
if (msg = (char*) FascistCheck(passbuf, CRACKLIBPATH)) {
printf("請另選密碼! (%s)/n",msg);
continue;
}

strncpy( newuser.passwd, passbuf, PASSLEN );
passbuf = getpass("請再輸入一次你的密碼 );
if( strncmp( passbuf, newuser.passwd, PASSLEN ) != 0 ) {
prints("密碼輸入錯誤, 請重新輸入密碼./n" ;
continue;
}
passbuf[8] = ‘/0’ ;
break;
}
這樣通過限制用戶使用不安全的密碼, 可以極大地提高系統的安全性

歡迎訪問:樂園www.ly8.co

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章