不安全的随机数¶
ID: js/insecure-randomness
Kind: path-problem
Security severity: 7.8
Severity: warning
Precision: high
Tags:
- security
- external/cwe/cwe-338
Query suites:
- javascript-code-scanning.qls
- javascript-security-extended.qls
- javascript-security-and-quality.qls
使用密码学上弱的伪随机数生成器生成安全敏感的值(例如密码)会使攻击者更容易预测该值。
伪随机数生成器生成一系列数字,这些数字仅近似于随机数的特性。该序列并非真正随机,因为它完全由一组相对较小的初始值(种子)决定。如果随机数生成器在密码学上很弱,那么该序列可能会通过外部观察很容易地预测。
建议¶
如果输出将在安全敏感的上下文中使用,请使用密码学安全的伪随机数生成器。一般来说,如果预测某个值会让攻击者执行他们本来无法执行的操作,则应将其视为“安全敏感”值。例如,如果攻击者能够预测为新用户生成的随机密码,他们将能够以该新用户的身份登录。
对于 NodeJS 平台上的 JavaScript,crypto.getRandomBytes
提供了密码学安全的伪随机字节生成器。请注意,从字节到数字的转换可能会引入破坏安全性的偏差。
对于浏览器中的 JavaScript,crypto.getRandomValues
提供了密码学安全的伪随机数生成器。
示例¶
以下示例展示了生成密码的不同方法。
在第一个示例中,我们通过将随机整数附加到静态字符串的末尾来生成一个新的密码。使用的随机数生成器(Math.random
)不是密码学安全的,因此攻击者可能能够预测生成的密码。
function insecurePassword() {
// BAD: the random suffix is not cryptographically secure
var suffix = Math.random();
var password = "myPassword" + suffix;
return password;
}
在第二个示例中,密码学安全的随机数生成器用于相同目的。在这种情况下,预测生成的整数要困难得多。
function securePassword() {
// GOOD: the random suffix is cryptographically secure
var suffix = window.crypto.getRandomValues(new Uint32Array(1))[0];
var password = "myPassword" + suffix;
// GOOD: if a random value between 0 and 1 is desired
var secret = window.crypto.getRandomValues(new Uint32Array(1))[0] * Math.pow(2,-32);
}
参考资料¶
维基百科:伪随机数生成器.
Mozilla 开发者网络:Crypto: getRandomValues().
NodeJS:crypto.randomBytes
通用弱点枚举:CWE-338.