Skip to main content

Non-encrypted confidential information - DB

Need

Secure storage of confidential information in the database

Context

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

Description

Non compliant code

from django.db import models

class UserQuery(models.Model):
query = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)

The vulnerability lies in the fact that the user's queries are stored in plain text in the database. If an attacker gains access to the database, they can easily read all the user's queries. This is a breach of the user's privacy and could potentially expose sensitive information.

A common way for attackers to gain access to a database is through SQL injection attacks. In this case, the attacker sends malicious SQL code in a query, which can trick the application into executing unintended commands, such as returning all the data in the database.

Even if the application is secure against SQL injection attacks, there are other ways an attacker can gain access to the database. For example, if the server where the database is hosted is compromised, the attacker can directly access the database and read all the data.

Storing sensitive data in plain text is a bad practice and should be avoided. The data should be encrypted before being stored in the database. This way, even if an attacker gains access to the database, they can't read the data without the encryption key.

Steps

  • Encrypt the sensitive data before storing it in the database. Django provides ways to encrypt model fields.
  • Use Django's built-in cryptographic fields to store sensitive information.
  • Implement proper access controls to restrict who can access the data.
  • Regularly audit your database and application to ensure that only authorized users have access.
  • Consider using a secure off-device storage solution for sensitive data.

Compliant code

from django.db import models
from django_cryptography.fields import encrypt

class UserQuery(models.Model):
query = encrypt(models.TextField())
user = models.ForeignKey(User, on_delete=models.CASCADE)

The above code fixes the vulnerability by encrypting the sensitive data before storing it in the database.

Here's a detailed breakdown of the changes:

  1. We import the encrypt function from django_cryptography.fields. This function will be used to encrypt the data before it is stored in the database.

  2. In the UserQuery model, we wrap the query field with the encrypt function. This means that whenever a query is saved to the database, it will be automatically encrypted.

By encrypting the data, we ensure that even if an attacker gains access to the database, they will not be able to read the sensitive information without the encryption key.

In addition to this, it's important to implement proper access controls to restrict who can access the data. Regularly audit your database and application to ensure that only authorized users have access. Consider using a secure off-device storage solution for sensitive data.

References