繼續對Fortify的漏洞進行總結,本篇主要針對 Insecure Randomness 漏洞進行總結,以下:html
成弱隨機數的函數是 random()。 java
電腦是一種具備肯定性的機器,所以不可能產生真正的隨機性。僞隨機數生成器 (PRNG) 近似於隨機算法,始於一個能計算後續數值的種子。 算法
PRNG 包括兩種類型:統計學的 PRNG 和密碼學的 PRNG。統計學的 PRNG 可提供有用的統計資料,但其輸出結果很容易預測,所以數據流容易複製。若安全性取決於生成數值的不可預測性,則此類型不適用。密碼學的 PRNG 經過可產生較難預測的輸出結果來應對這一問題。爲了使加密數值更爲安全,必須使攻擊者根本沒法、或極不可能將它與真實的隨機數加以區分。一般狀況下,若是並未聲明 PRNG 算法帶有加密保護,那麼它有可能就是一個統計學的 PRNG,不該在對安全性要求較高的環境中使用,其中隨着它的使用可能會致使嚴重的漏洞(如易於猜想的密碼、可預測的加密密鑰、會話劫持攻擊和 DNS 欺騙)。安全
示例: 下面的代碼可利用統計學的 PRNG 爲購買產品後仍在有效期內的收據建立一個 URL。網絡
String GenerateReceiptURL(String baseUrl) {dom
Random ranGen = new Random(); 函數
ranGen.setSeed((new Date()).getTime());加密
return (baseUrl + ranGen.nextInt(400000000) + ".html");spa
} 設計
這段代碼使用 Random.nextInt() 函數爲它所生成的收據頁面生成獨特的標識符。由於 Random.nextInt() 是一個統計學的 PRNG,攻擊者很容易猜到由它所生成的字符串。儘管收據系統的底層設計也存在錯誤,但若是使用了一個不生成可預測收據標識符的隨機數生成器(如密碼學的 PRNG),會更安全一些。
當不可預測性相當重要時,如大多數對安全性要求較高的環境都採用隨機性,這時能夠使用密碼學的 PRNG。無論選擇了哪種 PRNG,都要始終使用帶有充足熵的數值做爲該算法的種子。(諸如當前時間之類的數值只提供很小的熵,所以不該該使用。)
Java 語言在 java.security.SecureRandom 中提供了一個加密 PRNG。就像 java.security 中其餘以算法爲基礎的類那樣,SecureRandom 提供了與某個特定算法集合相關的包,該包能夠獨立實現。當使用 SecureRandom.getInstance() 請求一個 SecureRandom 實例時,您能夠申請實現某個特定的算法。若是算法可行,那麼您能夠將它做爲 SecureRandom 的對象使用。若是算法不可行,或者您沒有爲算法明確特定的實現方法,那麼會由系統爲您選擇 SecureRandom 的實現方法。
Sun 在名爲 SHA1PRNG 的 Java 版本中提供了一種單獨實現 SecureRandom 的方式,Sun 將其描述爲計算:「SHA-1 能夠計算一個真實的隨機種子參數的散列值,同時,該種子參數帶有一個 64 比特的計算器,會在每一次操做後加 1。在 160 比特的 SHA-1 輸出中,只能使用 64 比特的輸出 [1]。」
然而,文檔中有關 Sun 的 SHA1PRNG 算法實現細節的相關記錄不多,人們沒法瞭解算法實現中使用的熵的來源,所以也並不清楚輸出中到底存在多少真實的隨機數值。儘管有關 Sun 的實現方法網絡上有各類各樣的猜想,可是有一點無庸置疑,即算法具備很強的加密性,能夠在對安全性極爲敏感的各類內容中安全地使用。
實際解決方案:
將本來 Random sr = new Random() 換成SecureRandom sr = new SecureRandom()
一、須要建立隨機數時,不使用 new Random() 的方式建立,能夠選擇使用new SecureRandom() 的方式建立。