Session Security: Session Hijacking, Fixation & Credential Stuffing

HTTP is inherently a stateless protocol. To preserve user state across multiple page navigations (e.g. keeping you logged into your email or shopping cart), web applications assign a unique Session Identifier (Session ID) upon authentication. Because the possession of this session identifier is legally equivalent to knowing the user's password, compromising session tokens allows attackers to execute Session Hijacking and Account Takeover (ATO).

Session Fixation Attacks & Defenses

In a Session Fixation attack, the adversary forces a known session identifier onto a victim before the victim logs in:

  1. Attacker obtains a valid anonymous session ID from the bank website: PHPSESSID=ATTACKER_ID_999.
  2. Attacker sends the victim a link: https://bank.com/?PHPSESSID=ATTACKER_ID_999.
  3. Victim clicks the link and enters their credentials, successfully logging in.
  4. Vulnerable Behavior: The server keeps the same session ID after login! Because the attacker already knows this ID, they browse the site using PHPSESSID=ATTACKER_ID_999 and are immediately logged in as the victim.

The Fix: Session Regeneration Upon Privilege Change

Whenever a user logs in, logs out, or elevates privileges, the application must immediately destroy the old session and issue a brand new session identifier:

// In PHP: Destroy old session ID and issue a new random ID upon login
if (password_verify($password, $userHash)) {
    session_regenerate_id(true); // true deletes the old session data file!
    $_SESSION['user_id'] = $userId;
}

Defending Against Credential Stuffing & Password Spraying

  • Credential Stuffing: Attackers take billions of leaked username/password pairs from third-party breaches (e.g. from HaveIBeenPwned databases) and feed them into automated bots (like OpenBullet) to test for password reuse across your service.
  • Password Spraying: Rather than trying thousands of passwords against one user (which triggers account lockout), the attacker tests a single common password (e.g. Spring2026!) against thousands of user accounts.

The Production Session Cookie Checklist

Set-Cookie: session_id=e3b0c44298fc1c149afbf4c8996fb924; 
            Secure; 
            HttpOnly; 
            SameSite=Strict; 
            Path=/; 
            Max-Age=1800;
  • Secure: Ensures the browser only transmits the cookie over encrypted HTTPS connections.
  • HttpOnly: Blocks JavaScript document.cookie access to stop XSS theft.
  • SameSite=Strict: Forbids cross-site cookie transmission to stop CSRF.
  • Max-Age / Expires: Enforces automatic idle timeouts (e.g. 30 minutes).

Frequently Asked Questions (FAQ) - Student & Interview Review

Q1. What is the difference between an Idle Timeout and an Absolute Timeout?

An Idle Timeout invalidates the session if the user performs no activity for a period (e.g. 15 minutes). An Absolute Timeout forces a complete re-login after a fixed duration (e.g. 8 hours) regardless of active usage, limiting the lifetime of stolen tokens.

Q2. Why should account lockouts be timed rather than permanent?

Permanent account lockouts create a Denial of Service vulnerability: an attacker can write a 5-line script to submit bad passwords for every employee in your directory, locking everyone out of work. Use exponential back-off delays (e.g. 1 min, 5 mins, 15 mins).

Explore Related Cybersecurity Tutorials & Next Steps

Broaden your defensive and offensive security knowledge across our curriculum:

MFA & FIDO2 WebAuthn

Defeating password compromise and session takeover with hardware keys.

CSRF & Cookie Flag Defense

Setting HttpOnly, Secure, and SameSite attributes to lock down session cookies.

Brute Force & Credential Stuffing Defense

Implementing account lockout policies and distributed throttling.

120+ Cybersecurity Interview Q&A

How to fix session fixation and session replay vulnerabilities in web apps.

Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Reddit

You may also like this!