借助OTPW配置一次性密碼驗證
譯文密碼驗證涉及安全和信任方面的許多假設(shè)。經(jīng)過加密的SSH隧道和公開密鑰驗證則是確保密碼在傳輸過程中不受到危及的兩種常用方法。不過要是你目前所使用的這臺計算機不可信任,那該如何是好?
這絕非小心謹慎的人擔(dān)心的一種易受攻擊的場景。在許多平常情況和常見地方,你可能不該使用系統(tǒng)密碼,哪怕是通過一條安全隧道。例子包括如下:
◆酒店、圖書館或網(wǎng)吧里面的公共計算機;
◆同事被感染了病毒的計算機;
◆結(jié)對編程時所使用的共享工作站;
◆別人有可能看到你鍵入密碼整個過程的任何地方。
上述這些例子有何共同之處呢?共同之處就是,實際上,你試圖從一個不可信任的來源連接至可信任的目的地。這完全有悖于設(shè)計大多數(shù)驗證系統(tǒng)的初衷。
就拿公開密鑰驗證來說。SSH公開密鑰驗證無疑繞過了遠程主機上的密碼提示,但是它仍需要你把你的私有密鑰密碼交給本地機器。此外,一旦密鑰用你的密碼來解密,本地系統(tǒng)就可以完全訪問里面的敏感密鑰內(nèi)容。
幸好,已經(jīng)有一種辦法可以解決這個經(jīng)常被人忽視的問題:那就是一次性密碼。
SSH和一次性密碼這對組合具有強大的功能:
◆SSH協(xié)議提供了跨整個網(wǎng)絡(luò)對登錄順序進行加密的機制。
◆良好的SSH客戶端讓你可以在輸入登錄資料之前,先檢查遠程主機的公開密鑰指紋。這可以防止未授權(quán)主機收集你的一次性密碼。
◆一次性密碼體系確保了密碼無法被重復(fù)使用。所以,就算某個密碼在傳輸過程中被獲取,一旦你用該密碼登錄上去,這個密碼對攻擊者來說也是毫無價值的。
類似UNIX的系統(tǒng)有許多一次性密碼解決方案。兩種最有名的解決方案是S/KEY和OPIE(每件事情的一次性密碼)。
由于OPIE最近從Debian和Ubuntu儲存庫中移除后,由德國計算機科學(xué)家Markus Kuhn開發(fā)的OTPW一次性密碼體系提供了一種切實可行的替代方案。雖然OTPW并非直接替代OPIE,但它提供了同類功能,同時提供了S/KEY或OPIE所沒有的一些令人關(guān)注的特性。#p#
從Debian和Ubuntu儲存庫移除OPIE
Debian在2011年年初開始移除與OPIE有關(guān)的程序包,起因是二進制程序的安全性、許可問題和缺少上游活動等方面引起了一番討論。
如果你有興趣想了解具體細節(jié),可以參閱下列相關(guān)的Debian錯誤報告:
◆http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=511582
◆http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=622220
◆http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=622221
◆http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=622246
雖然截至截稿時,OPIE程序包仍然在目前的Debian穩(wěn)定版本(代號為"Squeeze")中,Debian端口(debports)儲存庫里面也有一些非正式的平臺端口,但OPIE并未出現(xiàn)在測試版或非穩(wěn)定版中,它也似乎不太可能添加到下一個隱私版本中。
尤其是,OTPW提供了下列功能:
◆雙因子驗證,由"前綴密碼"和一組自動生成的、一次性的后綴組成。就算后綴列表落到了壞人的手里,要是沒有前綴密碼,那也少不了蠻力攻擊。
◆通過使用密碼鎖和三重質(zhì)詢(triplet challenge),防范某些競爭條件和中間人攻擊。
◆支持共享式文件系統(tǒng)。由于OTPW對照存儲在用戶主目錄里面的散列值列表來檢查密碼,所以一次性密碼列表適用于掛載同一$HOME目錄的所有系統(tǒng)。
接下來將介紹OTPW的安裝和使用,并特別著重介紹與OpenSSH的集成。
程序包安裝
想使用OTPW,你就需要兩個二進制程序:otpw-bin和libpam-otpw。就Debian和Ubuntu而言,安裝很容易,只要執(zhí)行這個命令:
sudo apt-get install otpw-bin libpam-otpw
如果你的發(fā)行版并不提供OTPW,可以直接從開發(fā)者的主頁下載源代碼。源打包文件并不使用GNU自動配置(autoconf)工具,所以你需要按照開發(fā)者的操作說明,手動編譯和安裝二進制程序。
配置可插拔驗證模塊(PAM)
讓系統(tǒng)為OTPW作好準(zhǔn)備的下一步是,配置libpam-otpw。全面處理PAM不在本文的探討范圍之內(nèi),但我還是會在這里介紹幾種最常見的使用場合。
改動PAM配置會你讓無法使用你的工作站或服務(wù)器,所以一個好主意就是,讓你現(xiàn)有的終端保持開放狀態(tài),直到你確信一切都正常工作。如果你可以訪問控制臺,手邊要備一份可啟動的發(fā)行版或挽救盤。想了解通過SSH測試PAM方面的更多信息,請參閱《借助SSH,測試一次性密碼驗證》這篇附文。#p#
借助SSH,測試一次性密碼驗證
如果你在為OTPW配置一個遠程系統(tǒng),應(yīng)該在不關(guān)閉目前SSH連接的情況下測試PAM堆棧。切記:如果你在PAM配置上出現(xiàn)了錯誤,即便有權(quán)訪問控制臺,也可能無法驗證--所以手邊要備一份可啟動的發(fā)行版,比如Knoppix、SystemRescueCD或Finnix,以防萬一。與此同時,現(xiàn)有的登錄仍然不受到影響,因為它們已經(jīng)通過了驗證。
為了正確測試PAM堆棧,你不能重新使用現(xiàn)有的SSH連接。大多數(shù)最新的發(fā)行版在默認情況下都支持SSH多路復(fù)用和持久性連接,所以要明確禁用這些選項以便測試。
此外,SSH在默認情況下偏愛公開密鑰驗證。所以,為了測試OTPW驗證,公開密鑰驗證同樣需要臨時禁用。
下面這個調(diào)用能夠正確測試SSH PAM堆棧,不需要對系統(tǒng)做任何改動:
read -p 'Hostname: ' REMOTE_HOST &&
SSH_AGENT_PID= SSH_AUTH_SOCK= \
ssh \
-o PreferredAuthentications=keyboard-interactive \
-o ControlPersist=no \
-o ControlPath=none \
"$REMOTE_HOST"
一旦你確信OTPW在正常工作,還應(yīng)該驗證你的其他驗證機制(即SSH公開密鑰和平常的系統(tǒng)密碼)繼續(xù)正常工作。
啟用OTPW的最容易辦法就是把它直接放在common-auth配置文件中pam_unix的前面:
# /etc/pam.d/common-auth
auth sufficient pam_otpw.so
session optional pam_otpw.so
auth sufficient pam_unix.so nullok_secure
auth required pam_deny.so
PAM庫的順序非常重要。如果把OTPW放在第一位,擁有~/.otpw文件的用戶會首先得到一次性密碼的提示,要是OTPW登錄失敗,允許退回到標(biāo)準(zhǔn)的系統(tǒng)密碼。沒有~/.otpw文件的用戶只會看到標(biāo)準(zhǔn)的密碼提示。
如果你更喜歡順序倒過來,在退回到一次性密碼之前提示系統(tǒng)密碼,只要確保pam_deny放在最后一位:
# /etc/pam.d/common-auth
auth sufficient pam_unix.so nullok_secure
auth sufficient pam_otpw.so
session optional pam_otpw.so
auth required pam_deny.so
如果你忍不住想完全移除標(biāo)準(zhǔn)的系統(tǒng)密碼,尤其是控制臺登錄時所用的系統(tǒng)密碼,千萬別這么做。在一些系統(tǒng)上,尤其是在擁有ecryptfs-encrypted主目錄的Ubuntu系統(tǒng)上,要是沒有標(biāo)準(zhǔn)的系統(tǒng)密碼,想從OTPW故障恢復(fù)過來極其困難。
改動common-auth通常是在無外設(shè)服務(wù)器或只有控制臺的系統(tǒng)上要做的正確操作。不過,提供X Window System的工作站或服務(wù)器給一次性密碼體系帶來了特殊的問題。
一些工具或應(yīng)用程序無法與OTPW順利協(xié)同運行,原因是它們無法把質(zhì)詢顯示給用戶。典型的癥狀通常是,出現(xiàn)了永遠無法完成或似乎忽視用戶輸入的密碼對話。在過去,gksu和GNOME顯示管理器(GDM)結(jié)合OPIE使用時有這個問題。這種情況下,解決辦法就是從common-auth移除OTPW,只把它添加在特定的服務(wù)中。
比如說,你可以把OTPW驗證添加到SSH連接,同時針對控制臺或GUI登錄就使用標(biāo)準(zhǔn)的密碼提示。只要三個簡單步驟,就能做到這一點:
1. 從common-auth刪除引用pam_otpw.so的任何行:
# /etc/pam.d/common-auth on Debian Squeeze
auth sufficient pam_unix.so nullok_secure
auth required pam_deny.so
2. 為PAM創(chuàng)建一個新的OTPW包含文件:
# /etc/pam.d/otpw
auth sufficient pam_otpw.so
session optional pam_otpw.so
3. 在/etc/pam.d/sshd中的common-auth前面添加OTPW:
# 其他內(nèi)容……
# 啟用OTPW驗證。
@include otpw
# 標(biāo)準(zhǔn)的Un*x驗證。
@include common-auth
# 更多內(nèi)容……
SSH配置
除了配置PAM庫外,OTPW在SSH守護程序的配置文件中還需要下列三個設(shè)置:
# /etc/ssh/sshd_config
UsePrivilegeSeparation yes
UsePAM yes
ChallengeResponseAuthentication yes
這些設(shè)置通常就在那里,但是可能被注釋掉了或者被設(shè)置成"no",所以要作相應(yīng)改動。下一步,改動配置文件后,重新裝入SSH守護程序:
# 普通Linux
sudo /etc/init.d/ssh reload
# Debian 6.0.4+
sudo service ssh reload
# Ubuntu 11.04+
sudo reload ssh
#p#
生成OTPW密碼
一旦OTPW PAM模塊已被正確配置,只有擁有~/.otpw文件的用戶在登錄過程中會遭到一次性密碼對話的質(zhì)詢。除了只與質(zhì)詢的有效應(yīng)答匹配的單向散列列表外,該文件里面還含有關(guān)于其內(nèi)容的一些元數(shù)據(jù)。
想創(chuàng)建該文件,或者重新為它裝填新密碼,可使用otpw-gen實用工具。默認情況下,它會創(chuàng)建280個密碼后綴,格式經(jīng)編排后可以排列到單面信函紙(8.5" x 11")上。由于~/.otpw文件里面只存儲了單向散列,而不是密碼本身,密碼生成時,你必須捕獲或打印該命令的標(biāo)準(zhǔn)輸出。你無法事后獲取密碼列表,而是需要生成新的密碼。
下面是你首次運行該命令,將輸出發(fā)送到默認打印機所看到的樣子:
$ otpw-gen | lpr
Generating random seed ...
If your paper password list is stolen, the thief
should not gain access to your account with this
information alone. Therefore, you need to memorize
and enter below a prefix password. You will have to
enter that each time directly before entering the
one-time password (on the same line).
When you log in, a 3-digit password number will be
displayed. It identifies the one-time password on
your list that you have to append to the prefix
password. If another login to your account is in
progress at the same time, several password numbers
may be shown and all corresponding passwords have to
be appended after the prefix password. Best generate
a new password list when you have used up half of
the old one.
Enter new prefix password:
Reenter prefix password:
Creating '~/.otpw'.
Generating new one-time passwords ...
生成新密碼列表時,標(biāo)準(zhǔn)錯誤上出現(xiàn)的提示略有不同:
Overwrite existing password list '~/.otpw' (Y/n)?
Enter new prefix password:
Reenter prefix password:
Creating '~/.otpw'.
Generating new one-time passwords ...
第一個提示確保你沒有不小心覆蓋現(xiàn)有的密碼列表;第二個提示要求你輸入一個新密碼。沒有什么可以阻止你在每次調(diào)用時重復(fù)使用同一個前綴密碼--隨機種子使得重復(fù)散列不可能出現(xiàn),但是最好的做法還是每當(dāng)你重新生成密碼列表時,使用一個新的前綴。
如果你想在遠程主機上生成密碼列表,但是打印到本地輸出設(shè)備上,你可以通過SSH連接來做這一步,只要你信任你的本地主機:
read -p 'Hostname: ' &
注意使用stty以確保前綴密碼沒有回送到屏幕上。只要你的前綴密碼仍然是安全的,使用不可信任的輸出設(shè)備跟密碼列表落到壞人手里一樣沒有關(guān)系。對經(jīng)常出差的人來說,這常常是個實用的安全折中方案。
最后,想禁止對某個用戶實行OTPW質(zhì)詢,只要從該用戶的主目錄刪除.otpw文件即可。#p#
使用OTPW登錄
一旦你手里有了密碼列表,就可以準(zhǔn)備為你的SSH連接使用一次性密碼驗證了。假設(shè)你沒有將任何身份裝入到SSH代理里面,對話應(yīng)該類似這樣:
$ ssh localhost
Password 015:
帶數(shù)字的提示是OTPW質(zhì)詢。為了應(yīng)答,請在你之前打印的密碼清單上找到匹配的質(zhì)詢ID。接下來,輸入前綴密碼,后面跟著質(zhì)詢ID之后的字符串。
使用"foo"作為前綴密碼,生成下列后綴列表。就算你使用同一個前綴密碼,你的列表和后綴也會不一樣。
OTPW list generated 2012-05-06 13:40 on localhost
000 SWvv JGk5 004 =qfF q2Mv 008 sb5P h94r 012 o5aH +/GD 016 8eLV VxuA
001 xPZR :ceV 005 B=bq =mHN 009 WBSR smty 013 QMZ% +bm8 017 vjFL K4VU
002 Sj%n 9xD3 006 RrNx sJXC 010 Xr6J F+Wv 014 j=LO CMmx 018 Km8c 8Q3K
003 s7g8 NE%v 007 sd=E MTqW 011 fNKT vo84 015 fWI% MB9e 019 z8ui %eQ3
!!! 切記:先輸入前綴密碼!!!
為了成功應(yīng)答這個質(zhì)詢,在提示符處輸入:
foo fWI% MB9e
空格是可選的;如果有空格,OTPW會忽視。
如果你正確應(yīng)答了質(zhì)詢,登錄就會繼續(xù)下去。否則,你會得到使用標(biāo)準(zhǔn)系統(tǒng)登錄的提示。這時候,你可以輸入標(biāo)準(zhǔn)的系統(tǒng)密碼,或者按返回鍵,再試一下OTPW。在系統(tǒng)指定的密碼嘗試次數(shù)(通常是三次)之后,登錄失敗后,你就會回到命令提示:
$ ssh localhost
Password 013:
Password:
Password 013:
Password:
Password 013:
Password:
Permission denied (publickey,password,keyboard-interactive).
為了防止同時登錄,或者當(dāng)SSH在OTPW驗證過程中被中斷,OTPW可能會鎖定密碼。密碼被鎖定后,你下一次登錄嘗試就會實行三重質(zhì)詢,要求一個前綴和三個后綴來應(yīng)答:
$ ssh localhost
Password 004/011/005:
鑒于與前面一樣的密碼列表,將三重應(yīng)答作為一行來輸入,有無空格都沒關(guān)系。下面顯示了如何進行應(yīng)答(注意:下面第一行只是一種信息幫助;你只要輸入下面第二行,不帶管道符):
prefix | suffix 004 | suffix 011 | suffix 005
foo | =qfF q2Mv | fNKT vo84 | B=bq =mHN
一旦你成功應(yīng)答了三重質(zhì)詢,登錄就會繼續(xù)下去,~/.otpw.lock符號鏈接應(yīng)該會被刪除,你的下一個質(zhì)詢將再次是單一質(zhì)詢ID編號。
在一些情況下,無法正確清除密碼鎖。如果你繼續(xù)得到三重質(zhì)詢的提示,可以手動刪除鎖定文件:
rm ~/.otpw.lock
如果用戶擁有的經(jīng)過加密的主目錄在登錄之前沒有掛載上去,就需要采取另外幾個步驟。#p#
OTPW和經(jīng)過加密的主目錄
ecryptfs文件系統(tǒng)給SSH和OTPW帶來了特殊的問題。默認情況下,Ubuntu等發(fā)行版借助用戶的系統(tǒng)密碼,打開掛載經(jīng)過加密的主目錄所需的特殊口令短語(passphrase)。
這由pam_ecryptfs.so模塊來處理,可以通過/etc/pam.d/common-auth及其他來添加該模塊。如果你使用系統(tǒng)密碼之外的任何密碼來進行驗證,該模塊會提示你輸入系統(tǒng)登錄密碼,以便掛載經(jīng)過加密的主目錄。
實際上,這意味著掛載遠程主目錄時,你的系統(tǒng)密碼暴露在不可信任的終端上。這顯然不是很理想。
避免這個問題的最佳辦法就是,讓控制臺會話始終運行著。比如說,使用系統(tǒng)密碼登錄到控制臺,然后鎖定屏幕。只要你的控制臺會話仍處于活動狀態(tài),主目錄就仍然處于掛載狀態(tài)。因而,你可以使用OTPW驗證,無須對系統(tǒng)進行進一步的改動,也不會在登錄或掛載過程中泄露系統(tǒng)密碼。
然而,當(dāng)控制臺會話未運行時,如果你仍想能夠使用OTPW用于SSH登錄,又明白這么做對安全有何影響,下面教你如何來實現(xiàn)。
首先,你需要創(chuàng)建調(diào)用otpw-gen的包裝腳本:
#!/bin/bash
set -e
otpw-gen "$@"
mv ~/.otpw /usr/local/lib/otpw/$LOGNAME/
ln -s /usr/local/lib/otpw/$LOGNAME/.otpw ~/
包裝腳本應(yīng)該放在你的路徑中,并確保可以執(zhí)行。
下一步,把otpw4ecryptfs.sh(下面所列)放在~/bin或/usr/local/sbin中:
#!/bin/bash
# 用途:
# 為擁有ecryptfs-mounted主目錄的系統(tǒng)上所有用戶啟用OTPW。
set -e
# 暴露可能被ecryptfs隱藏的底層目錄。
sudo mkdir -p /mnt/real_home
sudo mount -o bind /home /mnt/real_home
# 收集所有非系統(tǒng)用戶。
users=$(
awk -F: '$1 != "nobody" \
&& $3 >= 1000 \
&& $3 < 65534 \
{print $1}' /etc/passwd
)
# 為每個非系統(tǒng)用戶啟用OTPW。
for user in $users; do
sudo mkdir -p /usr/local/lib/otpw/$user
sudo touch /usr/local/lib/otpw/$user/.otpw
sudo chown -R $user: /usr/local/lib/otpw/$user
sudo chmod 755 /mnt/real_home/$user
ln -sf /usr/local/lib/otpw/$user/.otpw \
/mnt/real_home/$user/
ln -sf /usr/local/lib/otpw/$user/.otpw \
/home/$user/
done < /etc/passwd
sudo umount /mnt/real_home
你運行該腳本后,它創(chuàng)建了可以由pam_otpw.so讀取的 OTPW文件,即使用戶的主目錄卸載后也能讀取。
請注意:該腳本為所有用戶的主目錄賦予了讀取和執(zhí)行權(quán)限,那樣pam_otpw.so就能讀取OTPW密碼文件。這本身不是一種風(fēng)險,但是依賴限制更大的目錄權(quán)限的用戶可能想之后立即加強其主目錄中文件和文件夾的許可權(quán)限。
最后,所有用戶都應(yīng)該運行otpw-gen-wrapper.sh,裝填和維護OTPW密碼列表。始終使用包裝腳本,而不是直接調(diào)用otpw-gen,否則密碼生成會破壞正確操作所需的符合鏈接。#p#
檢查剩余的密碼
如果你的密碼列表已用完,就再也無法使用OTPW來登錄,除非生成新的列表。同樣,如果你的密碼列表不含有至少三個未使用的應(yīng)答,~/.otpw.lock存在時,就無法使用OTPW來登錄,因為沒有足夠的質(zhì)詢ID來發(fā)出三重質(zhì)詢。
此外,OTPW的安全性一方面來自剩余質(zhì)詢具有的隨機性。使用三重質(zhì)詢特別會迅速用完你未使用的密碼,所以一旦數(shù)量降至最小數(shù)以下,重新生成密碼列表不失為是個好主意。
OTPW開發(fā)者建議:當(dāng)仍未使用的原始密碼不足一半時,應(yīng)該重新生成密碼列表,但不要定義質(zhì)詢的足夠隨機性所需要的最小密碼數(shù)量。少量未使用的密碼讓你更容易遭到蠻力攻擊,因為可供使用的質(zhì)詢比較少。
當(dāng)未使用的密碼降至所生成密碼數(shù)量的一半時,pam_otpw.so PAM模塊本該通知用戶。不過,PAM會話功能在Debian或Ubuntu上似乎無法正常使用。此外,就算能使用,該模塊也不會設(shè)立最小數(shù),以確保質(zhì)詢有足夠的隨機性。
代碼片段1所示的otwp-stats.sh腳本提供了這項缺失的功能。它還讓你可以定義合理的未使用密碼最小數(shù),只要調(diào)整腳本頂部的MIN_PASSWORDS變量。
代碼片段1:otwp-stats.sh
#!/bin/bash
# 30個未使用的密碼似乎是個合理的最小數(shù),可確保隨機性,并防止出現(xiàn)三重質(zhì)詢用完。
# 這個數(shù)字可隨意調(diào)整,以適合你的需要。
MIN_PASSWORDS=30
OTPW_LIST="$HOME/.otpw"
# 如果沒有為該用戶設(shè)置OTPW,就停止處理。
[ -f "$OTPW_LIST" ] || exit
# OTPW文件的最上面兩行是元數(shù)據(jù)。
TOTAL_PASSWORDS=$((`wc -l < "$OTPW_LIST"` - 2))
# 帶橫杠的行表示已使用的密碼。
USED_PASSWORDS=$(egrep '^-' "$OTPW_LIST" | wc -l)
# 剩余密碼的數(shù)量是個估算值。
PASSWORDS_LEFT=$((TOTAL_PASSWORDS - USED_PASSWORDS))
cat << EOF
OTPW Password Statistics
------------------------
Passwords used: ${USED_PASSWORDS:=0}
Passwords left: $PASSWORDS_LEFT
EOF
if [ $PASSWORDS_LEFT -le $((TOTAL_PASSWORDS / 2)) ]
then
echo "It's time to generate new OTPW passwords."
elif [ $PASSWORDS_LEFT -le $MIN_PASSWORDS ]; then
echo "Remaining passwords at critical levels."
echo "It's time to generate new OTPW passwords."
fi
把otwp-stats.sh添加到你的~/.profile(或其他外殼啟動腳本),以便在登錄時提供反饋:
# 通過SSH登錄時才運行腳本。
[ -n "$SSH_CONNECTION" ] && ~/bin/otpw-stats.sh
結(jié)論
OTPW提供了實現(xiàn)一次性密碼的機制,與OPIE和S/KEY相比毫不遜色。它很容易與大多數(shù)Linux系統(tǒng)上的SSH集成,而且仍可以在帶經(jīng)過加密的主目錄的Ubuntu系統(tǒng)上使用。
原文地址:http://www.linuxjournal.com/content/configuring-one-time-password-authentication-otpw?page=0,0