經得起原始碼資安弱點掃描的程式設計習慣培養(九)_Use of Cryptographically Weak PRNG(Pseudo-Random Number Generator)
接續前幾篇系列
在判讀上屬於中風險的漏洞
通常在於應用程式裡面使用的Random亂數功能不夠隨機亂或者隨機範圍很好被預測到因為範圍較小。
風險
可能發生什麼問題
隨機數值通常被用來作為防止惡意使用者猜測如密碼、加密金鑰或session識別元等數值的機制,依照此
隨機數值用途的不同,攻擊者能夠有辦法預測下一個或已經產生過的隨機值,這使得攻擊者可以奪取另
外一位使用者的session,並取代他的身分,或是破解一組加密金鑰 (端看這組偽隨機值的用途)。
原因
如何發生
應用程式使用較弱的演算法來產生偽隨機值,代表決定其他數值的樣本大小相對來說是較小的。因為產
生隨機值所使用的偽隨機值產生器是基於統計學上的均勻分布所設計的,具有近似確定性。所以在收集
到數個產生出來的數值 (建立幾個獨立session然後收集session辨識碼)
後,攻擊者就有可能計算出其他的session辨識值。
更準確的說,如果這組偽隨機值被用做任何安全性使用,如密碼、金鑰、或是隱密辨識值,攻擊者就可以
預測下一個或已經產生的數值。
如何避免
一般建議:
1.當在安全性情境下需要用到任何不可預測值時,使用加密型強隨機數產生器取代基於統
計的偽隨機產生器。
2.使用你的程式語言或平臺內建的隨機加密產生器,而且確保亂數種子的產生是安全的
(大多數的情況下,預設就是安全的隨機值)。
3.確保你的隨機值夠長,讓暴力破解失效。
具體建議:
用隨機加密產生器取代基於統計的偽隨機產生器。
在 Java 中, 使用 SecureRandom 類別。
而CheckMarx提供的建議中沒有針對.net提出solution
根據 EC Council CASE.NET培訓和微軟官網的建議
所習得的建議可採用如下solution
要改採加密亂數來進行微調
使隨機值較無法被欲判拿來作其餘攻破偽造等行為
不過遇到的好像只是針對文字大小範圍的調整變化隨機就不去處理了(CheckMarx誤判)
此外也不是針對原生HTML Attribute的封裝而是屬於額外擴充的Data Attribute因此
應該還好
當然要調整的話
改動幅度可以最小的使用方式
就是我們希望能夠只需要將程式裡面Random的型別可以無痛取代成RNGCryptoServiceProvider
但在RNGCryptoServiceProvider中並未定義Next
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace PRNG_Test { public static class CrypRngExtension { private static byte[] arrByte = new byte[4]; public static int Next(this RNGCryptoServiceProvider myRngProvider) { myRngProvider.GetBytes(arrByte); int val = BitConverter.ToInt32(arrByte, 0); return (val < 0) ? Math.Abs(val) : val; } public static int Next(this RNGCryptoServiceProvider myRngProvider,int max) { return Next(myRngProvider) % (max + 1); } public static int Next(this RNGCryptoServiceProvider myRngProvider,int min, int max) { return Next(myRngProvider,max-min) + min; } } } |
那在外面調用就跟之前一模一樣了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace PRNG_Test { class Program { static void Main(string[] args) { string randKey = genRandomKey(20); Console.WriteLine(randKey); Random rnd = new Random(); string dataWeight = rnd.Next(12, 20).ToString(); Console.WriteLine(dataWeight); RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider(); string rnd_val = provider.Next(12, 20).ToString(); Console.WriteLine(rnd_val); Console.ReadKey(); } public static string genRandomKey(int length) { //Random random = new Random(); RNGCryptoServiceProvider random = new RNGCryptoServiceProvider(); string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*"; string randomKey = new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()); return string.Format("{0}_{1}", randomKey, DateTime.Now.ToString("yyyyMMddHHmmssfff")); } } } |
留言
張貼留言