PAM: 你是誰啊?
你的金光驚醒了石頭的酣夢!
2
總體描述
Linux身份鑒別機制是保護作業系統安全的重要機制之一,是防止惡意使用者進入系統的一個重要環節。早期的身份鑒別機制就是傳統的UNIX身份鑒別機制,它採用口令加密並與原密碼進行對比的方式來對使用者身份進行鑒別。但是這種加密方式過於單一,在一個服務中使用者的帳號密碼洩露會涉及到多個服務的安全性,所以為了增強系統的安全性,出現了許多其他的身份鑒別機制,如指紋認證、USB認證等。但是這樣導致了一個問題,為了應用這些認證機制,就需要重新編寫並編譯應用程式(如系統登陸服務login)。為瞭解決這個問題,1995年Sun公司的Vipin Samar和 Charlie Lai提出了PAM(Pluggable Authentication Modules)身份鑒別機制,它採用模組化設計和外掛功能,使得系統在更改認證機制時不再需要修改應用程式,極大的提高了認證機制的靈活性。本報告對Linux各使用者帳號的許可權區別進行了分析,對傳統UNIX身份鑒別機制的實現過程進行了研究,重點對PAM身份鑒別機制的實現過程進行了研究與分析,最後透過一個具體的PAM策略演示場景實現了身份鑒別機制的執行過程,研究結果也發現Linux身份鑒別機制是在Linux使用者態下實現的,並不涉及內核的具體實現。
由於Linux身份鑒別機制是在使用者態下實現,本報告涉及的原始碼包括Linux-PAM-1.1.6,openpam和Linux su命令的實現。具體範圍說明如下:
-
Linux-PAM-1.1.6/moudles/pam_access.c:登入認證模組的實現原始碼。
-
Linux-PAM-1.1.6/libpam:PAM所用的頭檔案。
-
openpam/lib/pam_acct_mgmt.c:賬號管理介面函式實現。
-
Linux su命令:Linux系統命令原始碼包。
Linux身份鑒別機制就是對請求服務的使用者身份進行鑒別,並且賦予相應的許可權的過程。本文透過查閱資料,分析Linux系統中對各使用者帳號的管理及其許可權分配,分析傳統的UNIX身份鑒別機制,以su命令的程式碼實現來進行說明,著重分析PAM身份鑒別機制,並對其程式碼實現來進行分析說明。
在Linux系統中,系統設定了多個帳號和組來進行管理,每個帳號都具有不同的許可權,例如超級使用者root就具有最大的許可權,對所有的檔案具有讀寫執行的許可權,但是普通使用者對某些檔案只具有讀有時甚至連讀的許可權都沒有。Linux作業系統並不是以帳號名稱來識別使用者的,而是以識別符號UID和GID來辨別使用者的,這些帳號的資訊都存放在/etc/passwd檔案當中,該檔案中記錄的每個帳號資訊是以行來表現的,如下所示:
root:x:0:0:root:/root:/bin/bash
每行是以7個欄位來描述的,每個欄位以冒號來進行分隔,其中對應欄位的依次解釋如下:
1. 帳號名稱:用來對應UID。
2. 密碼:所有的使用者都有對該檔案的訪問許可權,為了防止密碼竊取,就將這個欄位的密碼資料改放到/etc/shadow中了,所以這裡顯示的是X。
3. UID:使用者識別符號,表1-1列出了redhat系統中UID號的限制。
表1-1 UID限制
Id範圍 |
該使用者ID特性 |
0(系統管理員) |
當UID為0時,代表這個帳號是“系統管理員”!所以當你要讓其他的帳號名稱也具有root許可權時,將該帳號的UID改為0即可。一個系統上面的系統管理員不見得只有root.不過不建議有多個。 |
1~499(系統帳號) |
保留給系統使用的ID,其實除了0之外,其他的UID許可權與特性並沒有不一樣。預設500以下的數字讓給系統作為保留帳號只是一個習慣。1~99:由distributions自行建立的系統帳號;100~499:若使用者有系統帳號需求時,可以使用的帳號UID。 |
500~65535 |
給一般使用者使用的 |
4. GID:使用者組識別符號,具體資訊存放在/etc/group中。
5. 使用者資訊說明列:解釋這個帳號的意義。
6. 主檔案夾:即使用者的主檔案夾。
7. Shell:當使用者登入系統後就會取得一個shell來與系統的核心通訊以進行使用者的操作任務(一個shell可以用來替代成讓帳號無法取得shell環境的登入操作/sbin/nologin)。
/etc/shadow中也是這樣的欄位,具體欄位的意義這裡不再做詳細解釋,這個檔案主要是為了增加系統安全性而另外設定用來存放使用者的密碼,只有root使用者才有許可權訪問,但是為了安全性顯示的仍然是加密後的密碼。
系統是透過UID、GID來對不同的帳號進行區分的,但是系統中是如何對應實現具體的許可權設定的呢?這裡就從檔案的許可權來進行說明。執行ls -al命令後,結果如圖1-1所示。
圖1-1 檔案屬性
每行顯示內容分為七列:第一列代表這個檔案的型別與許可權,第二串列示有多少檔案名連結到這個節點,第三串列示這個檔案的所有者的帳號,第四串列示這個檔案的所屬使用者組,第五串列示這個檔案的容量大小,預設單位為B,第六列為該檔案的建立檔案日期或者是最近的修改日期,第七列為該檔案名。
第一列中總共有10個字元,這10個字元解釋如下:
1. 第一個字元為[d],表示為目錄,為[-]則是檔案,為[l]則是連結檔案,為[b]則表示裝置檔案裡面的可供儲存的介面裝置,為[c]則表示裝置檔案裡面的串列埠裝置,比如鍵盤、滑鼠等。
2. 接下來都是以三個字元為一組,一共有三組,且每組都是以“rwx”這樣的形式組合,其中[r]代表刻度,[w]代表可寫,[x]代表可執行,如果沒有該許可權則會用[-]來表示。第一組是檔案所有者的許可權,第二組為同組的許可權,第三組為其他非本使用者組的許可權。這樣就把檔案的可讀屬性與不同使用者帳號的許可權對應起來了。
傳統的UNIX身份鑒別即口令認證方式,它主要透過識別使用者的使用者名稱或者UID號獲取在/etc/shadow中存放的對應使用者密碼密文等資訊,然後獲取使用者輸入密碼並採用crypt()函式對獲得的輸入密碼進行加密,當然加密方式是與原使用者密碼的加密方式是一致的,然後將這兩個密文進行比較,如果一致則透過驗證,如果不一致則拒絕賦予許可權。接下來以登入Linux系統為例,說明登入過程中傳統UNIX認證方式對使用者帳號的鑒別過程。Linux使用者在登入主機時會出現一個輸入賬號及密碼的介面,Linux會先找尋 /etc/passwd 裡面是否有這個賬號,如果拒絕使用者登入請求,如果有的話則將該賬號對應的 UID 、GID、該賬號的主目錄與shell設定 一併讀出,接著就是將使用者輸入密碼進行加密,然後讀取/etc/shadow 中存放的密碼,將這個密碼與使用者輸入並加密的密碼進行核對,如果核對成功,則進入系統。
Linux 提供getpwnam()來獲取使用者登入的相關資訊,傳回的是一個passwd型的結構體,該結構體就包含了使用者帳號的各種資訊,該結構體如下所示。
PAM(Pluggable Authentication Modules)即可插拔驗證模組,它是一個非常完善的身份驗證機制,它採用模組化設計和外掛功能,從而可以輕易的在應用程式中插入新的鑒別模組或者替換原來的元件,而不必對應用程式做任何修改,從而使軟體的定製、維持和升級更加輕鬆。PAM 的易用性較強,它對上層遮蔽了鑒別的具體細節,使用者不必詳細知道各種鑒別機制是如何實現的,它還實現了多鑒別機制的整合問題。
PAM 為了實現其外掛功能和易用性,採取了分層設計思想。就是讓各鑒別模組從應用程式中獨立出來,然後透過 PAM的API、 SPI作為兩者聯絡的紐帶,這樣應用程式就可以根據需要靈活地在其中“插入”所需要的鑒別功能模組,從而真正實現了在認證和鑒別基礎上的隨需應變。PAM框架如下圖所示:
其中的配置檔案(etc/pam.d)是由系統管理員來設定的,用以制定認證策略。當應用程式呼叫 PAM 的API 時,應用介面層按照 PAM 配置檔案的定義來載入相應的認證鑒別模組,然後把請求(即從應用程式那裡得到的引數)傳遞給底層的認證鑒別模組,這時認證鑒別模組就可以根據要求執行具體的認證鑒別操作了。當認證鑒別模組執行完相應的操作後,再將結果傳回給應用介面層,然後由介面層根據配置的具體情況將來自認證鑒別模組的應答傳回給應用程式。
上面簡單描述了PAM的運作方式,下麵對它的三個層次加以介紹:
1.最上層為應用程式層:使用PAM 機制的應用程式(如login、su等),呼叫PAM介面庫的上層介面API來實現認證功能;
2.中間為應用介面層:連線應用程式和服務模組的中間層,它根據配置檔案中的設定載入相應的服務模組,將請求傳遞到具體的服務模組,嚮應用程式的開發者提供API使用各種鑒別模組,向鑒別模組的開發者提供SPI來掛載新的鑒別模組;
3.最下層為服務模組:服務模組中都為動態連結庫,它給應用程式提供具體的認證使用者服務,應用程式可以使用幾個服務模組。PAM所支援的四種任務管理:account 型別表示賬戶管理,它執行賬戶管理,它主要用來限制/允許使用者對某個服務的訪問時間,當前有效的系統資源(最多可以有多少個使用者),限制使用者的位置(例如:root使用者只能從控制檯登入);auth型別表示認證管理,對使用者進行認證。讓應用程式提示使用者輸入密碼或者其它的標記,確認使用者的合法性;透過它的憑證許可許可權,設定組成員關係或者其它優先權;password型別表示口令管理,用於更新與使用者相關的認證特性,如更改使用者密碼;session型別表示會話管理,用於進入給定的服務之前,或者離開給定的服務之後,需要進行的會話操作,如:儲存關於與使用者交換資料的log資訊、掛接目錄等。【3】
應用PAM的服務例程是透過讀取PAM的配置檔案初始化pam_handle這個控制代碼,用來記錄整個PAM的過程資訊例如服務名、介面傳遞引數等,定義服務的配置檔案存放在/etc/pam.d中,/etc/pam.conf也是pam的配置檔案,該配置檔案是老版本的配置檔案,目前所安裝的版本當中,如果有pam.d這個檔案就首要讀取這個檔案,若沒有再讀取pam.conf這個檔案,另外若所讀服務不存在相應配置檔案,此時系統會讀取other這個配置檔案的資訊,other這個配置檔案是所有服務的預設選項。pam.d中的配置檔案的語法形式如下:
module-type control-flag mudle-path arguments【3】
1.module-type:linux PAM 所提供的四種服務模組,包括auth、account、session、password;
2.control-flag:控制標誌用來設定驗證成功或者失敗後PAM需要做出的反應,有四個關鍵詞如下所示:
required:表示即使某個模組對使用者的驗證失敗,也要等所有的模組執行完成,PAM才可以傳回錯誤資訊,如此使用者就不知道被哪個模組拒絕了。
requisite:一旦模組對使用者的驗證失敗,PAM立馬傳回出錯資訊。
sufficient:一旦模組對使用者的驗證成功,PAM立馬傳回成功資訊,並把控制權交給使用者。
optional:PAM會忽略這個模組所產生的驗證錯誤,繼續執行下一個模組。
3.module-path:PAM驗證模組的路徑;
4.arguments:傳遞給模組的引數。引數是可選擇的,可以是讀取另外配置檔案的路徑資訊,也可以是各種模組所需的傳遞引數。以下列出pam_unix模組的引數資訊:
表1-2 pam_unix模組引數【3】
引數 |
說明 |
debug |
開啟除錯資訊,透過syslog寫入日誌系統 |
audit |
比debug記錄更為詳細的除錯資訊 |
nullok |
預設值下,如果使用者輸入的口令為空,則不允許使用者訪問服務,該引數改寫率這個預設值,即使不輸入口令就可以獲得服務 |
nodelay |
取消延遲,預設是2秒為延遲時間 |
try_first_pass |
提示使用者使用前面模組認證透過的口令,只適用於auth 型別 |
use_first_pass |
強制使用前面模組認證透過的口令,只適用於auth password型別 |
not_authok |
當口令改變時,強制模組設定新口令到以前模組提供的口令 |
md5 |
當使用者下次改變他們的口令時,使用md5演演算法加密口令 |
shadow |
維護shadow口令,即使用/etc/shadow儲存口令 |
unix |
當使用者更改密碼時,密碼被放置在/etc/passwd中 |
bigcrype |
當使用者下次改變口令時,使用DEC C2演演算法加密口令 |
nis |
使用NISRPC(遠端過程呼叫)設定新口令 |
Remember=x |
將每個使用者最後x個口令儲存在/etc/security/opasswd檔案中,用於強制口令更改歷史,以免使用者頻繁使用同一個口令 |
broken_shadow |
在account管理模組中讀取shadow口令時忽略錯誤 |
pam_conf配置檔案的寫法與pam.d中的配置檔案沒有太大的出入,只是在最前面多了一行具體的服務名稱,例如login,而pam.d中是將各種模組分開來寫,這樣更便於控制。
PAM提供了多種介面函式以供使用者使用,其中包括框架API【4】、服務型別的API和服務模組SPI。
框架API:
每個支援PAM機制的應用程式在使用PAM機制之前必須呼叫函式pam_start()初始化PAM背景關係和PAM事務,使用完後呼叫pam_end()來結束PAM機制,透過pam_get_item、pam_set_item()來讀寫PAM事物的狀態資訊,透過pam_get_data()、pam_set_data()來取得和設定PAM模組及會話的相關資訊,透過pam_putenv()、pam_getenv()、pam_getenvlist()來讀寫環境變數,透過pam_strerror()傳回相關的錯誤資訊;
服務型別的API:
1.認證管理模組透過pam_authenticate()對使用者名稱和密碼進行認證,透過pam_setcred()用來修改使用者的信任引數,建立數字認證;
2.賬戶管理模組透過pam_acct_mgmt()來檢查使用者本身是否具有許可權登入系統、賬戶是否過期、賬戶是否有登入時間限制等;
3.密碼管理模組透過pam_chauthtok()來修改使用者的密碼;
4.會話管理模組透過pam_open_session()來開始會話,以pam_close_session()來結束會話;
PAM中的API與SPI詳細解釋如表1-3所示。
表1-3 PAM中API以及SPI【3】
服務管理型別 |
PAM API |
PAM SPI |
說明 |
account |
pam_acct_mgmt() |
pam_sm_acct_mgmt() |
檢查認證特性、賬戶有效期和驗證訪問控制 |
authentication |
pam_authenticate() |
pam_sm_authenticate() |
根據認證特徵認證使用者 |
pam_setcred() |
pam_sm_setcred() |
在認證後會話前呼叫,用來修改使用者的信任引數,如:uid gid |
|
passwd |
pam_chauthtok() |
pam_sm_chauthtok() |
用於改變給定使用者的認證特徵 |
session |
pam_open_session() |
pam_sm_open_session() |
為認證成功的使用者建立會話 |
pam_close_session() |
pam_sm_open_session() |
結束會話 |
【1】鳥哥的私房菜.人民郵電出版社.2010.
【2】Linux安全策略與實體.李洋等.機械工業出版社.2009.
【3】Linux安全體系分析與程式設計.倪繼利.電子工業出版社.2007.11
【4】The Linux-PAM Application Developers’ Guide
更多精彩推薦,請關註我們
▼