Insecure generation of random numbers
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.