為了安全起見,許多重要系統都要求必須成功通過兩階段認證(Two-step Verification)才允許登入,藉此讓系統的防護更加地周全。本文將以SSH伺服器為例,利用google-authentication搭配Linux系統上PAM(可插拔式認證模組)來實作一個兩階段認證系統。
隨著資訊安全意識的抬頭,對於系統的資安要求也日趨嚴格。為了安全起見,有許多機敏的系統採用兩階段認證(Two-step Verification),在現有單純的帳號密碼驗證外,另外再加上一次性密碼(One Time Password,OTP)的驗證,必須經過兩個階段都認證成功後,才允許登入至系統,藉此來確保系統更加的安全。
何謂一次性密碼
一次性密碼(OTP)指的是,在每次登入時都會動態產生一個具有時效性(例如一分鐘內有效)的唯一密碼。常見的有:
Challenge/Response(挑戰回應型)
由伺服器隨機選擇一個數值(此數值稱為Challenge),接著傳送給使用者一次性密碼產生裝置,之後再根據此數值來產生動態密碼。在產生動態密碼後,使用者再將密碼傳回伺服器端進行身分認證(Response)步驟。
Time-Base(時間型)
動態密碼的產生,是基於時間資訊(Time stamp)。因此隨著時間流逝,每次產生的動態密碼也不同。但使用此方式要特別注意系統與一次性密碼產生裝置的時間不可差距過大,否則可能會驗證失敗。
在本文中,將以Centos 8系統(以下稱Linux系統)中的SSH伺服器為例進行實際操作示範,利用google-authentication搭配Linux系統上的PAM(Pluggable Authentication Modules,可插拔式認證模組)實作一個兩階段認證系統。
什麼是PAM
PAM(Pluggable Authentication Modules)最早是由Sun提出的一種認證機制。就如同其名稱一樣,利用透過一套統一的存取方法,讓系統所提供的服務(Service)以及該服務的認證方式分開,使得系統管理員可以更加靈活地配置不同的認證方式給不同的服務而無須更改其服務的原始程式。
以Linux系統上的SSH服務為例,一般在登入SSH伺服器時,均須輸入使用者帳號及密碼等相關資訊來進行身分認證,一旦確認為合法使用者,即可登入。但如果想要增加雙認證功能,例如在登入時,不僅須輸入合法的帳號密碼進行驗證,甚至會要求輸入一次性的密碼來做雙重驗證。
如果採用傳統的驗證方式,在更換認證方式時,勢必要重新改寫相關驗證程式碼並且必須重新編譯。但若採用PAM模組驗證模式,就可像積木一樣,僅須在SSH服務認證加上一次性密碼的驗證功能,即可在無須重新更動SSH服務原始程序的情況下,另外為SSH服務加上一次性密碼的驗證功能。
PAM模組允許系統管理員透過設定組態檔的方式,來動態指定服務可使用那些認證方式,例如以帳號∕密碼方式驗證。
以Linux系統為例,針對服務所配置的認證服務組態檔通常位於「/etc/pam.d」目錄下,通常該目錄下的各個檔案名稱即表示所設定的服務,例如圖1中的sshd即表示為設定ssh服務的認證服務。
接著說明PAM組態檔格式,如圖2所示,為設定SSH服務(sshd)的組態內容。
每列格式可分為下列欄位:
[模組類型] [控制符號] [模組的路徑] [額外參數]
模組類型
PAM允許同一個服務可以使用多個PAM模組類型來進行認證,而這些模組可構成一個堆疊(Stack),其相關模組類型說明如下:
‧auth:對使用者所提供的認證資訊實際進行驗證,例如檢查使用者所輸入的帳號及密碼資訊,以判別是否為有效的使用者。
‧account:有點類似對帳號有效性的資格審查,auth模組是用來檢查驗證資料的正確性,而此類型則是用來確認帳號的有效性(例如驗證帳號是否過期,或利用帳號來源端來決定是否要限制存取等等)。
‧password:實際配置更新認證。例如當使用者更改密碼後,即可同步更新使用者密碼資訊。
‧session:此類型被用來當做使用者在使用帳戶前的初始化工作,例如安裝使用者的家目錄、使用者的電子郵箱等工作。
控制符號
用來設定當PAM模組驗證成功或失敗之後所須執行的動作,相關控制符號如下所述:
‧required:當帶有required標記的模組都驗證成功後,才會回傳成功的訊息,但即使是前一個required模組驗證失敗,仍會繼續延續執行相關模組的驗證,直到所有的模組都驗證完成後,才會回傳最終的結果。
‧requisite:就如同required一樣,一旦requisite返回成功後,用戶才能通過驗證。但最大不同的地方在於,當其驗證失敗就不再執行往後的其他驗證模組,而是直接回覆驗證失敗。
‧sufficient:只要有一個帶有sufficient標記的模組驗證成功,便會直接回覆成功,而不須繼續執行其他的驗證。但要特別注意的是,即使sufficient驗證失敗,也不會影響到整體的驗證執行結果,亦即當sufficient驗證失敗時,可將sufficient模組視為optional,不會對整體的驗證結果產生影響。
‧optional:當帶有該標記的模組失敗後,將繼續處理下一模組,也就是說,帶有此標誌的模組之驗證結果不會影響到最後的驗證結果。
‧substack:就如同include,用來包括其他的設定檔並執行該設定檔內的驗證模組,但最大的不同在於所包括的設定檔內有requisite的設定時,如果驗證失敗,並不會直接回覆失敗給應用程式。
模組的路徑
在此選項中即設定實際執行認證的模組程式,相關位置通常位於「/lib/security/」或「/lib64/security/」目錄下,其檔名大多以pam開頭。
額外參數
此為可選項,可在此針對相關認證模組設定相關額外的參數。
在簡單了解PAM的機制原理後,接下來將安裝Google所提供的雙認證軟體,並搭配PAM機制,為Linux系統上的SSH服務加上雙認證功能,讓使用者在登入SSH服務時,除了原先需要輸入帳號及密碼資訊來做驗證外,還要輸入google-authentication在當下所產生的一次性密碼。經過兩階段驗證後,才可登入到系統。
實作google-authentication(Google身分驗證器)
Google早在2010年就釋出google-authenticator-libpam(官方網址是https://github.com/google/google-authenticator-libpam),此軟體支援HOTP(HMAC-based One Time Password)和TOTP(Time-based One Time Password)。HOTP是基於雜湊訊息驗證碼(HMAC)的一次性密碼演算法,而TOTP則為基於當前時間及預先設定的金鑰計算一次性密碼的演算法。
在Linux系統安裝Google-authenticator-libpam之前,必須先在手機(Android系統)上安裝Google Authenticator應用程式(App)(可利用Google商店查詢),此軟體是用來顯示google-authenticator所產生一次性密碼的資訊,以便使用者利用此App來取得一次性密碼的資訊。
在安裝好Google Authenticator之後,即可至Linux系統上以下列指令安裝相關軟體(其中#為註解):
yum install qrencode #用來產生驗證用的QR Code yum install google-authenticator #安裝google-authenticator
安裝完成後,便會產生pam_google_authenticator.so驗證程式(位於「/lib64/security/」目錄下)及google-authenticator(主程式,用來設定相關組態)。
接下來,說明google_authenticator所提供的額外常用選項,相關說明如表1。
在簡單了解google_authenticator後,接著設定SSH服務,讓該服務可使用google_authenticator的驗證功能。
首先設定「/etc/ssh/sshd_config」(其中#為註解說明):
challengeResponseAuthentication yes #表示使用挑戰-回應(challenge- Response)型密碼 UsePAM yes # 表示使用PAM機制管理
然後,即可繼續設定SSH服務的PAM組態設定。
一開始先設定「/etc/pam.d/sshd」,並在該檔案加入下列設定:
#表示要使用google_authenticator的驗 證功能 auth required pam_google_authenticator. so nullok
在完成SSH服務相關設定後,就可以執行google-authenticator來產生相關組態檔。執行之後,將會產生一個連結並等待輸入認證碼,使用瀏覽器瀏覽此連結,便會發現有一個QR Code的圖案。
接下來,使用手機「android google_authenticator」的掃描QR Code功能,就會得到認證碼。
輸入認證碼之後,將詢問一連串問題,基本上均回應預設答案即可。完成設定後,即表示已綁定該系統,使用者可由手機取得該系統的一次性密碼資訊。
最後,就會將相關設定儲存在使用者家目錄下的「.google_authenticator」檔案之中,如果是以root使用者為例,就是儲存在「/root/.google_authenticator」檔案內。
要特別提醒的是,在執行過程中,google-authenticator會產生幾組緊急碼(Emergency)以供使用者因故無法取得一次性密碼時使用。
另外,由於google-authenticator預設採用TOTP演算法來產生一次性密碼,因此Linux系統上的時間最好與手機的時間不要差距過大,以避免可能產生無法匹配的一次性密碼。
在一切就緒後,即可重啟SSH服務,執行如下指令:
systemctl restart sshd.service
接下來,嘗試登入SSH伺服器,便會發現需要兩個階段的驗證程序,如圖3所示,其中Verification Code的資訊就可以透過手機上的「google_authenticator App」來取得。
實作至此,兩階段的驗證就已經順利地完成了。
<本文作者:吳惠麟,多年資安經驗,喜好利用開源碼建構相關解決方案,著有「資訊安全原理與實驗」等書。>