Secure Coding 101: How to Use Random Function

By SmartScanner

Random numbers are everywhere on the web, and your security depends on them. Let’s see if you’re using them right.

Random numbers play a critical role in web application security. They are used in session identifiers, passwords, cryptographic keys, and more. However, if not implemented securely, they can lead to vulnerabilities that attackers can exploit to gain unauthorized access to sensitive information.

TLDR

  • Most random generators are not really random. They use math that looks random
  • Do not use Math.random() in JavaScript or random in Python
  • Use Web Crypto API in JavaScript, crypto module in NodeJs, and secrets in python
  • Do not try to implement your own random generation algorithm
  • Incorrect usage of secure random numbers can make your application vulnerable

How Random Functions work

There are two main types of Random Number Generators (RNGs): pseudo-random number generators (PRNGs) and true random number generators (TRNGs).

Pseudo-random Number Generators (PRNGs)

PRNGs are the most commonly used type of RNGs. They work by using an algorithm to generate a sequence of numbers that appear to be random. The algorithm takes an initial value as input and produces a series of numbers based on it.

The common algorithms used in PRNGs are the Mersenne-Twister and linear congruential generator (LCG).

These algorithms get an initial number called seed. They change it by adding previous random number, shifting, and doing XOR operators to generate the output. The output looks like a random number though it’s just an output of a formula.

If you keep executing any PRNG, it will eventually generate the same numbers over and over. Any PRNG has a fixed length of numbers that can generate before starting over.

True Random Number Generators (TRNGs)

TRNGs generate truly random numbers based on physical processes that are inherently random. These processes include atmospheric noise, radioactive decay, and thermal noise. TRNGs measure the physical process and convert it into a random number.

Random Function Vulnerabilities

The seed and random number generation algorithm both can have weaknesses.

Prediction

You can say predictability is the main vulnerability of weak random number generators. PRNGs are inherently predictable as they are based on a mathematical formula. So if you know the seed and last random number, you can predict the next random number. This can lead to severe vulnerabilities.

For example, consider a forget password functionality that words based on a random token. If the token can be predicted, an attacker can reset the password of any user.

Collision

Besides the predictability, Some random generators that have low quality produce duplicate values very often. This can increase the risk of collision.

Consider an application that generates random session tokens for its users. The chances of producing duplicate session tokens are related to two factors:

  • Size of random space (length of session token)
  • Quality of the random selection

Short-length tokens will have a higher chance of collisions. And bad random generator does not generate all possible values. This can lead to vulnerabilities where a user can see another user’s data.

Seed Leakage or Manipulation

Another vulnerability related to random number generators is choosing a weak seed. PRNG always generates the same sequence of numbers with the same initial seed value. If an attacker can find the used seed or manipulate it, he can easily generate same random numbers.

In pratice, hackers use different methods to predict the next random number. Some methods may involve statistical analysis, while others may involve reverse-engineering the generator’s algorithm.

How to Use Secure Random Numbers

Using cryptographically secure random number generation algorithms is the key to securely producing random numbers. These algorithms generate random numbers that are unpredictable and cannot be easily guessed by attackers. The output of these algorithms is resistant to brute-force attacks, and it’s statistically robust. You should not try to implement your own one unless you know what you are doing. Instead, always use known to be secure random libraries.

Let’s see a few examples of using secure random libraries in different programming languages.

Javascript

The Math.random() function is not suitable for cryptographic purposes, as it is not truly random and can be predicted or manipulated by an attacker.

To generate a secure random number in JavaScript, you can use the Web Crypto API. The Crypto.getRandomValues() method lets you get cryptographically strong random values. Here is an example code that generates a secure random number:

function generateRandomNumber() {  
  const array = new Uint32Array(1); // Create a 32-bit unsigned integer array  
  window.crypto.getRandomValues(array); // Fill the array with random values  
  return array[0]; // Return the first element of the array as the random number  
}  
 
console.log(generateRandomNumber()); // Output a random number between 0 and 4294967295

NodeJS

In NodeJS, the crypto module can be used to generate cryptographically secure random numbers. The following code sample illustrates the use of crypto module in generating a random number:

const crypto = require('crypto');  
 
function generateRandomNumber() {  
  const randomBytes = crypto.randomBytes(4); // Generate 4 random bytes  
  const hexValue = randomBytes.toString('hex'); // Convert the bytes to a hex string  
  const intValue = parseInt(hexValue, 16); // Convert the hex string to an integer  
  return intValue;  
}  
 
console.log(generateRandomNumber()); // Output a random number between 0 and 4294967295

Python

In Python, the random module can be used to generate random numbers. However, it is not cryptographically secure. Instead, you can use the secrets module to generate cryptographically secure random numbers. The following code sample illustrates the use of secrets module in generating a random number:

import secrets  
 
def generate_random_number():  
    random_number = secrets.randbits(32) # Generate a 32-bit random number  
    return random_number  
 
print(generate_random_number()) # Output a random number between 0 and 4294967295

Conclusion

Random numbers in computers are mathematical formulas and predictable. Not every random number generator is suitable for cryptography and security usage. Random numbers are just one element in security system design and implementation. There are many other things like seed generation, key management, and overall security system design that are extremely important and hard to get right. The Crypto 101 is a great place to start learning more about cryptography.

Scan security of your website with SmartScanner for free

Download