在前一回最後,我們談到軟體安全性機制中的認證及授權。絕大多數的軟體系統,在認證機制上,皆以密碼做為認證的憑據。因此,密碼成了證實某位企圖使用系統的使用者,究竟是否的確為他所宣稱之使用者的關鍵。
對有心人士而言,取得密碼是一個穿過系統安全性保護的快速途徑,因為一旦取得密碼、通過認證程序之後,便可以獲得不被允許的授權,進行別有企圖的活動。對軟體系統而言,認證勢必要求使用者提供密碼,但如何在使用者提供密碼的過程中,妥善保護密碼的安全,使其不受有心人士竊取,便成了一個重要的議題。

例如,使用者的密碼在登入遠端伺服器時會需要透過網路傳送至伺服器端。一般來說,可以假設網路傳輸都是不安全的,在傳輸的過程中,倘若沒有經過加密演算法的處理,有一些環節便能夠讀到所傳輸的資料,因而得到密碼。因此,使用加密的演算法來處理資料,或者使用具有加密能力的通訊協定(例如SSL/TLS或HTTPS等)來傳輸資料,才能確定傳輸過程具有一定的安全性。

前一回也提到現在許多惡意程式,會利用API hooking之類的技巧,直接攔截使用者在鍵盤上輸入的密碼,藉以達成竊取的目的。現今,許多線上遊戲及一些網路ATM系統為了防止使用者帳號遭盜取,也都採取了防止API hook的措施。這證明了,竊取密碼/保護密碼之間的對抗,一直是軟體安全性的重要課題。

伺服器端儲存密碼的方式要夠安全,否則會全部失守
密碼在系統中,從使用者開始輸入、到系統收到、到傳輸到伺服器端、最後在伺服器端進行驗證都有可能被竊取密碼。除了在使用者端必須要保護密碼之外,在伺服器端一樣要保護,而且安全性的強度必須更高,因為在架構上,伺服器端通常會集中保管所有的密碼,並且集中於伺服器端進行密碼的驗證。

一旦伺服器端保管密碼的機制淪陷,那麼所有使用者的密碼也都會一同淪陷。

伺服器端免不了要透過某種形式來記錄使用者的密碼,如此一來,才能夠在伺服器端進行驗證。然而,對於在伺服器端記錄使用者密碼,要有一個很基本的觀念,也就是儲存密碼的方式,必須具備一定的安全性。

很有趣的是,有時候看到一些軟體系統,它們會將使用者的密碼記錄在檔案或是資料庫中,卻是以明碼的形式記錄的。也就是說,一旦檔案被有心人士取得,或是資料庫中的資料被取得,那麼使用者的密碼也形同被攻破。

保護密碼儲存的原理
一般來說,在儲存密碼時,記錄的會是密碼利用單向不可逆演算法處理過後的結果。

所謂的單向不可逆,指的便是無法基於演算法處理後的結果,再倒回算出原始的資料。

也就是說,即使拿到處理過後的密碼,也沒有辦法還原成原始的密碼,因此,也就提供了密碼的安全性保護。

一般來說,常使用於密碼保護的不可逆演算法是MD5或SHA之類的演算法,它們通常被稱為Hashing Algorithm,原始資料經過此種演算法計算之後得到的結果,便被稱為digest。

既然沒有儲存原始的密碼,僅儲存了演算法處理後的digest,那麼伺服器端又要如何進行密碼的比對認證呢?

其實很簡單,當伺服器端收到使用者輸入的原始密碼時,只需要把收到的密碼同樣經過一樣的演算法處理、得到digest,再比對所得到的digest和系統所記錄的digest是否相同,便可以確認使用者所輸入的密碼是否正確。

這一類的演算法之所以被稱為Hashing Algorithm,便是因為它們所計算出來的digest都是固定長度,而所有可能的輸入資料,經過演算法處理後,都會幾乎平均落在digest的值域之內。所以,發生碰撞(也就是兩個不同的輸入資料,卻計算出相同的digest值)的機會並不高,只要兩個digest相同,幾乎可以斷定它們的原始輸入資料是一樣的。這是此類單向不可逆演算法,可用於密碼驗證的重要基礎。

當密碼的記錄形式改成了記錄digest之後,即便使用者密碼被有心人士取得之後,有心人士也無法利用任何演算法,再把digest倒算回原始的密碼。這已經大大提高的密碼的安全性。但是,即使如此,有心人士還是有可乘之機可以利用。

當有心人士取得密碼的digest資訊後,雖然他無法利用任何演算法,將digest倒算得到原始的密碼,但是,他也可以跟認證密碼的方式一樣,將可能的候選密碼,經過一樣的演算法得到一組digest,接著再比對此digest跟他取得的digest是否相符,倘若相符,便代表候選密碼沒有意外的話,就是原始密碼。

利用這種方式,有心人士其實可以基於暴力法,產生很多組可能的候選密碼,再分別計算出其digest,如此一來,只要產生的大量候選密碼中,恰好命中原始密碼,那麼,便能夠找出來digest所對應的原始密碼。

為什麼須要求使用者輸入較複雜的密碼?
許多破解密碼檔的程式,都會基於一組字典檔(dictionary file),來做為產生候選密碼的基礎。在這組字典檔案裡可能記錄了常見的英文單字、時常用來做為密碼的字。基於這組字典檔,再搭配一些動態的產生原則,例如搭配數字1、12、123、1234等等,便可以產生出許多的候選密碼。

如果使用者的密碼,恰好是落在字典檔裡的字,或者是可以依據字典檔產生出來的,那麼,一旦密碼資訊被取得,即使用夠好的hashing algorithm處理過,僅記錄使用者密碼的digest,有心人士只要有充足的時間,便可以基於字典檔,利用暴力不斷產生各種可能密碼的方式來嘗試,還是有可能找到digest對應的原始密碼。

以前有過一次經驗,曾經取得某個網站的使用者密碼資訊來進行分析。有趣的是,我們還有另一張表,裡頭記載了常見的密碼及其對應的MD5 digest。分析了一下,這個網站中的使用者密碼digest,有很高的比例,都可以在這張表裡找到。這意謂著倘若網站的使用者密碼資訊被取得,只要採取暴力法,很容易就可以找到這個網站許多使用者的密碼。

現在很多系統會規定,使用者設定的密碼必須具備一定的強度,像是密碼的長度、以及必須混合數字、而且不能是單純的英文單字之類的,其實便是希望提升使用者密碼選用上的安全性強度。任何一個系統都有可能被破解,系統所記錄下來的密碼資訊,還是有可能被取得。針對密碼資訊有了一定安全性的保護之外,倘若密碼本身強度不足,那麼,仍然有可能被輕易計算出原始的密碼。

不同的系統需要不同的安全性層級,倘若你所要設計的系統,需要考慮即使所記錄的密碼資訊被取走,仍然能夠維持一定的安全性的話,那麼,除了利用適當的演算法處理所記錄下來的密碼資訊之外,也會需要為使用者的密碼內容設下一定的限制,否則,還是會存在一定的風險。

作者簡介


Advertisement

更多 iThome相關內容