HIGH session fixationflaskfirestore

Session Fixation in Flask with Firestore

Session Fixation in Flask with Firestore — how this specific combination creates or exposes the vulnerability

Session fixation occurs when an application assigns a user a session identifier before authentication and does not regenerate that identifier afterward. In a Flask app using Firestore as the session store, the risk arises from how session identifiers are created, stored, and validated. Flask’s default cookie-based sessions can rely on SESSION_COOKIE_NAME and SESSION_COOKIE_HTTPONLY settings, but if the server does not issue a new session ID after login, an attacker can set a known session ID on the victim’s browser and later hijack the authenticated session.

When Firestore is used to persist session data (for example via a custom session interface that reads and writes session documents by session ID), the session ID becomes a key into a user-specific document in a collection such as sessions. If the session ID is predictable or not rotated on authentication, an attacker who knows the ID can read or modify the corresponding Firestore document, assuming the security rules permit it. Even with restrictive Firestore rules, fixation undermines identity boundaries: the server treats the pre-auth session ID as equivalent to a post-auth session ID because it does not recreate the document or reissue the ID after login.

Consider a naive implementation where session data is stored in Firestore under a sessions collection, keyed by session ID, with fields like user_id, created_at, and expires. If Flask creates the session cookie once and never calls session.regenerate(), the same document is referenced before and after authentication. An attacker can craft a URL with a known session ID, trick a user into authenticating, and then use the now-authenticated Firestore document to impersonate the user. This maps directly to the OWASP API Top 10 session management issues and parallels classic web session fixation, but with the added complexity of server-side document lookups in Firestore.

Additionally, if the API endpoints that read or update session data in Firestore do not enforce strict input validation on the session ID, an attacker may leverage path traversal or malformed IDs to access documents outside the intended scope. Because middleBrick tests input validation and BOLA/IDOR across 12 checks in parallel, such a misconfiguration would likely be flagged as a high-severity finding under Authentication and Property Authorization categories, with remediation guidance to rotate session identifiers post-authentication and enforce strict document ownership checks.

Firestore-Specific Remediation in Flask — concrete code fixes

To remediate session fixation when using Firestore in Flask, regenerate the session identifier immediately after successful authentication and ensure session documents in Firestore are created or updated under the new identifier. Below is a concrete, syntactically correct example that integrates Flask with Firestore using the official Google Cloud client library.

from flask import Flask, session, request, redirect, url_for
from google.cloud import firestore
import os
import secrets

app = Flask(__name__)
app.secret_key = os.environ.get('FLASK_SECRET_KEY')

# Initialize Firestore client
db = firestore.Client()

@app.route('/login', methods=['POST'])
def login():
    username = request.form.get('username')
    password = request.form.get('password')
    # Validate credentials against your user store (e.g., Firestore 'users' collection)
    user_doc = db.collection('users').where('username', '==', username).limit(1).get()
    user = None
    for doc in user_doc:
        # In production, verify password with a secure hash check
        if doc.to_dict().get('password') == password:  # placeholder; use hashing in practice
            user = doc
            break
    if user is None:
        return 'Invalid credentials', 401

    # Critical remediation: regenerate session to prevent fixation
    session.regenerate()

    # Write a new session document keyed by the new session ID
    session_id = session.get('_id')  # Flask assigns this after regeneration
    db.collection('sessions').document(session_id).set({
        'user_id': user.id,
        'created_at': firestore.SERVER_TIMESTAMP,
        'expires': firestore.SERVER_TIMESTAMP  # set TTL logic separately or via TTL policy
    })

    # Ensure cookie settings are secure
    session['user_id'] = user.id
    return redirect(url_for('dashboard'))

@app.route('/profile')
def profile():
    session_id = session.get('_id')
    if not session_id:
        return redirect(url_for('login'))
    sess_doc = db.collection('sessions').document(session_id).get()
    if not sess_doc.exists:
        return redirect(url_for('login'))
    # Enforce ownership: verify that the session’s user_id matches the resource being accessed
    user_id = sess_doc.to_dict().get('user_id')
    # Fetch user-specific data, ensuring user_id aligns with the session
    user_data = db.collection('users').document(user_id).get()
    return f'Profile for {user_data.get("email")}'

Key points in this remediation:

  • session.regenerate() creates a new session identifier and discards the old one, preventing an attacker’s pre-set ID from remaining valid.
  • A new Firestore document is created under the regenerated session ID, establishing a clear one-to-one mapping between the authenticated session and the server-side document.
  • Firestore document reads and writes should always validate ownership by comparing the session’s user_id with the target resource’s user identifier, mitigating BOLA/IDOR risks.
  • Use secure, HttpOnly cookies and consider short session TTLs managed either in Firestore TTL policies or application logic to reduce the window of exposure.

For continuous assurance, middleBrick’s scans include checks for Authentication, BOLA/IDOR, and Input Validation, which can detect missing session regeneration or overly permissive Firestore security rules. If you maintain a dashboard or use the CLI (middlebrick scan <url>) as part of your workflow, these findings will be surfaced with severity and prioritized remediation guidance.

Frequently Asked Questions

How does Firestore document structure influence session fixation risk?
If session identifiers map directly to Firestore document IDs and the session ID is not rotated on login, an attacker can reuse a pre-auth document reference after authentication, effectively fixing the session to the attacker’s chosen ID.
Does Firestore’s server-side timestamp affect session fixation mitigation?
No; server timestamps are useful for TTL and audit but do not prevent fixation. The critical controls are session ID regeneration and strict document ownership checks in your Flask routes.