Authentication and Session Management

AuthNSession HandlingSession Security

Authentication and Session Management at a glance

What it is: Bugs and misconfigurations that let attackers bypass login, read or change another user's session, or steal session data.
Why it happens: Lets an attacker act as a real user, including admins
How to fix: Treat session ids like secrets, set Secure and HttpOnly; Never use user input as a session key or id; Rotate strong secrets, store them outside source control; Expire and reissue sessions on login, logout, and privilege change

Overview

Authentication proves who a user is, session management keeps that identity across requests. If either is weak, an attacker can take over real accounts. Common mistakes include reading session data with user chosen keys, committing secrets to source, skipping cookie protections, and reusing sessions across privilege changes.

Good handling keeps tokens unpredictable and protected, ties the session to expected context, and keeps lifetimes short. Authentication should verify credentials with rate limits and clear failure paths.

sequenceDiagram participant Browser participant App as App Server participant Store as Session Store Browser->>App: GET /profile?key=<user_key> App->>Store: read session[<user_key>] Store-->>App: returns value App-->>Browser: 200 OK with sensitive data
A potential flow for a Authentication and Session Management exploit

Where it occurs

It shows up when handlers read from session using params, cookies, or headers as keys, when apps hardcode session secrets, or when cookie flags like HttpOnly and Secure are disabled. Weak defaults and copied snippets make this easy to miss.

Impact

An attacker can read or change another user's session state, impersonate users, and access admin functions. This leads to account takeover, leakage of personal data, fraudulent actions, and loss of trust. Because requests use a valid session, incident response and audits are harder.

Prevention

Never derive session ids or keys from user input. Load strong secrets from environment or a secret manager, never from source files. Set cookie flags Secure and HttpOnly, and SameSite=Lax or Strict where possible. Invalidate sessions on logout and privilege changes, rotate ids on login, and apply short idle and absolute expirations. Add rate limits to login, and use multi factor for sensitive actions.

Examples

Switch tabs to view language/framework variants.

Spring Boot, code decodes JWT without verifying signature

The server decodes a JWT and trusts claims without verifying its signature.

Vulnerable
Java • Spring Boot — Bad
import com.auth0.jwt.JWT;
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.IOException;

public class JwtFilter implements Filter {
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest r = (HttpServletRequest) req;
    String auth = r.getHeader("Authorization");
    if (auth != null && auth.startsWith("Bearer ")) {
      String token = auth.substring(7);
      // BUG: decode() does not verify signature
      com.auth0.jwt.interfaces.DecodedJWT decoded = JWT.decode(token);
      String role = decoded.getClaim("role").asString();
      // trust the role claim directly
      r.setAttribute("role", role);
    }
    chain.doFilter(req, res);
  }
}
  • Line 11: JWT.decode(token) parses the token but does not verify its signature
  • Line 13: Trusting claims from an unverified token allows forged tokens

Decoding a JWT without verification lets an attacker craft a token with arbitrary claims. If those claims control authorization or session state, the attacker can escalate privileges.

Secure
Java • Spring Boot — Good
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;

Algorithm algorithm = Algorithm.HMAC256(System.getenv("JWT_SECRET"));
JWTVerifier verifier = JWT.require(algorithm).build();

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
  HttpServletRequest r = (HttpServletRequest) req;
  String auth = r.getHeader("Authorization");
  if (auth != null && auth.startsWith("Bearer ")) {
    String token = auth.substring(7);
    // verify signature - throws if invalid
    DecodedJWT decoded = verifier.verify(token);
    String role = decoded.getClaim("role").asString();
    r.setAttribute("role", role);
  }
  chain.doFilter(req, res);
}
  • Line 6: Load secret from environment, not commit to source
  • Line 12: Use verifier.verify(token) which checks signature and expiration

Verifying the token signature ensures the token originated from a trusted issuer and has not been tampered with. Also check expiry and audience.

Engineer Checklist

  • Do not use request values to choose a session key or id

  • Set cookie flags HttpOnly, Secure, and SameSite

  • Load strong secrets from env or a secret manager

  • Rotate session id on login and privilege change

  • Expire sessions on logout and short idle

  • Rate limit login and require MFA for sensitive actions

End-to-End Example

A small app exposes GET /profile that reads a value from session using a key from the query string. In production the cookie lacks the Secure flag due to a copied dev config. A user on shared Wi Fi leaks a valid session.

Vulnerable
JAVASCRIPT
// Express example, similar pattern in other stacks
const express = require('express');
const session = require('express-session');
const app = express();
app.use(session({ secret: 'dev-secret', resave: false, saveUninitialized: false, cookie: { secure: false } }));
app.get('/profile', (req, res) => {
  const key = req.query.key; // bug: user controls key
  res.send(String(req.session[key]));
});
Secure
JAVASCRIPT
// Express secure handler and cookie settings
const express = require('express');
const session = require('express-session');
const app = express();
app.set('trust proxy', 1);
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: { secure: true, httpOnly: true, sameSite: 'lax' }
}));
app.get('/profile', (req, res) => {
  const allowed = new Set(['theme']);
  const key = req.query.key;
  if (!allowed.has(key)) return res.status(400).send('unsupported');
  return res.send(String(req.session[key]));
});

Discovery

This vulnerability is discovered by analyzing session cookie attributes and testing for weak session management through cookie inspection, session token predictability analysis, timeout testing, and probing for session fixation or insecure transport.

  1. 1. Observe endpoint behavior

    http

    Action

    Access the /profile endpoint with a benign query parameter to understand the response pattern

    Request

    GET https://app.example.com/profile?key=theme

    Response

    Status: 200
    Body:
    {
      "note": "Response returns 'dark', indicating the endpoint reads from session using the key parameter"
    }

    Artifacts

    http_response_body http_status
  2. 2. Test with different keys

    http

    Action

    Try various key values to confirm user-controlled session field access

    Request

    GET https://app.example.com/profile?key=last_action

    Response

    Status: 200
    Body:
    {
      "note": "Response returns '/dashboard/settings', confirming arbitrary session field read capability"
    }

    Artifacts

    http_response_body log_line
  3. 3. Identify sensitive session fields

    analysis

    Action

    Test common session field names (userId, email, role, plan_id, isAdmin) to discover what data is accessible

    Request

    ANALYSIS N/A - Analysis step

    Response

    Status: 200
    Body:
    {
      "note": "Successfully retrieved values for 'userId' (12345), 'email' (user@example.com), and 'plan_id' (premium_annual), revealing sensitive session data is exposed"
    }

    Artifacts

    session_field_inventory
  4. 4. Check cookie security flags

    browser

    Action

    Inspect cookie headers in browser developer tools and test HTTP vs HTTPS requests

    Request

    ANALYSIS N/A - Analysis step

    Response

    Status: 200
    Body:
    {
      "note": "Session cookie lacks Secure flag and is transmitted over HTTP, making it vulnerable to network interception"
    }

    Artifacts

    cookie_headers network_capture

Exploit steps

An attacker exploits this by intercepting insecure session tokens, extracting sensitive session data through parameter manipulation, hijacking sessions through cookie theft or fixation, or maintaining persistent access by exploiting sessions that never expire.

  1. 1. Extract sensitive session data

    Enumerate session fields

    http

    Action

    Systematically request known session field names to extract user identity and account details

    Request

    GET https://app.example.com/profile?key=userId

    Response

    Status: 200
    Body:
    {
      "note": "Successfully retrieved userId: 12345, email: victim@company.com, plan_id: premium_annual, and role: admin revealing complete session state"
    }

    Artifacts

    http_response_body extracted_session_data
  2. 2. Capture session cookie via downgrade

    Force HTTP connection

    http

    Action

    Trick victim into clicking HTTP link or use MITM position on shared network to downgrade connection from HTTPS to HTTP

    Request

    GET http://app.example.com/profile?key=theme

    Response

    Status: 200
    Body:
    {
      "note": "Session cookie transmitted in cleartext over HTTP, captured via network sniffing: connect.sid=s%3AjK8mN3pQ1rT5uV7wX9yZ2aB4cD6eF8gH"
    }

    Artifacts

    network_capture session_cookie
  3. 3. Hijack user session

    Replay stolen cookie

    http

    Action

    Use the captured session cookie to make authenticated requests as the victim user

    Request

    GET https://app.example.com/dashboard
    Headers:
    Cookie: connect.sid=s%3AjK8mN3pQ1rT5uV7wX9yZ2aB4cD6eF8gH

    Response

    Status: 200
    Body:
    {
      "note": "Successfully authenticated as victim, gained access to their dashboard, settings, and can perform privileged actions as admin user"
    }

    Artifacts

    http_response_body session_proof
  4. 4. Maintain persistence

    Monitor session validity

    analysis

    Action

    Periodically test the stolen session to maintain access until it expires or user logs out

    Request

    ANALYSIS N/A - Analysis step

    Response

    Status: 200
    Body:
    {
      "note": "Session remains valid for 24 hours, allowing sustained unauthorized access to victim account"
    }

    Artifacts

    session_lifetime_log

Specific Impact

Sensitive session values leak. This reveals private activity and internal state such as plan tiers or feature flags. The attacker does not need to authenticate as the victim, they only need a route that uses a param to select a session key.

Because the cookie lacked the Secure flag, any http request exposes the token. With that cookie the attacker replays the session and performs actions as the user until the session expires.

Fix

Cookie flags Secure and HttpOnly protect the token in transit and from script access. SameSite reduces cross site use.

The handler allows only a small safe subset of keys. Unknown keys get a 400.

The secret is loaded from environment, not source code.

Detect This Vulnerability in Your Code

Sourcery automatically identifies authentication and session management vulnerabilities and many other security issues in your codebase.

Scan Your Code for Free