HIGH session fixationflaskapi keys

Session Fixation in Flask with Api Keys

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

Session fixation in Flask becomes particularly relevant when applications rely on API keys for authentication but continue to use session identifiers that can be predicted or forced. Flask’s default session handling uses signed cookies, and if the application does not rotate the session identifier after a user authenticates with an API key, an attacker can fixate a session ID before the victim authenticates.

Consider a Flask route that accepts an API key via a request header and then stores user identity in the session without issuing a new session cookie. Because the session ID remains unchanged, an attacker who knows or guesses the session ID can trick a victim into using a URL containing that ID (e.g., via a forged link or embedded image). When the victim authenticates with their API key, the server associates the authenticated identity with the attacker’s fixed session ID, allowing the attacker to hijack the session.

The vulnerability is amplified when API keys are used as bearer tokens but the server fails to treat them as equivalent to re-authentication for session rotation. Session fixation attacks fall under the Broken Access Control category in OWASP API Top 10 and can lead to unauthorized access to protected endpoints, data exposure, and privilege escalation when combined with weak session management.

In a black-box scan, middleBrick tests for indicators of session fixation by checking whether session identifiers remain constant across authentication events and whether API key usage is properly bound to session state changes. These checks are part of the BOLA/IDOR and Authentication test families and help identify missing session regeneration after successful API key validation.

Api Keys-Specific Remediation in Flask — concrete code fixes

To mitigate session fixation when using API keys in Flask, rotate the session identifier immediately after successful API key validation. Treat API key authentication as a form of login and issue a new session cookie to prevent an attacker from pre-seeding the session ID.

Below is a concrete, working example that demonstrates secure handling of API keys and session rotation in Flask.

from flask import Flask, session, request, jsonify, make_response
import secrets

app = Flask(__name__)
app.secret_key = secrets.token_bytes(32)

VALID_API_KEYS = {
    's3cr3t-k3y-1': {'user_id': 1, 'role': 'user'},
    'adm1n-k3y-2': {'user_id': 2, 'role': 'admin'},
}

@app.route('/login-with-api-key', methods=['POST'])
def login_with_api_key():
    api_key = request.headers.get('X-API-Key')
    if not api_key:
        return jsonify({'error': 'missing_api_key'}), 401

    user = VALID_API_KEYS.get(api_key)
    if not user:
        return jsonify({'error': 'invalid_api_key'}), 401

    # Regenerate session to prevent session fixation
    session.clear()
    session['user_id'] = user['user_id']
    session['role'] = user['role']
    session.permanent = True  # or manage expiry explicitly

    # Optionally rotate the session cookie name if needed
    response = make_response(jsonify({'status': 'authenticated', 'user_id': user['user_id']}))
    # Flask sets the session cookie automatically on response
    return response

@app.route('/protected')
def protected():
    if 'user_id' not in session:
        return jsonify({'error': 'unauthorized'}), 401
    return jsonify({'message': 'ok', 'user_id': session['user_id']})

if __name__ == '__main__':
    app.run(debug=False)

Key remediation steps in the example:

  • Validate the API key against a trusted source before establishing session state.
  • Call session.clear() to discard any pre-existing session data and force a new session identifier, effectively rotating the session.
  • Store only minimal claims (e.g., user_id, role) in the session after validation, avoiding storage of the API key itself.
  • Ensure the application does not accept session identifiers from query parameters or headers that could be influenced by an attacker.

For higher assurance, consider binding the session to additional context such as a hashed representation of the API key or a nonce, and enforce short session lifetimes. These practices reduce the window for fixation and limit the impact of a compromised session cookie.

Frequently Asked Questions

Does using API keys in headers prevent session fixation in Flask?
Using API keys in headers does not prevent session fixation by itself. If the Flask session identifier is not rotated after API key validation, an attacker can fixate the session regardless of how the API key is transmitted.
How does middleBrick detect session fixation risks when API keys are used?
middleBrick checks whether session identifiers remain unchanged across authentication events and whether API key usage is associated with proper session state changes, flagging missing session regeneration as a finding.