OWASP Web Top 10 — A07

Session Hijacking

Session Hijacking is a critical security vulnerability where attackers steal or predict session tokens to impersonate legitimate users. By exploiting weakly configured sessions, insecure cookies, or predictable identifiers, attackers can gain unauthorized access to user accounts without knowing passwords.

What Is Session Hijacking?

Session Hijacking, also known as session stealing or cookie hijacking, is an attack technique where an attacker takes over a valid user session by obtaining or predicting the session identifier. Modern web applications use session tokens (typically stored in cookies) to maintain user authentication state across multiple HTTP requests. When an application fails to properly secure these session tokens, attackers can intercept, steal, or guess them to impersonate legitimate users.

The vulnerability most commonly arises from missing or misconfigured security flags on session cookies, such as HttpOnly, Secure, and SameSite. Without these protections, session tokens become vulnerable to theft via Cross-Site Scripting (XSS) attacks, man-in-the-middle interception on unencrypted connections, or network sniffing on public WiFi. Additionally, weak session ID generation algorithms can allow attackers to predict valid session tokens without needing to steal them.

Session Hijacking falls under the OWASP Top 10 category A07: Identification and Authentication Failures. Despite being a well-documented threat with straightforward mitigation strategies, it remains a common attack vector. The impact is severe because successful hijacking grants attackers complete access to the victim's account, allowing them to perform any action the legitimate user could, often without triggering security alerts or leaving obvious audit trails.

How It Works

1
User authenticates and receives session token

A legitimate user logs into a web application with valid credentials. The server creates a session, generates a unique session ID, and sends it to the client in a cookie or URL parameter. This token is used to identify the user in subsequent requests without requiring repeated login.

2
Attacker obtains the session token

The attacker uses various techniques to steal the session token. This could be through XSS attacks that execute JavaScript to read document.cookie, network sniffing on unencrypted HTTP connections, man-in-the-middle attacks on public WiFi, or exploiting session fixation vulnerabilities where the attacker sets a known session ID.

3
Attacker replays the stolen session token

Once the attacker has obtained the session ID, they inject it into their own browser's cookie store or append it to URL parameters when making requests to the application. The attacker's browser now presents the same session identifier that the legitimate user's browser would send.

4
Server accepts the hijacked session

The server receives requests containing the stolen session token and validates it against its session store. Because the session ID is valid and still active, the server cannot distinguish between the legitimate user's requests and the attacker's requests. The application treats the attacker as the authenticated user.

5
Attacker gains full account access

With the hijacked session, the attacker can now perform any action the legitimate user could: view sensitive data, modify account settings, make transactions, or escalate privileges. The attack often goes undetected because the session appears legitimate to the application's logging and monitoring systems.

Vulnerable Code Example

Vulnerable — Java / Spring Boot
@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http)
            throws Exception {
        http
            .sessionManagement(session -> session
                // VULNERABLE: No session timeout configured
                // Sessions persist indefinitely
                .maximumSessions(1)
            )
            .csrf().disable();

        return http.build();
    }
}

@RestController
public class AuthController {

    @Autowired
    private HttpSession session;

    @PostMapping("/login")
    public ResponseEntity<?> login(
            @RequestBody LoginRequest req,
            HttpServletResponse response) {

        // Authenticate user...
        String sessionId = session.getId();

        // VULNERABLE: Cookie without HttpOnly, Secure, SameSite
        // Can be stolen via XSS and transmitted over HTTP
        Cookie cookie = new Cookie("JSESSIONID", sessionId);
        cookie.setMaxAge(86400); // 24 hours
        // Missing: cookie.setHttpOnly(true);
        // Missing: cookie.setSecure(true);
        // Missing: cookie.setSameSite("Strict");

        response.addCookie(cookie);
        return ResponseEntity.ok("Logged in");
    }
}

// VULNERABILITIES:
// 1. Session cookie accessible via JavaScript (XSS theft)
// 2. Cookie transmitted over HTTP (network sniffing)
// 3. No session timeout (indefinite validity)
// 4. No session binding to IP/User-Agent
// 5. Predictable session IDs if default generator used

Secure Code Example

Secure — Java / Spring Boot (Hardened Session)
@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http)
            throws Exception {
        http
            .sessionManagement(session -> session
                // SECURE: Short session timeout (15 minutes)
                .sessionCreationPolicy(
                    SessionCreationPolicy.IF_REQUIRED)
                .maximumSessions(1)
                .maxSessionsPreventsLogin(false)
                .expiredUrl("/login?expired")
            )
            // Enable session fixation protection
            .sessionManagement()
                .sessionFixation().migrateSession()
            .csrf().csrfTokenRepository(
                CookieCsrfTokenRepository.withHttpOnlyFalse());

        return http.build();
    }

    @Bean
    public ServletContextInitializer servletContextInitializer() {
        return servletContext -> {
            // SECURE: 15-minute timeout
            servletContext.setSessionTimeout(15);

            // Configure secure session cookies
            SessionCookieConfig config =
                servletContext.getSessionCookieConfig();
            config.setHttpOnly(true);   // Prevent XSS theft
            config.setSecure(true);     // HTTPS only
            config.setSameSite("Strict"); // CSRF protection
            config.setMaxAge(900);      // 15 minutes
        };
    }
}

@Component
public class SessionValidationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain) throws ServletException {

        HttpSession session = request.getSession(false);
        if (session != null) {
            // SECURE: Bind session to IP and User-Agent
            String currentIP = request.getRemoteAddr();
            String currentUA = request.getHeader("User-Agent");

            String sessionIP =
                (String) session.getAttribute("BOUND_IP");
            String sessionUA =
                (String) session.getAttribute("BOUND_UA");

            if (sessionIP == null) {
                session.setAttribute("BOUND_IP", currentIP);
                session.setAttribute("BOUND_UA", currentUA);
            } else if (!currentIP.equals(sessionIP) ||
                       !currentUA.equals(sessionUA)) {
                // Session hijacking detected
                session.invalidate();
                response.sendError(403, "Session invalid");
                return;
            }
        }

        filterChain.doFilter(request, response);
    }
}

// PROTECTIONS:
// 1. HttpOnly flag prevents JavaScript access
// 2. Secure flag ensures HTTPS-only transmission
// 3. SameSite=Strict prevents CSRF-based hijacking
// 4. Short 15-minute timeout limits exposure window
// 5. Session binding to IP/User-Agent detects theft
// 6. Session fixation protection via migrateSession()

Types of Session Hijacking

Session Token Theft

The most common form of session hijacking. Attackers steal session cookies through Cross-Site Scripting (XSS) attacks, where malicious JavaScript reads document.cookie and exfiltrates the token to an attacker-controlled server. Man-in-the-middle (MITM) attacks on unencrypted HTTP connections allow network-level interception of session cookies. Without the HttpOnly flag, cookies are accessible to JavaScript; without the Secure flag, they can be transmitted over unencrypted connections.

Session Prediction

When applications use weak random number generators or predictable patterns for session ID creation, attackers can predict valid session tokens without stealing them. Sequential session IDs like SID001, SID002, SID003 or timestamp-based tokens allow attackers to enumerate valid sessions. Insufficient entropy in session generation enables brute-force attacks. Modern applications must use cryptographically secure random number generators (CSRNG) with at least 128 bits of entropy for session tokens.

Session Sidejacking (Sniffing)

Exploits unencrypted WiFi traffic on public networks to capture session cookies in transit. Tools like Firesheep (2010) popularized this attack by making it point-and-click simple to hijack sessions on shared WiFi networks. The attacker runs a packet sniffer on the same network as the victim, capturing all HTTP traffic. Any session cookies transmitted without HTTPS encryption are immediately visible and usable. This attack was devastating before HTTPS became ubiquitous and remains a threat for applications that don't enforce HTTPS or have mixed content vulnerabilities.

Impact

Successful session hijacking gives attackers the same access level as the legitimate user, enabling a wide range of malicious activities. The severity depends on the privileges of the compromised account and the sensitivity of accessible data.

Complete account takeover

Attackers gain full access to the victim's account, including the ability to view private messages, personal information, financial data, and transaction history. They can act as the legitimate user across the entire application without needing to know the password.

Unauthorized transactions and actions

With hijacked sessions, attackers can perform actions on behalf of the user: making financial transactions, changing account settings, deleting data, sending messages, or initiating password resets to permanently lock out the legitimate user.

Privilege escalation opportunities

If the hijacked session belongs to an administrator or privileged user, attackers gain elevated access to system functions, user management, configuration settings, and sensitive business operations, potentially compromising the entire application and its data.

Persistent and undetected access

Session hijacking often goes unnoticed because the attacker's activity appears as legitimate user actions in logs. Unlike password theft, victims may not realize their account is compromised until unusual activity occurs. Attackers can maintain access for the entire session lifetime, often hours or days if sessions don't expire properly.

Prevention Checklist

Set HttpOnly, Secure, and SameSite flags on session cookies

The HttpOnly flag prevents JavaScript from accessing cookies, blocking XSS-based theft. The Secure flag ensures cookies are only transmitted over HTTPS, preventing network sniffing. SameSite (set to Strict or Lax) prevents cookies from being sent in cross-site requests, mitigating CSRF attacks. These three flags are non-negotiable for session security.

Implement short session timeouts

Configure both idle timeouts (15-30 minutes of inactivity) and absolute timeouts (maximum session lifetime regardless of activity). Short timeouts minimize the window of opportunity for attackers to exploit stolen sessions. Balance security with user experience by implementing sliding session renewal for active users.

Use cryptographically secure session ID generation

Generate session IDs using cryptographically secure random number generators (CSRNG) with at least 128 bits of entropy. Never use predictable patterns, sequential numbers, or weak algorithms. Most modern frameworks (Express.js, Spring, Django) provide secure session ID generation by default; do not implement custom session ID generators.

Bind sessions to IP address and User-Agent

Store the user's IP address and User-Agent string at session creation and validate them on every request. If they change, invalidate the session as it likely indicates hijacking. Be aware of legitimate scenarios where these might change (mobile users switching networks, VPNs) and implement appropriate tolerance or multi-factor re-authentication.

Regenerate session IDs after authentication

Implement session fixation protection by generating a new session ID after successful login. This prevents attackers from setting a known session ID before authentication and then using it after the victim logs in. Most web frameworks provide built-in session fixation protection; ensure it's enabled.

Enforce HTTPS across the entire application

Use HTTPS for all pages, not just login or sensitive transactions. Implement HTTP Strict Transport Security (HSTS) headers to force browsers to always use HTTPS. Mixed content (HTTP resources on HTTPS pages) can leak session cookies. Deploy automatic HTTPS redirects and consider tools like Let's Encrypt for free TLS certificates.

Real-World Examples

2010

Firesheep

A Firefox extension called Firesheep made session hijacking trivial on public WiFi networks. It captured unencrypted session cookies from popular sites like Facebook, Twitter, and Amazon, allowing one-click account hijacking. The tool's release forced many major websites to implement HTTPS by default, fundamentally changing web security practices.

2013

Yahoo Mail

Security researchers discovered that Yahoo Mail transmitted session cookies over unencrypted HTTP connections even after users logged in via HTTPS. This allowed attackers on shared networks to hijack email sessions simply by sniffing network traffic. The vulnerability persisted for years before Yahoo implemented full HTTPS encryption.

2014

Snapchat Snappening

A third-party Snapchat app failed to implement proper session security, allowing attackers to hijack user sessions and download over 200,000 private photos and videos. The breach occurred because the app used predictable session tokens and didn't bind sessions to device identifiers, enabling mass account compromise through session replay attacks.

2018

British Airways

The British Airways data breach, which compromised 380,000 payment transactions, involved attackers injecting malicious JavaScript that stole session cookies alongside payment data. The XSS-based session hijacking gave attackers authenticated access to customer accounts, demonstrating how session theft compounds the impact of other vulnerabilities. The breach resulted in a $230 million fine.

Ready to Test Your Knowledge?

Put what you have learned into practice. Try identifying and fixing Session Hijacking vulnerabilities in our interactive coding challenges, or explore more security guides to deepen your understanding.