Insecure generation of random numbers - Python

Insecure generation of random numbers - Python

Need

Secure generation of random numbers

Context

  • Usage of Python 3 for building and executing Python applications
  • Usage of random for generating random numbers or values

Description

Non compliant code

        import random

def generate_random_number():
    return random.randint(0, 100)
        
        

In the above Python code, we are using the random.randint() function from Python's standard random library to generate a random number between 0 and 100.

This introduces a potential vulnerability in the system. The random library in Python uses a Mersenne Twister as the core generator. It produces 53-bit precision floats and has a period of 2**19937-1. Although this is a very large period, it is not truly random and can be predicted after enough outputs from the generator have been collected.

This means that an attacker, after observing enough outputs from this function, could potentially predict future outputs, which could lead to a variety of attacks, depending on what the random numbers are used for in the application. For example, if they are used in cryptographic operations, this could lead to the compromise of the keys and thus the data they protect.

Moreover, the range of the random numbers is also limited between 0 and 100 which further reduces the entropy of the generated numbers, making it easier for an attacker to guess the generation sequence.

Steps

  • Replace the insecure random number generator with a secure one. Python's 'random' module is not suitable for security-sensitive work, as it is not cryptographically secure.
  • Use a function like 'secrets.randbelow' or 'secrets.randbits' from the 'secrets' module in Python, which generates random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets.
  • Ensure that the range of the random numbers generated is appropriate for the use case. If the range is too small, it may be easy for an attacker to guess the number.
  • Consider adding additional entropy to the random number generation process if necessary. This could be done by incorporating user input or system state into the generation process.

Compliant code

        import secrets

def generate_secure_random_number():
    return secrets.randbelow(101)
        
        

The original code was using the random.randint function from Python's random module to generate random numbers. This function is not cryptographically secure, which means it's not suitable for generating random numbers in a security-sensitive context. An attacker could potentially predict the sequence of numbers generated by this function after a short time.

The revised code uses the secrets.randbelow function from Python's secrets module to generate random numbers. This function is designed for generating cryptographically secure random numbers, which makes it suitable for security-sensitive work. The secrets.randbelow function generates a random number that is less than the argument given to it. In this case, it generates a random number less than 101, which means it generates a random number in the range [0, 100].

This change makes the random number generation process in the code more secure, reducing the risk of an attacker being able to predict the sequence of numbers generated.

References