Insecure Randomness

ID

javascript.insecure_randomness

Severity

high

Resource

Predictability

Language

JavaScript

Tags

CWE:330, CWE:332, CWE:336, CWE:337, CWE:338, NIST.SP.800-53, OWASP:2021:A2, PCI-DSS:6.5.3, cryptography

Description

Use of cryptographically weak pseudo-random number generator (PRNG).

Insecure randomness errors occur when a function that can produce predictable values is used as a source of randomness in a security-sensitive context.

Computers are unable to produce true randomness. Pseudo-Random Number Generators (PRNGs) approximate randomness algorithmically, starting with a seed from which subsequent values are calculated.

There are two types of PRNGs: statistical and cryptographic. Statistical PRNGs provide useful statistical properties, but their output is predictable and forms an easy to reproduce numeric stream, unsuitable for use in cases where security depends on generated values being unpredictable.

Cryptographic PRNGs address this problem by generating output that is more difficult to predict. For a value to be cryptographically secure, it must be highly improbable for an attacker to distinguish between it and a truly random value. In general, if a PRNG algorithm is not advertised as being cryptographically secure, then it is probably a statistical PRNG and should not be used in security-sensitive contexts, where its use can lead to serious vulnerabilities such as easy-to-guess temporary passwords, predictable cryptographic keys, session hijacking, and DNS spoofing.

Rationale

Randomness is often utilized in software applications for generating keys, tokens, session identifiers, and more. However, not all random number generators are suitable for security-sensitive tasks.

The Math.random() function, for example, does not provide the unpredictability needed for secure random number generation, as its algorithm and seed value can lead to predictable sequences.

The following code uses a statistical PRNG to create a URL for a receipt that remains active for some period of time after a purchase.

function generateToken() {
  // 16 hex chars (64 bit), insecure PRNG
  const rnd =
    Math.random().toString(16).slice(2, 10) +
    Math.random().toString(16).slice(2, 10);
  let token = tokenPrefix + rnd + tokenSuffix;
  return token;
}

The function above uses Math.random() to generate access tokens. Because Math.random() is a statistical PRNG, an attacker may guess the strings it generates. The randomness source is not sufficiently secure for generating tokens used in security contexts.

Remediation

To remediate the vulnerabilities related to insecure randomness in Node/JavaScript applications, developers should transition to a cryptographically strong random number generator in context where a cryptographic PRNG is needed.

In the example before:

const crypto = require('crypto');

function generateToken() {
  // 16 hex chars (64 bit), cryptographic PRNG
  const rnd = crypto.randomBytes(8).toString('hex');
  let token = tokenPrefix + rnd + tokenSuffix;
  return token;
}

Below are best practices to ensure appropriate randomness for cryptographic tasks in JavaScript applications :

  1. Use cryptographic random generator: If you are using a cryptographic library, probably it contains a suitable random number generator. If not, you may consider alternatives such as:

    • window.crypto.subtle.getRandomValues(), from Web Crypto API (if under a modern browser).

    • crypto.randomBytes() or crypto.randomFill(), from Node.js Crypto package (if under Node.js).

    • sjcl.random.randomWords(), from Stanford Javascript Crypto Library (works both client- and server-side)..

  2. Seed Management: Avoid setting a custom seed for your cryptographic random generator, as it manages seeds internally to ensure strong randomness and entropy. If you must seed, ensure it is done securely and with a truly random value. Read the documentation to ensure that a random seed is generated appropriately.

By adhering to these practices, applications can achieve secure randomness necessary for maintaining strong security in sensitive operations.

Configuration

The rule has the following configurable parameters:

  • checkSecurityContext, that indicates if the detector should raise issues that are not located under a security context. When this is set to false, the issues not located under a security context will still be reported but with INFO severity.

  • securityContextPattern, the pattern used to match the code units (like functions) that are related to a security context.

References

  • CWE-338 : Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG).

  • CWE-330 : Use of Insufficiently Random Values

  • CWE-332 : Insufficient Entropy in PRNG

  • CWE-336 : Same Seed in Pseudo-Random Number Generator (PRNG)

  • CWE-337 : Predictable Seed in Pseudo-Random Number Generator (PRNG)

  • OWASP - Top 10 2021 - A2 : Cryptographic Failures