Access control and authentication
Log in Join

Lesson 7 · Reading · 30 min

Sessions: cookies, fixation, and logout

You log in once and stay logged in across dozens of requests. Something is carrying your identity between them, and in Foundations you learned it is a value you send. This lesson is about that value as a security object: how it should be issued, carried, and destroyed, and every point where getting that wrong hands your session to someone else.

A session cookie's flags, and the three lifecycle failures: fixation, logout, expiry

The session cookie and its flags

After login the server issues a session identifier, usually in a cookie, and your browser sends it on every request. The cookie's flags decide how well it is protected, and a missing flag is a finding you can spot by reading one Set-Cookie header:

Set-Cookie: session=8f3a...; HttpOnly; Secure; SameSite=Lax
  • HttpOnly: JavaScript cannot read the cookie. Missing it means any cross-site-scripting bug can steal the session outright, turning a contained XSS into full account takeover. This flag is why an XSS and a session-theft are, or are not, the same incident.
  • Secure: the cookie is only ever sent over HTTPS. Missing it means the session can leak over plain HTTP on a hostile network.
  • SameSite: controls whether the cookie rides along on cross-site requests, the main defence against CSRF (below). Lax or Strict is expected; None without good reason is a red flag.

Check these on every authenticated cookie. "Session cookie missing HttpOnly/Secure" is a legitimate, if modest, finding, and it changes the severity of every other client-side bug on the site.

Session fixation: the id that does not change

A session is meant to be yours, issued to you at login. Fixation is when the id does not change when you log in: the same session value you had as an anonymous visitor is simply promoted to "logged in". Why is that dangerous? An attacker can plant a known session id in a victim's browser (via a link, a set-cookie on a shared subdomain, or an injection), wait for the victim to log in, and then use that same id, now authenticated as the victim.

Test it directly: note your session cookie before logging in, log in, and look again. If the value is identical, the app does not rotate the session on authentication, and it is vulnerable to fixation. A correct app issues a brand-new id the moment you authenticate.

Logout and expiry: does the session ever actually die?

The other half is destruction, and it is where "it looks fine in the browser" hides real bugs:

  • Logout that only forgets locally. When you log out, does the server invalidate the session, or does it just tell your browser to drop the cookie? Test it: capture your session cookie, log out, then replay a request with that captured cookie. If the server still honours it, logout is cosmetic and a stolen session survives the victim clicking "log out".
  • Sessions that never expire. Does a session work indefinitely, days after issue, with no idle timeout? A stolen cookie that lives forever is far worse than one that dies in an hour.
  • Sessions that survive a password change or reset. A security-sensitive event should end other sessions. If you change your password (or complete a reset) and a session captured beforehand still works, then an attacker who stole a session keeps it even after the victim "secures" the account. Mature platforms revoke sessions on reset for exactly this reason.

Each of these is tested the same way: capture a session value, perform the event that should kill it, and see whether the old value still works.

CSRF: making the victim's session act

The session's SameSite flag defends against Cross-Site Request Forgery, worth naming here because it rides on sessions. If a state-changing action (change email, transfer funds, delete account) is triggered by a simple request the browser will auto-send the session cookie on, then a malicious page the victim visits can make that request on the victim's behalf, the victim's browser attaches the session automatically. The defences are anti-CSRF tokens (a secret the attacker's page cannot know) and SameSite cookies. Test whether a sensitive action can be replayed without a valid, per-request token, and whether it works cross-site. A missing CSRF protection on a high-impact action is a real finding.

The honesty gate

Prove session findings on your own accounts and sessions: your own captured cookie surviving your own logout, your own session id failing to rotate on your own login. For CSRF, demonstrate with a proof-of-concept page that acts on your test account. Do not hijack a real user's live session to "prove impact", the mechanism, shown on your own session, is the proof.

Your labs

Two labs exercise this. GateKeeper staff portal auth cookie hinges on a session/auth cookie that is trusted more than it should be, inspect it, understand what the server reads from it, and reach a state you should not. MoveWell Physio remember-me forgery is about a persistent "remember me" token that can be forged: the long-lived value that keeps you logged in is, itself, guessable or forgeable, so you can mint one for an account that is not yours. Both are session security, made concrete.

Where this goes next

Sometimes the token that carries your identity is not an opaque session id the server looks up, but a self-contained token that carries the identity inside it, a JWT. When the server trusts that token without verifying it correctly, the token itself becomes the vulnerability. That is the final lesson of this path.

This lesson has 3 labs to try what you just read.