使用不是加密隨機的 System.Random 的實際影響是什麼?
我最近注意到一個
.NET
軟體PBKDF
用來從密碼字元串中獲取加密密鑰。此密碼字元串是使用動態生成的System.Random
。現在,我知道這System.Random
不是真正的加密隨機,不應該用於安全目的。此外,在. _.NET``System.Random
但我的問題是這樣的:
- 使用 System.Random 創建密碼字元串並從中派生密鑰的實際影響是什麼。我們真的有可能在以後重現密鑰嗎?是否有可行的攻擊可以讓我以高機率推斷出在這種情況下生成的隨機字元串?還是只能在特定的“實驗室”條件或場景中利用的那種漏洞?
您要求實際影響,所以答案是120美元我可能會在明天之前完成您的整個密碼數據庫。
這是您的程序或類似的程序:
using System; using System.Text; using System.Security.Cryptography; class Program { static void Main(string[] args) { byte[] pwd = new byte[128]; byte[] salt = Encoding.ASCII.GetBytes("saltsalt"); var rand = new Random(); rand.NextBytes(pwd); Rfc2898DeriveBytes k = new Rfc2898DeriveBytes(pwd, salt, 1000); Console.WriteLine(System.Convert.ToBase64String(k.GetBytes(16))); } }
我們應該花點時間談談你的鹽。我假設它是固定的。你通常會隨機生成它——如果你對鹽和密碼都使用一個 System.Random 實例,那麼攻擊基本上是相同的。如果您
System.Random
一個接一個地創建兩個實例,那麼考慮到預設種子的生成方式,您不太可能獲得任何東西。如果您的鹽基於遞增的計數器或使用者名或其他東西,那麼我要說的僅適用於攻擊單個密碼而不是整個數據庫。無論哪種方式,您仍然應該擔心。我編譯了它並在我自己的機器上執行它,它給了我密鑰
IDWrj6Fd9c4kqJ6A2FHDEg==
。讓我們嘗試打破它!
System.Random
有據可查:https ://docs.microsoft.com/en-us/dotnet/api/system.random.-ctor?view=netframework-4.8 。它使用 32 位整數密鑰,實際上如果密鑰為負數,文件告訴我們它實際上出於某種原因使用了密鑰的絕對值。便利!那隻是31位!讓我們用這個程序打破它:using System; using System.Text; using System.Linq; using System.Security.Cryptography; class Program { static void Main(string[] args) { byte[] target = System.Convert.FromBase64String("IDWrj6Fd9c4kqJ6A2FHDEg=="); byte[] pwd = new byte[128]; byte[] salt = Encoding.ASCII.GetBytes("saltsalt"); for (int i = 0; i < Int32.MaxValue; i++){ if (i % 1024 == 0) { Console.WriteLine(i); } var rand = new Random(i); rand.NextBytes(pwd); Rfc2898DeriveBytes k = new Rfc2898DeriveBytes(pwd, salt, 1000); if (k.GetBytes(16).SequenceEqual(target)){ Console.WriteLine("pwnt"); Console.WriteLine(i); Environment.Exit(0); } } } }
這需要執行多長時間?
dnSpy 是用於逆向 C# 應用程序的便捷工具,我們可以使用它來查看預設建構子的
System.Random
作用。你的可能會有所不同,但在我的一個 unseededSystem.Random
中將種子設置為Environment.TickCount
,這是自電腦啟動以來經過的毫秒數。我不會讓我的電腦一次執行超過幾個小時,因此 Environment.TickCount 可能不會超過 36,000,000。看著按鍵經過,我每分鐘嘗試大約 14,336 個按鍵。36000000/14336 = 2511 分鐘嘗試所有可行的密鑰,所以它應該在大約 40 小時內完成。在筆記型電腦上執行 40 小時糟糕的 C# 程序根本不安全。即使您更好地挑選種子,2147483648/14336 = 149796 分鐘,也就是大約 2,400 小時。我想我可以花一些時間重新編寫我的垃圾層 C# 程序,以便它執行得更快——它肯定真的很慢並且可以大量改進——但我不太關心你的密碼來做到這一點。從不同的種子開始執行幾千個實例每個小時更容易。
亞馬遜將以每小時 0.05 美元左右的價格向我出售 CPU 小時數,因此我需要花費120 美元,外加一些時間和精力編寫程式碼並將其放到他們的伺服器上,以破解你的整個密碼數據庫。可能更少,因為我的筆記型電腦可能比他們的計算節點慢。
這裡的大部分時間都花在實際計算 PBKDF2 函式上。PBKDF2 非常棒,你仍然應該使用它——它的設計速度恰好是緩慢的,因此這樣的攻擊效率低下。120美元的估算是基於在您的 PBKDF2 中使用 1,000 次迭代,這在我的機器上每個雜湊需要幾毫秒。你可以讓這次攻擊花費$1200 只需將該參數調整為 10,000,儘管堅定的攻擊者仍會很樂意支付這筆費用以獲取使用者數據。如果您希望這次攻擊花費我 1,200,000 美元,您可以使用 10,000,000 次迭代!每次您想要密碼時,您也會浪費幾個小時。我不知道你的應用程序在做什麼,但如果它把所有時間都花在計算雜湊上,那麼它可能會通過探勘比特幣或其他東西賺更多的錢。
基於非加密隨機數生成器的密碼方案不是一個好主意。改用這個:https ://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rngcryptoserviceprovider.getbytes?view=netframework-4.8 。如果您要從 CSPRNG 生成 128 字節,那麼這種蠻力將開始花費我數万億美元的計算時間,這是整個地球 GDP 的幾百倍。沒有任何組織擁有接近這種計算能力的任何東西。