Unix – Shadow Password

這裡討論的內容以 FreeBSD 為主,可能會與 linux 系的不同。

Shadow Password 簡單來講說就是將真正的密碼存在另一份檔案, 原來的那一份「密碼檔」裡面其實並沒有包含密碼的資訊。

比如說在 FreeBSD 的「/etc/passwd」這個檔案,裡面有各個使用者的資訊, 包含使用者名稱、家目錄、使用的 Shell等,但就是沒有包含密碼內容, 而真正的密碼是放在「/etc/master.passwd」裡,只有 root 才能查看。

話又說回來,既然 root 可以查看「/etc/master.passwd」的內容, 那豈不是就知道所有人的密碼了嗎?那這樣還有誰敢登入?

當然不!

這裡首先要知道 FreeBSD 的密碼系統是怎麼運作的,使用者輸入密碼後, 輸入的密碼會先經過 hash 後,才比對「/etc/master.passwd」裡的值是不是相同,若是相同, 就表示輸入的密碼正確,是真正的使用者,因為密碼正確。也就是說, 「/etc/master.passwd」存放的其實也不是真正的密碼,而是 hash 過後的值。

hash 指的是單向雜湊函式,這種函式的特點就是單一方向運算很簡單, 但反方向推算卻非常困難。也就是說,我可以把一個值轉換成另一個值, 但我很難把值轉換回來。而且原則上,這種函式不同值轉換的值幾乎不會重覆。

這種函式非常適合用來儲存密碼,因為我們無法從 hash 過的值推算回密碼, 所以就算 root 可以看到這份密碼檔,還是不會知道實際的密碼是什麼 (雖然不知道密碼,但 root 還是可以改你的密碼,畢竟 root 是神呀~).

而且不同的密碼幾乎不會產生同樣的 hash 值, 所以我們可以直接比對 hash 值是否相同來判斷使用者是不是打了正確的密碼。

順帶一提,真正運作時,系統還會在使用者輸入新的密碼時,隨機產生一個數字(稱作 salt),添加進密碼中, 所以就算是同樣的密碼,可能 hash 出來的結果也都會不同。當然這個隨機產生的數字還是要存進去才行。

「/etc/master.passwd」儲存密碼的時候,共有三個欄位,由 $ 分隔,其格式如下:

$id$salt$encrpted
Code language: PHP (php)

id 指的是用什麼 hash function,若為 1 則是採用 MD5,第二個則是產生的隨機數字,最後一項才是 hash 出來的值, 詳細資訊可以查詢 crypt(3)

在「/etc/login.conf」中,可以設定要使用的 hash 函式,比如說 MD5。

passwd_format md5

舉例來說:

>>> cat /etc/master.passwd | grep marco marco:$1$65Y.0rv4$PLzeceW8U4rDbA2ZSorLQ0:1001:1001::0:0:marco li:/home/marco:/bin/tcsh
Code language: JavaScript (javascript)

「那為什麼要將密碼存在另一個檔案呢?反正我也沒辦法由 hash 猜到別的使用者的密碼呀?」

理由是使用者的密碼通常不會太複雜,常常就是那幾個字, 可能性其實不夠多,所以若我可以看到密碼 hash 過後的值, 我還是有機會從 hash 猜到真正的密碼是什麼。

為了減少發生問題的可能性,最實在的辦法就是讓使用者連看都看不到, 不過話說如此,也不能把「密碼檔」的讀取權限拿掉,讓使用者看不見「密碼檔」, 因為上面還包含很多資訊是要讓使用者知道的,所以就另外產生一個檔案來存放密碼, 而且這個檔案除了 root 外,其他人都看不到內容, 這種把檔案分成兩個的方式就是「Shadow Password」的機制。

檔案說明
/etc/passwd密碼檔,包含使用者的相關資訊
/etc/master.passwd真正存放密碼的檔案(不同作業系統,可能名稱會不太一樣)

為什麼要用「Shadow Password」呢?其實理由我也不清楚, 這裡寫的理由是我在網路上看到的一個說法,不知道是不是正確的,不過不重要, 重要的是理解這是在幹麻就行了。話說回來,我覺得這不是好理由, 因為一開始就不要在密碼檔放個人資訊就好了呀?也許是歷史遺毒的關係吧?。

發表迴響