不安全的随机性¶
ID: cs/insecure-randomness
Kind: path-problem
Security severity: 7.8
Severity: warning
Precision: high
Tags:
- security
- external/cwe/cwe-338
Query suites:
- csharp-code-scanning.qls
- csharp-security-extended.qls
- csharp-security-and-quality.qls
使用加密强度较弱的伪随机数生成器来生成安全敏感值(例如密码)会使攻击者更容易预测该值。
伪随机数生成器生成的数字序列仅近似于随机数的属性。该序列并非真正随机,因为它完全由一组相对较小的初始值(种子)决定。如果随机数生成器的加密强度较弱,则可以通过外部观察轻松预测该序列。
建议¶
如果要在安全敏感的上下文中使用输出,请使用加密安全的伪随机数生成器。根据经验,如果预测某个值将允许攻击者执行他们原本无法执行的操作,则该值应被视为“安全敏感的”。例如,如果攻击者可以预测为新用户生成的随机密码,则他们将能够以该新用户的身份登录。
对于 C#,RNGCryptoServiceProvider
提供了加密安全的伪随机数生成器。Random
不是加密安全的,在安全上下文中应避免使用。对于非安全敏感的上下文,Random
可能更可取,因为它具有更方便的接口,并且可能更快。
示例¶
以下示例展示了生成密码的不同方法。
在第一种情况下,我们通过将随机整数附加到静态字符串的末尾来生成新密码。使用的随机数生成器(Random
)不是加密安全的,因此攻击者有可能预测生成的密码。
在第二个示例中,出于相同目的使用了加密安全的随机数生成器。在这种情况下,预测生成的整数要困难得多。
在最后一个示例中,使用 Membership.GeneratePassword
库方法生成密码,该方法生成的密码存在偏差,因此应避免使用。
using System.Security.Cryptography;
using System.Web.Security;
string GeneratePassword()
{
// BAD: Password is generated using a cryptographically insecure RNG
Random gen = new Random();
string password = "mypassword" + gen.Next();
// GOOD: Password is generated using a cryptographically secure RNG
using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
{
byte[] randomBytes = new byte[sizeof(int)];
crypto.GetBytes(randomBytes);
password = "mypassword" + BitConverter.ToInt32(randomBytes);
}
// BAD: Membership.GeneratePassword generates a password with a bias
password = Membership.GeneratePassword(12, 3);
return password;
}
参考资料¶
维基百科。伪随机数生成器。
MSDN。RandomNumberGenerator。
常见弱点枚举:CWE-338。