Session Hijacking and Session Fixation: How Attackers Skip the Password Step
The login wall only stops people without credentials. Everything after login runs on a bearer token — and whoever holds your session cookie bypasses authentication entirely. The two classic attacks on that trust, and the fixes that actually matter.
📑 Table of contents
You can have a twelve-character password, hardware two-factor, and a lock icon in the address bar — and still get fully compromised without any of it firing. Because the moment you log in, all of that is traded for a small string of text: the session cookie. From then on, the server does not check your password, your 2FA, or your device. It checks the cookie. Whoever holds it is you.
That trade is what makes sessions fast — and what makes them the highest-value target on any authenticated website. Attackers do not break authentication; they skip it.
Sessions are bearer tokens
Understand the mechanics first, because both attacks fall straight out of them. At login, the server creates a session record and puts its identifier in a cookie. Every subsequent request carries that cookie, and the server looks up the session — no re-authentication, no challenge. The cookie security guide covers the attributes that protect this token; here we are after the attacks themselves.
A bearer token means possession equals identity. There is no "proof it's really you" step after login. So the entire game becomes: get the token.
Session hijacking: four theft paths
Path 1 — XSS without HttpOnly. If your site has a cross-site scripting flaw and the session cookie is readable from JavaScript, the attack is one injected script away: document.cookie, exfiltrate, done. HttpOnly denies script access to the cookie, which is why its absence is a finding on every serious scan — it converts a lethal chain into a survivable one.
Path 2 — The network. Without HTTPS (or with a cookie missing the Secure flag, letting it travel on an accidental plain-HTTP request), anyone on the path — hostile Wi-Fi, compromised router, BGP mishap — reads the token off the wire. The Secure flag exists precisely for the edge cases: that one redirect, that mixed-content page, that staging subdomain where TLS is misconfigured.
Path 3 — The URL. Applications that accept session identifiers from URL parameters (some legacy frameworks did) leak the token into referrer headers, browser history, proxy logs, and shoulder-surfing. A session ID should live in a cookie and nowhere else.
Path 4 — Infostealer malware. The most common path in the current threat landscape: credential-stealing malware on the victim's own machine harvests browser cookie stores wholesale. You cannot harden the cookie against the victim's own infected endpoint — which is why server-side controls (short expiry, rotation, anomaly handling) matter as the backstop.
Session fixation: the attack that needs no theft
Fixation is quieter and, in a way, more elegant: the attacker never needs to steal anything.
- The attacker obtains or sets a session identifier the application will accept — planting a cookie on the victim's browser (via a vulnerable subdomain, an HTTP response on the path, or a link containing the ID if the app accepts it).
- The victim logs in. The application authenticates them — and keeps using the same session identifier instead of generating a fresh one.
- The attacker reloads the page with the identifier they already know. They are now logged in as the victim.
The vulnerability is purely about rotation: the server must issue a brand-new session ID at every privilege change — most importantly at login. If the identifier survives the transition from anonymous to authenticated, whoever arranged the pre-login identifier owns the post-login session.
This is one of the oldest web vulnerabilities on record, and it still ships in new code, because nothing about it looks like a bug: login works, sessions work, everything works — right up until someone thinks like an attacker.
Why "logout" so often doesn't
The third failure is the one nobody tests: clicking logout, then checking whether the session actually died server-side. The lazy implementation deletes the cookie in the browser and calls it done — but the server-side session record remains valid until expiry. A stolen copy of the token keeps working after the victim "logged out."
Worse is the password-change case: a user who suspects compromise changes their password — and on many applications, all existing sessions survive the change. The attacker keeps their access through the very remediation meant to evict them.
The correct behavior, non-negotiable for admin panels and anything payment-adjacent:
- Logout invalidates the server-side session record, not just the cookie
- Password change invalidates all sessions for the account
- Sessions expire on a sane idle timeout (hours, not months) and an absolute cap
The defensive checklist
- Regenerate the session ID on every privilege change — login, role elevation, re-authentication. This single fix kills fixation.
- Set the cookie attributes: HttpOnly, Secure, SameSite=Lax or Strict, scoped to the tightest path and domain that works.
- Invalidate server-side on logout and password change — all sessions, not just the current one.
- Keep idle and absolute timeouts honest. An admin session that lives for thirty days of inactivity is a standing invitation.
- Never put session IDs in URLs.
- Pair with XSS defenses. CSP (see the Content-Security-Policy guide) and output encoding close the cheapest theft path.
How 2MNY tests all three failure modes
Session weaknesses are invisible to "does it work" testing — everything works while being wide open. So the 2MNY session security module attacks the session lifecycle the way an attacker would, using three automated checks: it plants a session identifier and verifies the application rotates it at login (the fixation test); it audits every Set-Cookie for HttpOnly, Secure, and SameSite straight off the raw headers; and it performs a real logout flow with the CSRF token and then verifies the old session is refused server-side. For sites that opt in, the authenticated scanning module logs in with test credentials and diffs the session behavior of the logged-in surface against the public one.
Run a free scan at 2mny.com — the session checks are part of every scan, and each finding comes with the evidence and the fix, not just a warning. If you are dealing with a compromise right now, the first-hour checklist covers the session-eviction step that has to happen before anything else.
Authentication is a gate. Sessions are the wristbands everyone after the gate is wearing — and attackers long ago stopped attacking the gate.
Security engineer building 2MNY — 292 free website-security checks — and the open-source Website Vulnerability Scanner. I find exposed secrets, misconfigurations and real vulnerabilities, then explain how to fix them in plain language.
1 Does HTTPS prevent session hijacking?
It prevents one path: passive network interception of the cookie in transit. It does nothing against XSS stealing cookies that lack the HttpOnly flag, infostealer malware on the victim's machine, session identifiers leaked in URLs, or servers that keep accepting old tokens after password changes. HTTPS is necessary but nowhere near sufficient.
2 How do I test my site for session fixation?
Plant a session cookie you control (set one yourself via a subdomain or a URL parameter if the app accepts one), then log in through the normal form, and check whether the application issued a fresh session identifier or kept the planted one. Only a fully regenerated identifier on login passes. 2MNY's session security module runs this exact test automatically, along with cookie attribute checks and logout invalidation.
3 What is the difference between session hijacking and session fixation?
In hijacking, the attacker steals a session identifier that the server already issued to a real logged-in user — via XSS, network interception, or malware. In fixation, the attacker never steals anything: they plant a known session identifier on the victim first, the victim logs in, and the server keeps using the planted identifier — so the attacker already has it. Hijacking is a theft problem; fixation is a rotation problem.
4 Why doesn't logging out on one device kill my sessions everywhere?
Because many applications implement logout as a client-side cookie deletion: the browser forgets the token, but the server still accepts it. A stolen copy of that token keeps working until it expires naturally. Real logout invalidates the session server-side — and high-value applications also invalidate all existing sessions when the password changes.