01Summary

Session fixation is a vulnerability where an attacker tricks a user into logging in with a session ID that the attacker already knows. Because the application doesn't generate a fresh session ID after successful authentication, the attacker can use the pre-set ID to impersonate the logged-in user. This is distinct from session hijacking — the attacker doesn't steal the ID, they plant it beforehand.

02How It Happens

Session fixation occurs when an application reuses the same session identifier before and after login. Typically, a user arrives at a login page with a session ID (set by the server or carried in a URL parameter). An attacker can force a victim to use a specific session ID — for example, by sending a link like https://example.com/login?sessionid=ATTACKER_KNOWN_ID. If the application authenticates the user without invalidating and regenerating the session ID, that same ID remains valid after login. The attacker, who knows the ID, can now use it to access the authenticated session.

The root cause is usually one of two patterns: (1) the application accepts session IDs from user input (URL or cookie) without validation, or (2) the application fails to call a session regeneration function after successful authentication. Some frameworks handle this automatically; others require explicit code.

03Real-World Impact

A successful session fixation attack allows an attacker to gain full access to a victim's authenticated account without knowing their password. The attacker can view private data, modify account settings, make purchases, or perform any action the victim can perform. Because the session is legitimate from the server's perspective, detection is difficult — there are no failed login attempts or unusual IP changes to alert administrators.

04Vulnerable & Fixed Patterns

Vulnerable pattern
from flask import Flask, request, session

app = Flask(__name__)
app.secret_key = 'secret'

@app.route('/login', methods=['POST'])
def login():
    username = request.form.get('username')
    password = request.form.get('password')
    
    if authenticate(username, password):
        session['user_id'] = username
        session['authenticated'] = True
        return redirect('/dashboard')
    return redirect('/login')

Why it's vulnerable:
The session object is reused without regeneration after authentication. If an attacker set session['user_id'] before login (via a crafted URL or cookie), that same session persists after the user authenticates, allowing the attacker to use the known session ID to access the account.

Fixed pattern
from flask import Flask, request, session

app = Flask(__name__)
app.secret_key = 'secret'

@app.route('/login', methods=['POST'])
def login():
    username = request.form.get('username')
    password = request.form.get('password')
    
    if authenticate(username, password):
        session.clear()  # Invalidate old session
        session.regenerate()  # Generate new session ID
        session['user_id'] = username
        session['authenticated'] = True
        return redirect('/dashboard')
    return redirect('/login')
Vulnerable pattern
<?php
session_start();

if ($_POST['username'] && $_POST['password']) {
    if (authenticate($_POST['username'], $_POST['password'])) {
        $_SESSION['user_id'] = $_POST['username'];
        $_SESSION['authenticated'] = true;
        header('Location: /dashboard');
    }
}
?>

Why it's vulnerable:
The session ID is not regenerated after successful login. An attacker who set a known session ID before the user logged in can reuse that ID to access the authenticated session.

Fixed pattern
<?php
session_start();

if ($_POST['username'] && $_POST['password']) {
    if (authenticate($_POST['username'], $_POST['password'])) {
        session_regenerate_id(true);  // Invalidate old ID, generate new one
        $_SESSION['user_id'] = $_POST['username'];
        $_SESSION['authenticated'] = true;
        header('Location: /dashboard');
    }
}
?>

05Prevention Checklist

Regenerate session IDs after login:
Call session_regenerate_id(true) (PHP) or equivalent after successful authentication; invalidate the old session.
Never accept session IDs from user input:
Do not allow users to set or override session IDs via URL parameters or request headers; rely on the server to generate and manage them.
Use secure, httpOnly session cookies:
Set the HttpOnly and Secure flags on session cookies to prevent client-side access and transmission over unencrypted channels.
Implement session timeout:
Expire sessions after a period of inactivity and require re-authentication for sensitive operations.
Validate session state on each request:
Check that the session ID matches expected properties (e.g., user agent, IP address consistency) to detect anomalies.
Test login flows:
Verify that session IDs change after authentication in your test suite.

06Signs You May Already Be Affected

Check your application logs for patterns such as the same session ID being used across multiple user accounts, or a session ID appearing in access logs before any login attempt was recorded for that user. If you notice users reporting unauthorized access immediately after receiving a suspicious link or email, session fixation may be the cause. Review your authentication code to confirm that session_regenerate_id() or equivalent is called immediately after password verification.

07Related Recent Vulnerabilities