Skip to main content

Business information leak - Token

Need

Protection of sensitive user information in session tokens

Context

  • Usage of Python 3.0+ for developing Python applications
  • Usage of Django for building web applications

Description

Non compliant code

from django.contrib.auth import authenticate, login
from django.http import JsonResponse

def login_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)

if user is not None:
login(request, user)
return JsonResponse({"status": "success", "token": request.session.session_key, "username": user.username, "fullname": user.get_full_name()})
else:
return JsonResponse({"status": "error", "message": "Invalid credentials"})

This code represents a login view in Django, a Python web framework. When the client sends a POST request to this view with a username and password, the server attempts to authenticate the user with these credentials.

If the authentication is successful, the server logs the user in and returns a JSON response containing the status, the session token, the username, and the full name of the user. This is where the vulnerability lies.

The session token is supposed to be a secret key that allows the client to maintain a session with the server. However, by including the username and full name in the data contained in the session token, the server is potentially leaking sensitive business information.

If an attacker can somehow intercept this token, they could gain access to the user's username and full name. This information could then be used for further attacks, such as identity theft or phishing.

Therefore, it is a bad practice to include such sensitive information in the session token. Instead, only the absolute necessary information should be stored in the session, and everything else should be retrieved from the server as needed using the session token for authentication.

Steps

  • Remove sensitive user information from the session token. The token should not contain any personal data such as username, email, or full name.
  • Use a secure method to generate the session token. This could be a random string that does not contain any user information.
  • Store the session token on the server side. This way, the token can be used to identify the session, but it does not need to contain any user information.
  • Use HTTPS for all communications. This will ensure that the session token is always transmitted securely.
  • Implement token expiration. This will limit the time window in which a token can be used, reducing the risk of token theft.

Compliant code

from django.contrib.auth import authenticate, login
from django.http import JsonResponse
from django.middleware.csrf import get_token

def login_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)

if user is not None:
login(request, user)
csrf_token = get_token(request)
return JsonResponse({"status": "success", "token": csrf_token})
else:
return JsonResponse({"status": "error", "message": "Invalid credentials"})

The updated code now removes the sensitive user information from the session token. The token is generated using Django's built-in get_token function, which creates a secure CSRF token that can be used to authenticate the user's session. This token does not contain any user information, making it much more secure.

The username and fullname fields have been removed from the JSON response. This ensures that no sensitive user information is included in the session token. The only information returned in the JSON response is the status of the login attempt and the session token.

The session token is stored on the server side, which means it can be used to identify the session without needing to include any user information. This greatly reduces the risk of a business information leak.

It's also recommended to use HTTPS for all communications to ensure that the session token is always transmitted securely. This is not shown in the code, but it's a crucial part of securing the session token.

Finally, Django's session framework automatically implements token expiration. This limits the time window in which a token can be used, reducing the risk of token theft.

References