Missing Session Timeout – Bug Bounty Guide 2026

By Devashish

Published on:

Missing Session Timeout
๐Ÿ› Bug Bounty Series

Missing Session Timeout โ€”
Complete Bug Bounty Guide 2026

Missing Session Timeout extends the attack window of every session vulnerability โ€” a stolen token valid for 7 days is catastrophic compared to one expiring in 15 minutes. This guide covers idle timeout, absolute timeout, JWT expiry testing, and all framework fixes.

๐Ÿ† OWASP A07:2021 ๐ŸŸ  Low โ†’ High ๐ŸŽฏ Beginner โฑ๏ธ CWE-613 ๐Ÿ’€ Force Multiplier

๐Ÿ” What is Missing Session Timeout?

Missing Session Timeout occurs when an application fails to automatically terminate a user’s session after inactivity or after a maximum absolute duration. A session that never expires โ€” or one that lasts days โ€” dramatically extends the window attackers have to exploit any stolen, captured, or abandoned session token.

Missing Session Timeout diagram showing attacker replaying a stolen session token days after the victim logged out because no idle or absolute timeout was configured

Missing Session Timeout โ€” stolen session token remains valid long after victim expects it to be dead

๐Ÿ’ก Core Concept

Missing Session Timeout is a force-multiplier. It does not create a session attack on its own โ€” it makes every other session attack (XSS theft, network sniffing, shared device access) far more dangerous by extending the attack window from minutes to hours, days, or even permanently. A 15-minute token stolen via XSS causes limited damage. The same token valid for 30 days is a catastrophe.

๐Ÿ”ด Critical โ€” JWT with no exp claim = permanent access
๐ŸŸ  High โ€” Session valid for 24+ hours or days
๐ŸŸก Medium โ€” Session valid for 1โ€“8 hours with no idle timeout

โšก Two Types of Session Timeout โ€” Both Must Be Configured

โฑ๏ธ Idle Timeout (Inactivity)
Session expires after N minutes of no activity
Resets on every authenticated request
Protects: shared computers, unattended sessions
Recommended: 15โ€“30 min for sensitive apps
Test: wait 30 min idle โ†’ replay token
๐Ÿ”’ Absolute Timeout (Max Lifetime)
Session expires after N hours regardless of activity
Forces re-authentication even for active users
Protects: long-lived token replay, privilege drift
Recommended: 8โ€“24 hours maximum
Test: keep session active for 8+ hours โ†’ test
โš ๏ธ Both Must Be Configured Independently

An app can have idle timeout but no absolute timeout โ€” a user who keeps clicking around can stay logged in forever. And an app can have absolute timeout but no idle timeout โ€” stepping away from a terminal for 4 hours leaves a wide-open window. Test both separately.

๐Ÿ“Š Severity Scales Directly With Token Lifetime

15 min
โœ… Best Practice
30 min
โœ… Acceptable
1โ€“4 hours
โš ๏ธ Low โ€” Info Finding
8โ€“24 hours
๐ŸŸ  Medium Finding
2โ€“7 days
๐Ÿ”ด High Finding
30+ days / Never
๐Ÿ”ด Critical Finding

๐Ÿ“Š Missing Session Timeout โ€” Quick Reference

FieldDetails
VulnerabilityMissing Session Timeout
Also Known AsInsufficient Session Expiration, No Idle Timeout, Long-lived Session, CWE-613
OWASPA07:2021 โ€” Identification and Authentication Failures
CWECWE-613: Insufficient Session Expiration
CVE Score4.3 โ€“ 7.5 (scales with lifetime duration)
SeverityLow โ†’ High โ†’ Critical (JWT with no exp = Critical)
Root CauseNo server-side session expiry; JWT with far-future or missing exp; default framework values
Where to CheckCookie Max-Age/Expires | JWT exp claim | Session after 30+ min idle | Session after 8+ hours
Best ToolsBurp Suite Repeater, curl, Python requests, jwt_tool, browser DevTools
Practice LabsPortSwigger Authentication Labs, HackTheBox, TryHackMe, OWASP WebGoat
DifficultyBeginner โ€” requires only waiting and replaying; no technical exploit skill needed
Force MultiplierMakes every other session vulnerability more severe โ€” always report in combination
Related VulnsSession Hijacking, Insecure Logout, Session Fixation

๐Ÿง  Manual Testing for Missing Session Timeout

๐Ÿ“Œ The Testing Rule

Always test two things separately: (1) idle timeout โ€” does session expire after inactivity? (2) absolute timeout โ€” does session expire after a maximum duration even with continuous activity? Both can be missing independently.

Phase 1 โ€” Idle Timeout Test

Wait and Replay โ€” No Technical Skill Required
1
Login and Capture Session Token
Login โ†’ Burp HTTP History โ†’ note session cookie or JWT. Or use curl with -c cookies.txt to save. Record the exact time of login.
2
Confirm Baseline โ€” Token Works
Immediately call GET /api/me with the saved token. Confirm 200 OK and user data returned. This is your baseline proof that the session was valid.
3
Wait โ€” Make No Requests During This Period
Do absolutely nothing for 30 minutes. No browser activity, no API calls, no refreshes. Genuine idle time. Then replay the old token.
4
Test at Progressive Intervals
Test at 30 min, 60 min, 2 hours, 8 hours, 24 hours. Document each result. The exact lifetime window is the severity-determining factor in your report.
Idle Timeout Test โ€” curl
# Step 1: Login and save session
curl -c cookies.txt -X POST https://target.com/api/login \
     -H 'Content-Type: application/json' \
     -d '{"email":"test@test.com","password":"test123"}'

# Step 2: Confirm baseline works
curl -b cookies.txt https://target.com/api/me
# โ†’ {"user_id":1001,"email":"test@test.com"}

# Step 3: Wait 30 minutes (genuinely idle)
sleep 1800

# Step 4: Replay old session
curl -b cookies.txt https://target.com/api/me
# SECURE:     HTTP 401 Unauthorized
# VULNERABLE: HTTP 200 + user data โ†’ idle timeout MISSING

Phase 2 โ€” Absolute Timeout Test

Absolute Timeout โ€” Keep Session Alive and Test
# Keep session alive with periodic pings, test for absolute expiry
START=$(date +%s)
while true; do
  CODE=$(curl -b cookies.txt -s -o /dev/null -w '%{http_code}' \
         https://target.com/api/me)
  ELAPSED=$(( ($(date +%s) - $START) / 60 ))
  echo "t+${ELAPSED}min: HTTP $CODE"
  [ "$CODE" = '401' ] && echo "Session expired at t+${ELAPSED}min" && break
  sleep 300  # ping every 5 min to keep alive
done

# Expected results:
# t+480min (8h): 401 โ†’ Good absolute timeout
# t+1440min (24h): 200 OK โ†’ Missing absolute timeout!

Phase 3 โ€” Password Change Session Invalidation

Session Invalidation on Password Change
# Session 1: Login from Device A
curl -c session1.txt -X POST https://target.com/api/login \
     -d '{"email":"test@test.com","password":"test123"}'

# Session 2: Login from Device B (different session)
curl -c session2.txt -X POST https://target.com/api/login \
     -d '{"email":"test@test.com","password":"test123"}'

# Change password using Session 1
curl -b session1.txt -X POST https://target.com/api/password/change \
     -d '{"old":"test123","new":"NewPass456!"}'

# Test Session 2 (other device) after password change
curl -b session2.txt https://target.com/api/me
# SECURE:     401 โ†’ All other sessions invalidated on password change
# VULNERABLE: 200 โ†’ Session 2 still valid despite password change!

๐Ÿ” JWT Expiry Testing โ€” Deep Dive

๐Ÿšจ Most Common Critical Finding

JWT tokens with no exp claim or with exp set to year 2099 are a Critical finding. The token can never be revoked and remains valid indefinitely. This is the #1 JWT-related session vulnerability found in bug bounty programs.

JWT Expiry Analysis
# Decode JWT payload (middle section between dots)
echo 'eyJ1c2VyX2lkIjoxMDAxfQ==' | base64 -d
# Or: python3 jwt_tool.py YOUR_TOKEN

# SECURE โ€” short expiry:
{"user_id": 1001, "exp": 1704067815}  โ† 15 min from now

# VULNERABLE โ€” far-future expiry:
{"user_id": 1001, "exp": 4102444800}  โ† Year 2099!

# CRITICAL โ€” no exp at all:
{"user_id": 1001}  โ† No exp โ†’ permanent token

# Convert exp timestamp to human date:
python3 -c "import datetime; print(datetime.datetime.fromtimestamp(4102444800))"
# โ†’ 2099-12-31 00:00:00
Test If Server Validates exp Claim
# Even if exp is set, the server must validate it!
# Some servers issue tokens with correct exp but never check it.

# Step 1: Get a JWT with short exp (e.g. 15-minute token)
# Step 2: Wait for it to expire (wait 20 minutes)
# Step 3: Replay the expired JWT
curl -H "Authorization: Bearer EXPIRED_JWT_TOKEN" \
     https://target.com/api/me

# SECURE:     HTTP 401 {"error": "Token expired"}
# VULNERABLE: HTTP 200 + user data โ†’ exp claim NOT validated!

๐Ÿค– Tools for Missing Session Timeout Testing

๐Ÿ”ฌ Burp Repeater
Send authenticated request to Repeater, wait 30+ minutes, click Send again โ€” simplest idle timeout test.
HTTP History โ†’ right-click โ†’ Send to Repeater โ†’ wait โ†’ Send
๐ŸŒ curl
Save session with -c, replay with -b. Run in bash loop to test at time intervals.
curl -c cookies.txt /login ; sleep 1800 ; curl -b cookies.txt /api/me
๐Ÿ Python
Automate multi-interval testing โ€” login, wait, test at 15/30/60/120/480 min, report lifetime.
time.sleep(interval); requests.get(url, cookies=session)
๐Ÿ” jwt_tool
Decode JWT, display exp in human-readable date, test if server validates the exp claim.
python3 jwt_tool.py TOKEN โ†’ shows exp as readable date
๐Ÿ–ฅ๏ธ DevTools
Application โ†’ Cookies โ€” check Expires column for session cookie lifetime hint.
F12 โ†’ Application โ†’ Cookies โ†’ Expires column
๐ŸŒ epochconverter.com
Convert JWT exp Unix timestamp to human-readable date โ€” instantly shows if token expires in 2099.
epochconverter.com โ†’ paste exp value โ†’ read date

๐Ÿ”ฅ Burp Suite โ€” Missing Session Timeout Guide

1
Idle Timeout Test in Repeater
Login โ†’ HTTP History โ†’ find GET /api/me โ†’ Ctrl+R (Repeater) โ†’ Send (confirm 200 baseline) โ†’ wait 30 min โ†’ Send again. 200 OK = idle timeout missing.
2
Check Cookie Expiry in Set-Cookie Header
HTTP History โ†’ login response โ†’ Headers tab โ†’ Set-Cookie. Check for Max-Age or Expires attribute. Missing both = no client-side hint, but also test server-side.
3
JWT Expiry in Burp Decoder
Copy JWT โ†’ Decoder tab โ†’ paste middle section (payload) โ†’ Decode as Base64 โ†’ read exp value. Then visit epochconverter.com to convert Unix timestamp to human date.
4
Test Server-Side Enforcement of JWT exp
Wait for JWT to pass its exp time โ†’ send it again in Repeater. 200 OK despite expired exp claim = server doesn’t validate it โ€” Critical finding regardless of exp value.

๐Ÿ“‹ Recommended Timeout Values by Application Type

Application TypeIdle TimeoutAbsolute TimeoutRisk if Missing
Banking / Finance5โ€“15 min4โ€“8 hoursCritical โ€” direct financial loss
Healthcare / Medical10โ€“15 min4โ€“8 hoursCritical โ€” HIPAA violation risk
E-Commerce / Payments15โ€“30 min8 hoursHigh โ€” payment data exposure
Admin / Staff Panels15 min4โ€“8 hoursHigh โ€” privileged operations
Standard Web App30 min8โ€“24 hoursMedium โ€” general user data
JWT Access Tokens5โ€“15 minN/A (use refresh)Critical โ€” use refresh token pattern
JWT Refresh TokensN/A24 hours maxHigh โ€” rotate on every use

๐Ÿ› ๏ธ Framework Secure Configuration Reference

FrameworkVulnerable DefaultSecure Configuration
PHPsession.gc_maxlifetime = 1440session.gc_maxlifetime = 900;
Node/Expresscookie: {} // no maxAgecookie: { maxAge: 15 * 60 * 1000 }
DjangoSESSION_COOKIE_AGE = 1209600SESSION_COOKIE_AGE = 900
Spring Boot# no timeout configuredserver.servlet.session.timeout=15m
Laravel‘lifetime’ => 120‘lifetime’ => 15, ‘expire_on_close’ => true
JWTexp: now + (86400 * 365)exp: Math.floor(Date.now()/1000) + 900
Redis sessionsSET session:ID valueSET session:ID value EX 900

๐Ÿ”— Real Missing Session Timeout Bug Chains

๐Ÿ’‰
XSS Steals Token + No Timeout = Days of Persistent Access
XSS steals session token โ†’ victim logs in next day โ†’ token still valid 7 days later โ†’ attacker maintains access for entire week without re-exploitation
CRITICAL ๐Ÿ’ฐ
๐ŸŒ
JWT exp=2099 โ†’ Single Leak = Permanent Access
JWT leaked via log exposure or XSS โ†’ exp claim = year 2099 โ†’ token valid indefinitely โ†’ attacker has permanent account access โ€” no way to revoke without architecture change
CRITICAL ๐Ÿ’ฐ
๐Ÿ’ป
Shared Computer + No Idle Timeout = Next User Access
User logs into bank on library computer โ†’ closes browser without logout โ†’ no idle timeout โ†’ next person opens browser โ†’ session still active โ†’ account access
HIGH ๐Ÿ’ฐ
๐Ÿ“ก
Network Sniff + No Absolute Timeout = Week-Long Access
Token sniffed on cafรฉ WiFi โ†’ session valid for 30 days โ†’ attacker has month-long window to access victim’s account โ†’ financial fraud, PII exfiltration possible
HIGH ๐Ÿ’ฐ
๐Ÿ”‘
No Timeout After Password Change = Former Employee Access
Employee leaves company โ†’ password changed โ†’ existing session tokens never invalidated โ†’ former employee still authenticated โ†’ access to company systems for days
HIGH ๐Ÿ’ฐ
๐Ÿ—‚๏ธ
No Timeout + IDOR = Extended Data Exfiltration Window
Single compromised session โ†’ no timeout โ†’ attacker has days to enumerate all user IDs via IDOR at leisure โ†’ mass PII exfiltration without re-authentication pressure
HIGH ๐Ÿ’ฐ

๐Ÿ›ก๏ธ Defense Against Missing Session Timeout

โœ… The Core Fix

Configure both idle timeout AND absolute timeout server-side. Set JWT exp to 15 minutes maximum for access tokens. Use refresh tokens for longer sessions. Invalidate ALL sessions on password change and logout.

Server-Side Session Timeout Implementation
// Node.js / Express โ€” Both timeout types
app.use(session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: {
        httpOnly: true,
        secure:   true,
        sameSite: 'strict',
        maxAge:   15 * 60 * 1000  // 15 min idle timeout
    },
    rolling: true,  // reset idle timer on every request
}));

// Absolute timeout middleware
app.use((req, res, next) => {
    if (req.session?.loginTime) {
        const elapsed = Date.now() - req.session.loginTime;
        if (elapsed > 8 * 60 * 60 * 1000) {  // 8 hour absolute
            req.session.destroy();
            return res.status(401).json({error: 'Session expired'});
        }
    }
    next();
});

// JWT โ€” always set short exp
const token = jwt.sign(
    {user_id: user.id, role: user.role},
    process.env.JWT_SECRET,
    {expiresIn: '15m'}  // never omit expiresIn!
);
๐Ÿ“‹ Session Timeout Security Checklist

โ˜‘ Idle timeout configured server-side โ€” 15-30 min for sensitive apps
โ˜‘ Absolute timeout enforced โ€” 8-24 hours regardless of activity
โ˜‘ JWT access tokens: exp = 15 minutes maximum โ€” use refresh tokens
โ˜‘ JWT refresh tokens: 24-hour expiry, deleted from DB on use
โ˜‘ All sessions invalidated on password change
โ˜‘ All sessions invalidated on logout โ€” not just current device
โ˜‘ Cookie Max-Age set to match server-side timeout value
โ˜‘ Server validates JWT exp on every request โ€” not just issuance
โ˜‘ Provide “logout all devices” feature for users
โ˜‘ Log session creation/expiry for audit trail

๐Ÿง  Key Takeaways โ€” Missing Session Timeout

  • Missing Session Timeout is a force-multiplier โ€” it makes every session attack more severe by extending the window
  • Test two things separately: idle timeout (inactivity) AND absolute timeout (max lifetime)
  • Always decode every JWT and check the exp claim โ€” far-future or missing = Critical finding
  • Severity scales with token lifetime โ€” hours = Low/Medium, days = High, never = Critical
  • Client-side Max-Age alone is NOT sufficient โ€” server-side must also expire the session
  • Test at specific intervals: 15, 30, 60 min; then 2, 4, 8, 24 hours โ€” document the exact lifetime
  • Test session invalidation on password change โ€” often missed separately from timeout testing
  • JWT with no exp claim = one of the most common Critical findings in modern bug bounty programs
  • Frame impact clearly: “token remains valid for X days” โ€” numbers make severity undeniable
  • Banking/healthcare: 5-15 minute idle timeout is the standard โ€” anything beyond that is a reportable finding
๐Ÿ’ฐ Real Bounty โ€” $4,000

A SaaS platform issued JWT tokens with exp set to year 2099. Any single token leak gave permanent account access. The fix was three characters in the JWT issuance code: expiresIn: '15m'. Bounty paid: $4,000. One field. Maximum severity. Always check the exp claim.

๐Ÿ’ฌ Found this Missing Session Timeout guide helpful? Share it!

Related Posts

Session Hijacking – Bug Bounty Guide 2026

Session Fixation โ€” Bug Bounty Guide 2026

Weak Password Policy โ€” Bug Bounty Guide 2026

Devashish

Iโ€™m Devashish, a Bug Bounty Researcher and Cyber Security Analyst sharing practical insights โ€” from beginner payloads to advanced exploitation chains โ€” explained in a simple, clear way. Beyond cybersecurity, Iโ€™m passionate about technology, gadgets, and topics like health, cricket, politics, and people.

Leave a comment