logo

Non-encrypted confidential information - Python


Need

Secure storage of confidential information


Context

  1. Usage of Python 3 for developing Python applications
  2. Usage of Django for building web applications in Python

Description

Insecure Code Example

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

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

Secure Code Example

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

  • 020 - Non-encrypted confidential information

  • Last updated

    2023/09/18