Ethical Hacking
Session Hijacking
Authentication verifies identity once. Sessions maintain that identity across every subsequent request. Stealing or forging a session token gives an attacker all the access of the authenticated user — without ever needing their password, without triggering a login, and often without leaving any authentication log entry.
Sessions — the mechanism that creates the attack surface
HTTP is stateless. After authentication succeeds, the server creates a session — a server-side record linking a random identifier to the authenticated user's identity and permissions. That identifier — the session token — travels in a cookie on every subsequent request. The server looks up the token, finds the session, and knows who is making the request.
Session hijacking targets this mechanism at its weakest points — acquiring the token through theft, predicting it through weakness in the generation algorithm, or forging requests that use it without the victim's knowledge. Each technique exploits a different property of session management. Understanding all of them is what makes session management testing thorough rather than superficial.
Session token theft — acquiring a valid token
The most direct path to session hijacking is stealing a token that is already in use. A valid token gives immediate authenticated access — no cracking, no brute forcing, no bypass required. The acquisition method determines the required conditions and the countermeasures.
XSS-based cookie theft
A stored or reflected XSS payload that reads document.cookie and sends the value to an attacker-controlled server. Covered in Lesson 39 — the most common session hijacking technique in web assessments. Defeated entirely by the HttpOnly cookie flag, which prevents JavaScript from reading cookies regardless of the XSS payload.
Network capture — plaintext protocol interception
Session cookies transmitted over HTTP — without the Secure flag enforced — can be captured by anyone on the same network segment. The Wireshark and MITM techniques from Lessons 30 and 31 apply directly. Following the TCP stream of an HTTP session surfaces the Cookie header containing the session token in every request. Defeated by HTTPS everywhere and the Secure cookie flag.
Log file exposure — tokens in server logs
Session tokens appearing in URLs — rather than cookies — are logged by every web server and proxy. Web server access logs, CDN logs, analytics platforms, and browser history all capture the full URL including query parameters. A token like /dashboard?sessid=abc123 appears verbatim in every log entry for requests to that page. An attacker with read access to any of these log sources obtains valid session tokens for every user who visited the page during the log retention period.
Referrer header leakage
When a page containing a session token in its URL links to an external site, the browser includes the full URL — including the token — in the Referer header of the outgoing request. The third-party site receives a valid session token for the user in every Referer header from that page. Analytics scripts, social sharing buttons, and any embedded third-party content on the authenticated page all receive these headers automatically.
Session token replay — demonstrating hijacking in Burp
Once a session token is obtained — through any acquisition method — replaying it is trivial. The server has no way to distinguish a legitimate session cookie from a stolen one. Both arrive in the same Cookie header. Both get the same response. This is the core reason session management security matters: a stolen token is a stolen identity.
# Session token replay — demonstrating hijacking in Burp Repeater
# Requires a session token obtained through any of the acquisition methods above
# Step 1 — obtain the victim's session token
# In this lab scenario, the XSS cookie theft from Lesson 39 captured:
# PHPSESSID=abc123def456ghi789
# Step 2 — open a new browser profile or use curl to make requests
# without any existing DVWA session of your own
# Step 3 — replay the stolen token using curl
# -b sets the cookie header to the stolen session value
# This request arrives at the server with the victim's session token
# The server looks up the session, finds the victim's account, and responds
curl -b "PHPSESSID=abc123def456ghi789" \
http://192.168.56.101/dvwa/index.php
# Step 4 — same test in Burp Repeater
# Capture any request to DVWA in Burp Proxy
# In Repeater, modify the Cookie header to replace your session with the victim's
# Cookie: PHPSESSID=abc123def456ghi789
# Send the request and read the response — it should show the victim's account
# Step 5 — document the account accessed
# The response body will include the victim's username and role
# whoami equivalent for web apps: check which username appears in the response
# This is the session hijacking proof of concept for the report
--- curl response (abbreviated) --- HTTP/1.1 200 OK Set-Cookie: PHPSESSID=abc123def456ghi789; path=/ <title>Damn Vulnerable Web Application (DVWA)</title> Welcome to Damn Vulnerable Web Application! ... <p>Logged in as: <em>admin</em></p> --- Session replay confirmed --- Request used token: PHPSESSID=abc123def456ghi789 Response shows account: admin No re-authentication requested No anomaly detection triggered
Breaking it down:
The session token replay received a 200 response with the victim's account information. The server had no mechanism to detect that the request came from a different IP address, different browser, or different geographic location than the original session. Session tokens are bearer tokens — possession is proof of identity. Without additional context binding (IP binding, device fingerprinting), any possessor of the token gets the same access as the original user.
No alert fired despite a session from one IP address suddenly being used from a completely different IP. Mature session management includes anomaly detection — alerting or requiring re-authentication when a session is used from an unexpected location or device. This is a separate finding from the hijacking itself: not only was the token stolen and replayed, the application had no mechanism to detect or respond to the abnormal session usage pattern.
Session fixation — controlling the token before authentication
Session theft acquires a token after authentication. Session fixation takes the opposite approach — supplying the token before authentication and waiting for the victim to authenticate with it. If the application accepts a pre-supplied session ID and elevates it to authenticated status without generating a new one, the attacker already knows the session token that the victim just authenticated into.
The attack proceeds in three steps. The attacker obtains a valid unauthenticated session ID from the application. They send the victim a link containing that session ID — typically as a URL parameter or in a crafted cookie. The victim follows the link, lands on the login page, and authenticates. If the application uses the same session ID after authentication without regenerating it, the attacker's known session ID is now authenticated with the victim's account.
# Testing for session fixation vulnerability
# Requires two browser sessions or a Burp proxy setup
# Step 1 — visit the application without logging in
# The server issues an unauthenticated session ID in the Set-Cookie header
# Note this session ID — we will track it throughout
# Step 2 — check the initial session ID
# Look at the Cookie header in the first request to the login page
# Example initial session: PHPSESSID=unauthenticated_token_abc123
# Step 3 — log in with valid credentials through the same browser session
# The application authenticates the user
# Step 4 — check the session ID immediately after login
# A secure application regenerates the session ID on authentication
# The post-login session ID should be COMPLETELY DIFFERENT from the pre-login one
# In Burp — compare the Cookie header before and after login:
# Before login: Cookie: PHPSESSID=unauthenticated_token_abc123
# After login: Cookie: PHPSESSID=NEW_AUTHENTICATED_TOKEN_xyz789 <-- secure
# After login: Cookie: PHPSESSID=unauthenticated_token_abc123 <-- VULNERABLE
# If the session ID did NOT change after login — the application is vulnerable
# to session fixation. An attacker who supplied the pre-login session ID
# can now use it as an authenticated session without ever logging in themselves.
# Step 5 — in PHP, the fix is one line before login succeeds:
# session_regenerate_id(true);
# The true parameter deletes the old session file — preventing ID reuse
--- Pre-login session --- GET /dvwa/login.php HTTP/1.1 Cookie: PHPSESSID=unauthenticated_token_abc123 --- Post-login session (vulnerable application) --- POST /dvwa/login.php HTTP/1.1 Cookie: PHPSESSID=unauthenticated_token_abc123 [Credentials: admin:password] HTTP/1.1 302 Found Location: /dvwa/index.php Set-Cookie: PHPSESSID=unauthenticated_token_abc123 [SAME TOKEN — VULNERABLE] --- Result --- Session ID did not change after authentication Attacker who knew unauthenticated_token_abc123 now has an authenticated session Finding: Session fixation vulnerability — session ID not regenerated on login
Breaking it down:
The Set-Cookie header in the login response shows the same PHPSESSID value that existed before authentication. The session was elevated from unauthenticated to authenticated without changing its identifier. Any attacker who set this identifier — by supplying it in a crafted link — can now use their known value to access the authenticated session. The fix is session_regenerate_id(true) called immediately when authentication succeeds — one line of code eliminates the vulnerability entirely.
Cross-site request forgery — abusing an active session
CSRF does not steal the session token. Instead it abuses the fact that a victim's browser automatically includes their cookies in every request to the target domain — even requests triggered by a page on a completely different domain. An attacker crafts a malicious page that, when visited by an authenticated user, sends a state-changing request to the target application using the victim's credentials — without the victim's knowledge.
A bank transfer form that submits via POST with no CSRF token is exploitable this way. The attacker builds an HTML page with a hidden form pointing at the bank's transfer endpoint and auto-submits it on page load. When an authenticated banking customer visits the attacker's page — perhaps through a phishing email — their browser submits the transfer request with their valid session cookies. The bank processes it as a legitimate request.
The defence is a CSRF token — a unique, unpredictable value included in every state-changing form as a hidden field. The server validates it on submission. A cross-origin page cannot read this value (same-origin policy prevents cross-domain reads), so the forged request cannot include it, and the server rejects it. The SameSite=Strict cookie attribute provides a complementary defence by refusing to include the cookie in cross-site requests at all.
Is a CSRF token present in the form?
Check the page source for hidden input fields named csrf_token, _token, nonce, or similar. Check the POST body in Burp for the same. Absence of any unpredictable token is a CSRF finding.
Is the CSRF token actually validated server-side?
Remove the CSRF token from the POST body entirely in Burp Repeater and resend. If the request still succeeds — the token is present in the form but not validated on the server. This is almost as bad as having no token at all.
Does the application accept GET requests for state-changing actions?
Convert the POST request to GET in Burp and resend. If state changes via GET — account settings updated, passwords changed, transfers submitted — it is trivially exploitable with an img tag or a simple link. State-changing actions must use POST with CSRF protection.
Is the SameSite cookie attribute set?
Check Set-Cookie headers for SameSite=Strict or SameSite=Lax. SameSite=Strict refuses all cross-site cookie inclusion. SameSite=Lax allows cookies in top-level navigations (clicking a link) but blocks them in cross-site POST and iframe requests. Either provides significant CSRF protection as a defence-in-depth layer.
Analysing session token quality
Not all session tokens are created with equal randomness. A predictable session token — one generated from a weak source of entropy, or using a pattern that can be extrapolated — allows an attacker to guess valid tokens without stealing them. Burp Suite's Sequencer tool is designed specifically to analyse session token randomness.
Sequencer captures a large sample of session tokens — typically 100 or more — and performs statistical analysis on their bit-level randomness. A strong token should be indistinguishable from random noise. Tokens with patterns, sequential components, or low effective entropy are flagged. The analysis takes a few minutes of automated captures and produces a clear verdict on whether the token generation is cryptographically adequate.
# Burp Sequencer — analysing session token randomness
# Run this in the Burp GUI — documented here as a step-by-step reference
# Step 1 — capture a login response in Burp Proxy
# The response should contain a Set-Cookie header with the session token
# Step 2 — send to Sequencer
# Right-click the response in Burp → Send to Sequencer
# Step 3 — configure the token location
# In Sequencer → Token Location, select the cookie parameter containing the session ID
# Burp needs to know exactly which part of the response is the token
# Step 4 — run live capture
# Click Start Live Capture
# Burp repeatedly sends the captured request and records each new session token issued
# Let it collect at least 200 tokens for meaningful statistical results
# Step 5 — analyse
# After collection, click Analyse Now
# Burp performs FIPS-140 randomness tests on the token sample
# What the results mean:
# Effective entropy > 100 bits = strong (cryptographically adequate)
# Effective entropy 60-100 bits = moderate (borderline — flag for review)
# Effective entropy < 60 bits = weak (predictable — significant finding)
# Patterns detected = critical (token generation is algorithmically predictable)
--- Burp Sequencer Results --- Tokens analysed: 200 Token length: 26 characters (PHP default session ID) Overall result: EXCELLENT Effective entropy: 112 bits FIPS tests: Monobit test: PASS Poker test: PASS Runs test: PASS Long runs test: PASS Autocorrelation: PASS Verdict: The session tokens appear to be randomly generated with sufficient entropy. No patterns detected. Token prediction is not considered a viable attack path against this application. --- Example of a WEAK token result (for comparison) --- Effective entropy: 18 bits Autocorrelation: FAIL — sequential pattern detected Verdict: Tokens are predictable. Brute force or extrapolation feasible.
Breaking it down:
PHP's default session ID generation passes all randomness tests with 112 bits of effective entropy. This means the token space is large enough that guessing or brute forcing valid tokens is computationally infeasible. A negative result — low entropy, sequential patterns, autocorrelation — would indicate the application is using a weak random source such as a timestamp, an incremental counter, or an insufficiently seeded PRNG.
The comparison result with 18 bits is based on real-world findings from applications that generated session IDs from Unix timestamps, username hashes, or sequential integers. With 18 bits of entropy, the attacker only needs to test 2^18 = 262,144 possible values — feasible in seconds with a scripted attack. A predictable session token effectively removes authentication as a security boundary.
Session management security controls — the complete picture
Comprehensive session management security requires multiple controls applied together. Each control addresses a different attack vector — no single setting stops all session attacks.
| Control | Attack prevented | Test |
|---|---|---|
| HttpOnly flag | XSS-based cookie theft — JavaScript cannot read the token via document.cookie | Check Set-Cookie header in Burp |
| Secure flag | Network interception — cookie only transmitted over HTTPS connections | Check Set-Cookie header in Burp |
| SameSite=Strict | CSRF — cookie not included in cross-site requests regardless of CSRF token presence | Check Set-Cookie header in Burp |
| Session regeneration on login | Session fixation — new token issued after authentication prevents pre-supplied token elevation | Compare token before and after login |
| Server-side invalidation on logout | Session replay after logout — token becomes invalid server-side, not just deleted client-side | Replay token after logout in Burp |
| High-entropy token generation | Token prediction — CSPRNG with sufficient entropy makes brute force computationally infeasible | Burp Sequencer analysis |
Every row in that table is a testable condition, a specific attack it prevents, and a specific test method. A session management assessment that checks all six and confirms each passes — with Burp evidence for each — is a complete session security assessment. Finding any one of these missing is a reportable finding with a clear, specific remediation.
Teacher's Note: CSRF testing is routinely skipped in web assessments because it requires building a proof-of-concept page to demonstrate exploitability — more effort than most other findings. Resist the temptation to skip it. A missing CSRF token on a sensitive action — password change, account settings update, admin function — is a critical finding. The Burp CSRF PoC generator (right-click any request → Engagement tools → Generate CSRF PoC) builds the HTML proof-of-concept automatically in under ten seconds.
Quiz
Scenario:
Scenario:
Scenario:
Up Next · Lesson 42
File Upload Vulnerabilities
Bypassing file type restrictions, uploading web shells, and the filter bypass techniques that turn an innocent upload form into remote code execution.