身份認證設計的基本準則
密碼長度和復雜性策略
密碼認證作為當前最流行的身份驗證方式,在安全方面最值得考慮的因素就是密碼的長度。一個強度高的密碼使得人工猜測或者暴力破解密碼的難度增加。下面定義了高強度密碼的一些特性。
(1)密碼長度
對于重要的應用,密碼長度最少為6;對于關鍵的應用,密碼長度最少為8;對于那些最關鍵的應用,應該考慮多因子認證系統。
(2)密碼的復雜度
有的時候僅有長度約束是不夠的,比如說12345678、11111111這樣的密碼,長度的確是8位,但極容易被猜測和字典***,所以這時候就需要增加密碼復雜度。下面列舉了一些提供復雜度的策略。
至少一個大寫字母(A~Z)。
至少一個小寫字母(a~z)。
至少一個數字(0~9)。
至少一個特殊字符(!@#$%^&等)。
定義最少密碼長度(如8個字符)。
定義最長密碼長度(如16個字符)。
不能出現連續的字符(如123、abc、def)。
不能出現連續相同的字符(如1111)。
一旦我們定義好了這些策略,在用戶注冊時就可以強制用戶輸入高強度的密碼,從而提高密碼的安全性。
實現一個安全的密碼恢復策略
上一節介紹了密碼的長度和復雜度,有時,太復雜的密碼自己都給忘記了,該怎么辦?所以一般來說,一個應用會提供密碼恢復功能。鑒于大部分應用都提供了電子郵箱這具有唯一性字段的恢復方式,所以可見最常見的方式就是讓用戶輸入電子郵箱,輸入電子郵箱后,一般會有以下兩種解決方法。
(1)把原來的密碼發送到用戶信箱中去。
我個人的意見是,如果這樣做,說明這個應用可以得知你的密碼明文,這與系統只存hash/加密值的單項策略相違背,若哪一天這個程序的數據庫被攻克,所有的明文就會被很容易地得知,所以這種方式還是不值得提倡。
(2)重設一個臨時密碼,用戶用這個密碼登錄然后修改密碼。
這是一個相對較好的方法,通常為了增加安全性,我們還可以給這個臨時密碼一個有效期,如用戶必須24小時內使用這個密碼登錄等。
上面的密碼恢復策略是基于一個事實的,就是你的電子郵箱應該足夠安全(沒有人知道你的郵箱密碼)。但是如果這個應用具有CSRF漏洞,即電子郵件可能被修改成一個***者的郵箱而受害者卻毫無所知,這時候如果進行密碼恢復就會把密碼發到***者的信箱里,那么該怎么辦呢?
答案是更新重要字段時需要重新認證。比如用戶的密碼、電子郵件等,如果用戶需要更新,則彈出一個對話框讓用戶輸入原先的密碼,這樣就可以有效地防止CSRF***。
重要的操作應通過HTTPS傳輸
對于重要的操作,如登錄、修改密碼等,一定要通過HTTPS進行傳輸。我們就以Tomcat為例,說明一下如何進行配置,使得指定的URL必須走HTTPS。
首先是產生一個證書。為了說明方便,我們采用Java提供的keytool產生一個自認證證書,命令如下:%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA。然后回答一些問題,這里注意設置證書庫的密碼和key的密碼,我們這里設置為changeit,這樣就會產生一個證書庫,如圖10-22所示。
圖10-22 用Java生成一個證書庫
然后在把產生的.keystore復制到{TOMCAT_HOME}\conf目錄下,配置server.xml如下:
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="${user.home}/.keystore" keystorePass="changeit" />
最后我們再配置APP應用下的WEB-INF\web.xml如下:
<security-constraint>
<web-resource-collection>
<web-resource-name>must https</web-resource-name>
<url-pattern>/login.jsp</url-pattern>➊
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
➊ 設置哪些URL 需要走HTTPS。
認證錯誤信息以及賬戶鎖定
下面是一些不正確的認證錯誤信息:
登錄失敗,用戶Kevin的密碼錯誤。
登錄失敗,無效的用戶名。
登錄失敗,該用戶已被禁用。
登錄失敗,該用戶沒有被激活。
正確的表達方式應該是唯一的一種:
登錄失敗,用戶名或密碼錯誤。
不正確的認證錯誤信息可能會導致字典***或者暴力破解,所以我們要盡可能地給出一個很普遍的錯誤信息。
此外為了防止暴力***,我們可以設定下列規則:
第一次登錄失敗,下一次登錄至少間隔5s。
第二次登錄失敗,下一次登錄至少間隔15s。
第三次登錄失敗,下一次登錄至少間隔45s。
第四次登錄失敗,集成圖形驗證碼CAPTCHA,讓用戶輸入圖片中的字符串。
如果有足夠明顯的證據顯示是暴力破解(如每分鐘進行了100次嘗試),IP地址或者Session ID應該在接下來一段時間(如15分鐘)被阻止,在這種情況下,我們應該給出清楚明白的錯誤信息,說明為什么這個登錄會失敗。
本文節選自《Web應用安全威脅與防治——基于OWASP Top 10與ESAPI》

王文君 李建蒙 編著
電子工業出版社出版