Session Fixation - Session-Übernahme durch vorgegebene Session-ID
Session fixation is an attack in which an attacker provides a valid session ID to a victim and waits until the victim authenticates using that pre-determined session. Unlike session hijacking (stealing an existing session), the attacker sets the session ID before the user logs in. After authentication, the attacker uses the known session ID to gain unauthorized access. Protection: generate a new session ID after login, SameSite cookies, HttpOnly flag.
Session Fixation exploits a common implementation flaw in session management: Instead of generating a new session ID after login, the application retains the existing one. An attacker who knows the session ID before login (because they set it themselves) gains full access to the authenticated session once the victim logs in.
Attack Principle
Session Hijacking vs. Session Fixation
Session Hijacking (classic):
- Victim logs in → new session ID generated
- Attacker steals session ID (XSS, network sniffing)
- Attacker uses stolen session
Session Fixation (alternative):
- Attacker knows a valid session ID (e.g., from their own registration)
- Attacker passes this ID to the victim (URL, cookie manipulation)
- Victim logs in → session ID remains the same (error!)
- Attacker has full control over the authenticated session!
Step-by-Step Process
Step 1 - Attacker obtains valid session ID:
GET https://bank.com/
→ Set-Cookie: SESSIONID=abc123def456 (Server sends session for anonymous user)
Step 2 - Attacker provides session ID to victim:
- Method A (URL parameter, previously possible):
https://bank.com/login?SESSIONID=abc123def456→ Victim clicks link, browser retrieves session ID from URL - Method B (JavaScript-based, more common today): XSS on a subpage of bank.com sets
document.cookie = "SESSIONID=abc123def456"- sets attacker's session ID in the victim's browser - Method C (Response Header Injection, less common): If the attacker can manipulate the HTTP response
Step 3 - Victim logs in:
POST https://bank.com/login
Cookie: SESSIONID=abc123def456
Body: username=alice&password;=SECRET
Vulnerable application:
- Checks credentials: correct!
- Sets session variables:
session['user'] = 'alice' - Does not refresh session ID! ← Error!
- Response:
200 OK, Cookie:SESSIONID=abc123def456
Step 4 - Attacker accesses session:
GET https://bank.com/account
Cookie: SESSIONID=abc123def456
→ Attacker has authenticated access as Alice!
Detection in the Penetration Test
Session Fixation Test
-
Record session ID before login:
GET https://target.com/→SESSIONID=XYZ(note this down!) -
Perform login:
POST https://target.com/loginwithCookie: SESSIONID=XYZand valid credentials -
Check session ID after login: Response header:
Set-Cookie: SESSIONID=...?- Secure: new session ID after login (≠ XYZ)
- Insecure: same session ID (= XYZ) → Session fixation!
-
Burp Suite test:
- Proxy → HTTP History
- Pre-login request: Note session cookie
- Post-login request: Compare cookie
- Same? → Finding!
More in-depth check
- Is the session ID accepted as a URL parameter? (e.g.,
?PHPSESSID=xyz) - Different session cookie after logout + re-login?
- Is the session invalidated after a password change?
- Is the session immediately invalidated after revocation of privileges?
Related Session Vulnerabilities
- Session not invalidated after logout (server-side)
- Session ID too short / predictable
- Session ID in URL (referrer leakage, logs!)
- Session ID in browser history (if in URL)
- No session expiration on inactivity
Mitigation Measures
1. Critical: New Session ID after Authentication
// PHP:
session_regenerate_id(true); // true = delete old session ID!
// MUST be called immediately after successful authentication!
# Python (Flask):
session.clear() # Delete old session
session['user'] = user_id # New session data
// Java (Spring Security):
// Automatic via Spring Security!
// SessionManagementConfigurer: session-fixation = change-session-id
// Node.js (express-session):
req.session.regenerate((err) => {
req.session.userId = user.id;
res.redirect('/dashboard');
});
2. Session ID via cookie only (not via URL parameter)
# PHP ini:
session.use_only_cookies = 1
session.use_trans_sid = 0
session.cookie_httponly = 1
session.cookie_secure = 1
session.cookie_samesite = Strict
3. Set cookie attributes correctly
Set-Cookie: SESSIONID=...; HttpOnly; Secure; SameSite=Lax; Path=/
- HttpOnly: no JavaScript access (prevents XSS-based fixation)
- Secure: transmitted only via HTTPS
- SameSite=Strict: no cross-site transmission (prevents CSRF + fixation via redirect)
4. Limit session lifetime
- Absolute Timeout: always invalidate session after 8 hours
- Idle Timeout: Invalidate session after 30 minutes of inactivity
- After Logout: Delete session on the server side (not just the cookie!)
5. Invalidate properly after logout
// Incorrect: Delete only the cookie
setcookie('SESSIONID', '', -1, '/');
// → Server still holds the session! An attacker with an old cookie can still gain access!
// Correct: Destroy the session on the SERVER SIDE:
session_destroy(); // PHP
req.session.destroy(); // Node.js
SecurityContextHolder.clearContext(); // Spring