Skip to main content

Weak credential policy - Temporary passwords

Need

Implementation of a strong credential policy for temporary passwords

Context

  • Usage of Python 3 for writing and executing Python code
  • Usage of Django for building web applications in Python

Description

Non compliant code

from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password

def create_temporary_password(user_id):
user = User.objects.get(pk=user_id)
temp_password = user.username[::-1] # Reverse of username
user.password = make_password(temp_password)
user.save()

In the above code, we are creating a temporary password for a user. The function create_temporary_password(user_id) takes a user's id as an argument, fetches the corresponding user instance from the database, and then sets a temporary password for the user.

The temporary password is created by simply reversing the username (temp_password = user.username[::-1]). This approach to generating a temporary password is weak and predictable, making it easy for an attacker to guess the password if they know the username.

The password is then hashed using Django's make_password function and saved to the database (user.password = make_password(temp_password)).

This code is vulnerable due to its weak credential policy for temporary passwords. The password strength is weak because it's derived from the username in a predictable manner. This can lead to unauthorized access if an attacker can guess the temporary password.

Steps

  • Implement a strong password policy for temporary passwords. This could include a minimum length, a requirement for a mix of uppercase and lowercase letters, numbers, and special characters.
  • Avoid using predictable information, such as the reverse of the username, as a temporary password. Instead, generate a random string.
  • Consider using a library or built-in function to generate secure random passwords.
  • Ensure that temporary passwords are only used once and prompt the user to change their password after the first login.
  • Store passwords securely. Use a strong, one-way hashing algorithm to store passwords.

Compliant code

import string
import random
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password

def create_temporary_password(user_id):
user = User.objects.get(pk=user_id)
temp_password = ''.join(random.choices(string.ascii_uppercase + string.ascii_lowercase + string.digits + string.punctuation, k=10))
user.password = make_password(temp_password)
user.save()
return temp_password

The updated code now generates a secure temporary password for the user. Here's how it works:

  1. We import the necessary libraries. string and random are Python's built-in libraries. string contains various string constant which contains the ASCII characters of all cases. random is used to generate random numbers.

  2. In the create_temporary_password function, we first retrieve the user object from the database using the provided user_id.

  3. We then generate a random temporary password. The random.choices() function returns a list with a randomly selection from the given iterable (in our case, a combination of uppercase and lowercase ASCII letters, digits, and punctuation). We specify that we want a list of 10 elements. The join() function then combines this list into a single string.

  4. We use Django's make_password function to hash the password before storing it in the database. This is a security best practice, as it means that even if someone gains access to the database, they won't be able to see the users' actual passwords.

  5. Finally, we save the user object with the updated password.

This code ensures that the temporary password is both secure (as it's randomly generated and hashed) and unique to each user. The user should be prompted to change this temporary password after their first login.

References