Skip to main content

Non-encrypted confidential information - Credentials

Need

Secure storage of confidential information - Credentials

Context

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

Description

Non compliant code

from django.contrib.auth.models import User

def create_user(request):
username = request.POST.get('username')
password = request.POST.get('password')

user = User.objects.create_user(username=username, password=password)
user.save()

The above code is a simple Django view function that creates a new user in the system with the provided username and password. The password is received from the HTTP POST request and is used directly to create a new User object.

The vulnerability lies in the fact that the password is handled and stored in plain text. This means that if an attacker is able to gain access to the server logs or the database, they can easily read and use these passwords for unauthorized access. Furthermore, if the HTTP connection itself is not secured (i.e., not using HTTPS), then the password can be intercepted during transmission.

In Django, the User model's create_user method does not automatically hash the password. Therefore, the password is stored in the database exactly as it is received from the user, which in this case is in plain text. This is a severe security risk as it exposes sensitive user data.

This vulnerability can be exploited in various ways, such as:

  1. An attacker gaining unauthorized access to the application's database can easily read the passwords.
  2. If the application's server logs include request data, the passwords can be read from there.
  3. An attacker intercepting the HTTP traffic can read the password during transmission.

To fix this vulnerability, the password should be hashed before it is stored in the database. Django provides built-in functions for this purpose. Additionally, the transmission of the password should be secured using HTTPS.

Steps

  • Use Django's built-in authentication system which automatically hashes passwords.
  • Ensure that the password is not logged or printed anywhere in plain text.
  • Use HTTPS for all communications involving sensitive data to prevent interception during transmission.
  • Implement proper access controls to limit who can view the source code.
  • Regularly update and patch your systems to protect against known vulnerabilities.

Compliant code

from django.contrib.auth.models import User
from django.views.decorators.csrf import csrf_protect
from django.contrib.auth.hashers import make_password

@csrf_protect
def create_user(request):
username = request.POST.get('username')
password = request.POST.get('password')
hashed_password = make_password(password)

user = User.objects.create_user(username=username, password=hashed_password)
user.save()

The updated code now includes Django's built-in make_password function, which is used to hash the password before it is stored. This ensures that the password is not stored in plain text in the database, making it much more difficult for an attacker to retrieve.

The @csrf_protect decorator is used to add cross-site request forgery protection to the view. This helps to ensure that the form is only submitted by the site that generated it, preventing potential attacks.

It's also important to note that Django's create_user method already takes care of password hashing. The make_password function is used here for demonstration purposes, to show how you can manually hash a password.

Remember, it's also crucial to use HTTPS for all communications involving sensitive data to prevent interception during transmission, implement proper access controls to limit who can view the source code, and regularly update and patch your systems to protect against known vulnerabilities.

References