CodeQL 文档

不安全的随机数

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

单击以查看 CodeQL 存储库中的查询

使用密码学上弱的伪随机数生成器生成安全敏感的值(例如密码)会使攻击者更容易预测该值。

伪随机数生成器生成一系列数字,这些数字仅近似于随机数的特性。该序列并非真正随机,因为它完全由一组相对较小的初始值(种子)决定。如果随机数生成器在密码学上很弱,那么该序列可能会通过外部观察很容易地预测。

建议

如果输出将在安全敏感的上下文中使用,请使用密码学安全的伪随机数生成器。一般来说,如果预测某个值会让攻击者执行他们本来无法执行的操作,则应将其视为“安全敏感”值。例如,如果攻击者能够预测为新用户生成的随机密码,他们将能够以该新用户的身份登录。

对于 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);
}

参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私