Skip to main content

Non-encrypted confidential information

Need

Secure storage of confidential information

Context

  • Usage of Python 3 for developing Python applications
  • Usage of Django for building web applications in Python

Description

Non compliant code

from django.db import models

class User(models.Model):
username = models.CharField(max_length=200)
password = models.CharField(max_length=200)

In the above code, we have a Django model for a User. The User model has two fields: username and password. The username field is a CharField with a maximum length of 200 characters. The password field is also a CharField with a maximum length of 200 characters.

The vulnerability lies in the way the password is stored. It is stored as plain text in the database. This means that if an attacker were to gain access to the database, they would be able to see the passwords of all users without needing to decrypt them. This is a major security risk as it could lead to unauthorized access to user accounts.

The secure way to handle this is to store passwords in a hashed and salted format, not in plain text. This means that even if an attacker gains access to the database, they won't be able to use the passwords directly because they are not stored in a readable format. To verify a password, the same hashing process would be applied to the entered password and then compared to the stored hash.

Steps

  • Import the necessary Django libraries for password hashing.
  • Replace the CharField for the password with a field that automatically handles password hashing, such as Django's PasswordField.
  • Ensure that when creating or updating a user, the password is hashed before being stored in the database.
  • Verify that the application uses the Django authentication system to check passwords, which will automatically handle the comparison of the hashed password.

Compliant code

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

class User(models.Model):
username = models.CharField(max_length=200)
password = models.CharField(max_length=200)

def save(self, *args, **kwargs):
self.password = make_password(self.password)
super(User, self).save(*args, **kwargs)

The updated code now includes the necessary Django libraries for password hashing. The make_password function from django.contrib.auth.hashers is used to hash the password before it is stored in the database.

The CharField for the password is still used, but the save method of the User model has been overridden. Now, every time a User object is saved, the save method hashes the password using the make_password function before calling the original save method. This ensures that the password is always stored as a hashed value in the database.

It's important to note that this code assumes that the Django authentication system is being used to check passwords. The Django authentication system automatically handles the comparison of the hashed password when a user logs in. If a custom authentication system is being used, it will need to be updated to handle hashed passwords.

References