# 密碼存儲備忘單
> 原文:[Password Storage Cheat Sheet](https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet)
> [密碼存儲備忘單](http://cheatsheets.hackdig.com/?7.htm)
## 介紹
媒體幾乎每天都會報道一些竊取密碼的新聞。媒體報道的密碼竊取大多數是密碼存儲方案泄露、存儲方案存在漏洞。通常會有大量的憑據遭到破壞,從而影響大量的WEB站點或者其他應用程序。本文提供了一個正確存儲密碼、密碼問題及答案和類似憑據信息的指導。合適的存儲方案能防止證書被盜、被泄露和惡意使用。信息系統通過各種保護形式來存儲密碼和其他憑據。常見的漏洞讓竊密者能通過SQL注入等攻擊向量來竊取被保護的密碼。受保護的密碼也有可能被攻擊者通過其他形式(如日志、轉儲和備份文件等)竊取。
這份指導會教你如何防止憑據被盜,但是大部分內容是關于防止密鑰泄露的。這個指導同樣能幫助你設計抵御用戶憑據被盜或防止竊密者訪問憑據信息的系統。你可以參閱 http://goo.gl/Spvzs 以獲取更多信息。
## 指導
### 不限制字符集和設置最大憑據長度
一些系統會做如下限制:1)特定的字符類型。2)系統能夠接受的憑據長度(因為這有助于防止SQL注入、跨站腳本、命令執行和其他形式的注入攻擊)。這些善意的限制讓系統更易于受到暴力破解這類的攻擊。
不要在登陸入口或存儲憑據時使用過短、沒有長度限制的、只限制字符集或編碼的密碼。除此之外,還要使用編碼、轉碼、隱藏、忽略和其他最佳實踐來消除注入攻擊的風險。
合理的長密碼的長度是160,太長的密碼可能會讓系統出現DDOS攻擊漏洞[1].
### 使用一個強大的加密憑據專用的鹽(salt)
鹽是固定長度的、用于加強密碼學可靠性的隨機值。將憑據數據加入鹽中并將其作為保護函數的輸入。形式如下:
```
[protected form] = [salt] + protect([protection func], [salt] + [credential]);
```
遵循如下的實踐來實現憑據專用的鹽的生成:
為每一個憑據生成唯一的鹽(而不是每個用戶或每個系統生成一個鹽);
使用有強密碼學可靠性的隨機[\*3]數據;
根據存儲許可要求,使用32位或64位鹽(實際大小依賴于保護函數);
安全機制并不取決于隱藏、拆分或隱藏鹽;
加鹽是為了達到兩個目的:1)防止兩個相同憑據的生成同樣的加密數據;2)增加熵值讓保護功能不再依賴憑據的復雜度。第二個還能讓個人憑據免遭彩虹表攻擊。
### 利用攻擊者不可行驗證
用來保護存儲憑據的函數應該平衡攻擊者和防衛驗證。防御者需要一個即使在訪問高峰時也能接受的驗證用戶憑據的響應時間。但是要知道,生成“憑據<=>保護數據”的映射表的時間與攻擊者的硬件(GPU、FPGA)和技術(基于字典、暴力破解等)能力有關。
下面兩種方法都不完美。
使用可以自適應的單向函數
自適應的單向函數進行單向的不可逆轉換。每個函數都可以配置“工作因子”。如何實現不可逆性、支配工作因子(如時間、空間和并行度)將不在這里討論。
選擇:
PBKDF2 [\*4]是FIPS認證的,已經獲得很多企業支持。
scrypt [\*5]能抵御任何/全部硬件加速攻擊,但支持并不好。
bcrypt不支持PBKDF2和scrypt加密算法。
protect()的偽代碼如下:
```
return [salt] + pbkdf2([salt], [credential], c=10000);
```
設計師選擇單向自適應函數來實現protect()函數,因為這些函數相對于哈希函數,能夠通過修改配置改變它的執行耗時(線性或指數方式)。防衛者調整工作因子來與攻擊者持續增長的硬件能力賽跑。這些自適應的單向函數的實現必須工作因子調整,從而在阻礙攻擊者的同事提供可接受的用戶體驗。
此外,自適應的單向函數不能有效的阻止常見的基于字典的憑據破解,用戶規模和加鹽對于此絲毫沒有幫助。
#### 工作因子
一般而言,資源是有限的,一個常見的調整工作因子(或耗時)的法則是:讓protect()函數在不影響用戶的體驗和增加額外的超預算硬件的前提下,盡可能的降低速度。因此,在注冊和身份驗證時,你可以改變protect()的參數,讓這個計算在你的硬件上耗時1秒鐘。這樣一來,它就不會因為過慢影響到你的用戶,同時又能有效阻止攻擊者的嘗試輕輕。
雖然有推薦的最小迭代次數來確保數據的安全,但是由于技術在發展,這個值至少每年需要改變一次。一個知名的迭代次數的例子是蘋果公司,他們加密iTunes密碼(使用PBKDF2)的迭代次數是10000。但是你要知道,使用單一的工作因子并不適合所有的情況。實驗很重要[\*6]
#### 杠桿鍵函數
鍵函數,如HMACs算法,使用私鑰和輸入參數計算單向(不可逆)轉換。對于HMACs,它繼承了哈希函數的屬性,包括:速度、允許即時驗證。密鑰的長度影響不可行長度和/或空間要求——甚至是常見的憑據。設計者使用鍵函數來保護存儲的憑據:
使用一個“站點級別”的key;
像保護所有密鑰一樣用最佳實踐來保護這個key;
將這個key和憑據分開存儲(不要存在數據庫中);
使用強密碼學可靠性的偽隨機數據生成密鑰;
不要擔心輸出數據塊的大小(如 SHA-256 vs. SHA-512).
protect()偽代碼如下:
```
return [salt] + HMAC-SHA-256([key], [salt] + [credential]);
```
鹽方案的持續改進依賴于正確的密鑰管理。
### 設計能處理密碼被泄露的密碼存儲的方法
實際上,受保護憑據頻繁被盜的現狀逼迫著我們做“失敗設計”。如果發現憑據被盜,一個好的憑據存儲方案能輕松的對被盜憑據執行安全操作并使用備選的憑據驗證流程:
保護用戶的賬號
使用第2因素或者密碼問題來進行登陸,不再支持快捷登陸。
不允許用戶修改賬戶信息,如編輯密碼問題和修改賬戶多因子認證配置。
使用新的保護方案
使用新的更強大的密鑰保護函數
包含版本信息的存儲形式;
設置賬號被盜或疑似被盜的標示,讓用戶重置憑據;
修改密鑰和/或調整保護函數參數(迭代次數);
增加方案版本號
當用戶登陸時:
根據存儲的版本驗證憑據(新的或者舊的憑據);如果是舊密碼,則要求進行多因子認證或詢問密碼問題。
提示用戶憑據已經變化,向用戶道歉并引導用戶進行其他身份確認。
當用戶成功登陸后,將存儲的憑據轉換為新方案。
## 引用
[1] Morris, R. Thompson, K., Password Security: A Case History, 04/03/1978, p4:http://cm.bell-labs.com/cm/cs/who/dmr/passwd.ps
[2] Space-based (Lookup) attacks: Space-time Tradeoff: Hellman, M., Crypanalytic Time-Memory Trade-Off, Transactions of Information Theory, Vol. IT-26, No. 4, July, 1980http://www-ee.stanford.edu/~hellman/publications/36.pdf Rainbow Tables -http://ophcrack.sourceforge.net/tables.php
[3] For example: SecureRandom.html.
[4] Kalski, B., PKCS #5: Password-Based Cryptography Specification Version 2.0, IETF RFC 2898, September, 2000, p9 http://www.ietf.org/rfc/rfc2898.txt
[5] Percival, C., Stronger Key Derivation Via Sequential Memory-Hard Functions, BSDCan ‘09, May, 2009 http://www.tarsnap.com/scrypt/scrypt.pdf
[6] For instance, one might set work factors targeting the following run times: (1) Password-generated session key - fraction of a second; (2) User credential - ~0.5 seconds; (3) Password-generated site (or other long-lived) key - potentially a second or more.
[7]php hmac hash function:http://www.php.net/manual/en/function.hash-hmac.php
## 作者和主編
John Steven - john.steven[at]owasp.org (author)
Jim Manico - jim[at]owasp.org (editor)
## 原文屬性
最后修改時間:This page was last modified on 25 March 2014, at 09:53.