HIGH session fixationdjangobasic auth

Session Fixation in Django with Basic Auth

Session Fixation in Django with Basic Auth — how this specific combination creates or exposes the vulnerability

Session fixation occurs when an attacker sets or predicts a user’s session identifier and tricks the user into authenticating with that known session. In Django, this is commonly mitigated by rotating the session key after login via request.session.cycle_key(). However, when Basic Authentication is used for API or view-level authentication, the session mechanism may be bypassed or treated inconsistently, creating a mismatch between authentication and session state.

With Basic Auth, credentials are sent on every request via the Authorization: Basic base64(username:password) header. If a view relies on session state (for example, to track authorization or store user-specific data) but does not properly rotate or validate the session after Basic Auth verification, an authenticated attacker who knows or fixes the session ID can maintain access after the victim authenticates. This is especially relevant when Django’s session middleware is active but the view does not explicitly tie the Basic Auth check to a fresh session.

Consider a scenario where an API endpoint accepts Basic Auth and also uses Django sessions for supplemental authorization checks. An attacker might craft a link that includes a known session cookie (e.g., from an unauthenticated prior visit or an insecure subdomain). When the victim visits the link and authenticates via Basic Auth, the backend validates credentials but does not ensure the session bound to the request is newly established. The attacker, already possessing the session ID, can then make subsequent requests with that cookie and be treated as the authenticated victim, effectively completing a session fixation attack.

The risk is compounded if the application does not enforce per-request authentication binding between the Basic Auth credentials and session data. For example, if the view caches authorization decisions based on session data set before credential validation, or if the session is not invalidated and recreated after a successful Basic Auth login, the attack surface remains open. This pattern is sometimes seen in legacy integrations or custom API gateways that layer Basic Auth atop existing session-based UI flows.

To detect this during a scan, tools like middleBrick analyze whether session rotation occurs after authentication and whether session state is consistently tied to the authenticated identity. Cross-referencing OpenAPI specs with runtime behavior helps identify endpoints where Basic Auth is accepted but session management is inconsistent or incomplete.

Basic Auth-Specific Remediation in Django — concrete code fixes

Remediation focuses on ensuring that authentication and session state are aligned and that session identifiers are rotated after successful authentication. Below are concrete patterns for Django views that use HTTP Basic Authentication.

Example 1: Basic Auth with session rotation after validation

import base64
from django.http import JsonResponse
from django.contrib.auth import authenticate, login
def api_protected_view(request):
    auth_header = request.META.get('HTTP_AUTHORIZATION', '')
    if not auth_header.startswith('Basic '):
        return JsonResponse({'error': 'Unauthorized'}, status=401)
    try:
        encoded = auth_header.split(' ')[1]
        decoded = base64.b64decode(encoded).decode('utf-8')
        username, password = decoded.split(':', 1)
    except Exception:
        return JsonResponse({'error': 'Bad credentials'}, status=400)
    user = authenticate(request, username=username, password=password)
    if user is not None:
        # Critical: rotate session key to prevent fixation
        if hasattr(request, 'session'):
            request.session.cycle_key()
        login(request, user)
        return JsonResponse({'status': 'ok'})
    return JsonResponse({'error': 'Invalid credentials'}, status=401)

Example 2: Using Django’s built-in login with session management

from django.contrib.auth import login
def login_view(request):
    # Assume Basic Auth credentials have been validated earlier
    user = request.user  # after authenticate
    if user.is_active:
        # Ensures a new session key is issued
        request.session.cycle_key()
        login(request, user)
        return JsonResponse({'detail': 'Logged in'})
    return JsonResponse({'detail': 'Inactive user'}, status=400)

Additional recommendations:

  • Always call request.session.cycle_key() before or immediately after login() when using session-based tracking alongside Basic Auth.
  • Avoid relying on session data set before authentication; recompute authorization based on the authenticated user object on each request.
  • If the endpoint is truly stateless, consider omitting session middleware for that view or ensuring session cookies are not relied upon for authorization decisions.
  • Use HTTPS to prevent credential interception, as Basic Auth transmits credentials on every request.

middleBrick can support this workflow by scanning endpoints that accept Basic Auth and checking whether session rotation and authentication binding are handled correctly. Its OpenAPI/Swagger analysis, with full $ref resolution, can cross-reference spec definitions with runtime behavior to highlight inconsistencies in authentication and session management.

Frequently Asked Questions

Does middleBrick fix session fixation issues found during a scan?
middleBrick detects and reports session fixation findings with remediation guidance; it does not automatically fix or patch the application.
Can the CLI be used to check for session fixation risks in CI/CD?
Yes; use the middlebrick CLI to scan endpoints from the terminal and integrate the JSON output into scripts or GitHub Action checks to enforce security thresholds.