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:
-
We import the necessary libraries.
string
andrandom
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. -
In the
create_temporary_password
function, we first retrieve the user object from the database using the provideduser_id
. -
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. Thejoin()
function then combines this list into a single string. -
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. -
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.