OWASP Web Top 10 — A07

Session Fixation

Session Fixation is a web application security vulnerability that allows attackers to hijack user sessions by forcing victims to authenticate using an attacker-controlled session identifier. This attack exploits the application's failure to regenerate session IDs after successful authentication.

What Is Session Fixation?

Session Fixation is an attack where the attacker obtains or sets a valid session identifier before the victim authenticates, then tricks the victim into using that specific session ID to log in. Once the victim authenticates with the fixed session ID, the attacker can use the same session identifier to gain unauthorized access to the victim's account, bypassing the need to steal credentials or exploit authentication mechanisms.

The vulnerability exists when web applications fail to regenerate session identifiers after a privilege level change, particularly during the authentication process. When a user logs in, the application should invalidate the old session and create a new one with a fresh session ID. If the application reuses the pre-authentication session ID, an attacker who knows that ID can hijack the authenticated session immediately after the victim logs in.

Session Fixation is categorized under A07:2021 – Identification and Authentication Failures in the OWASP Top 10. While less prevalent than some other session-based attacks, it remains a critical vulnerability because it requires minimal technical sophistication to exploit. The attack is particularly dangerous because it can completely bypass authentication without requiring the attacker to know the victim's username or password.

How It Works

1
Attacker obtains a valid session ID

The attacker visits the target web application and obtains a valid session identifier. This could be a cookie, URL parameter, or hidden form field. The attacker doesn't need to authenticate; they simply need a session ID that the application recognizes as valid.

2
Attacker fixes the session ID on the victim's browser

The attacker tricks the victim into using this specific session ID. This can be done through various methods: sending a crafted link with the session ID in the URL (e.g., https://bank.com/login?JSESSIONID=abc123), using XSS to set the session cookie, or exploiting subdomain vulnerabilities to inject cookies.

3
Victim authenticates with the fixed session ID

The unsuspecting victim clicks the malicious link or visits the page where the session ID has been set, then proceeds to log in normally using their legitimate credentials. The application authenticates the user but fails to regenerate the session identifier.

4
Application reuses the pre-authentication session ID

After successful authentication, the vulnerable application continues using the same session ID that existed before login. The session is now authenticated and associated with the victim's account, but it's still using the session identifier that the attacker knows and can control.

5
Attacker hijacks the authenticated session

The attacker uses the known session ID to make authenticated requests to the application. Since the session is now authenticated as the victim, the attacker gains full access to the victim's account without ever knowing their password. The attacker can view sensitive data, perform transactions, or modify account settings.

Vulnerable Code Example

Vulnerable — Java / Spring Boot
@RestController
public class AuthController {

    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public ResponseEntity<?> login(
        @RequestBody LoginRequest req,
        HttpSession session
    ) {
        User user = userService.authenticate(
            req.getUsername(),
            req.getPassword()
        );

        if (user != null) {
            // VULNERABLE: Session ID is NOT regenerated after login
            // The pre-authentication session ID remains valid
            session.setAttribute("userId", user.getId());
            session.setAttribute("username", user.getUsername());
            session.setAttribute("authenticated", true);

            return ResponseEntity.ok(Map.of(
                "message", "Login successful",
                "user", user.getUsername()
            ));
        }

        return ResponseEntity.status(401)
            .body("Invalid credentials");
    }
}

// Attack scenario:
// 1. Attacker gets session ID: JSESSIONID=attacker-known-id
// 2. Attacker sends victim: https://app.com/login?JSESSIONID=attacker-known-id
// 3. Victim logs in with their credentials
// 4. Session "attacker-known-id" is now authenticated as victim
// 5. Attacker uses JSESSIONID=attacker-known-id to access victim's account

Secure Code Example

Secure — Java / Spring Boot (Session Regeneration)
@RestController
public class AuthController {

    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public ResponseEntity<?> login(
        @RequestBody LoginRequest req,
        HttpServletRequest request
    ) {
        User user = userService.authenticate(
            req.getUsername(),
            req.getPassword()
        );

        if (user != null) {
            // SECURE: Get the old session and invalidate it
            HttpSession oldSession = request.getSession(false);
            if (oldSession != null) {
                oldSession.invalidate();
            }

            // Create a new session with a new session ID
            HttpSession newSession = request.getSession(true);
            newSession.setAttribute("userId", user.getId());
            newSession.setAttribute("username", user.getUsername());
            newSession.setAttribute("authenticated", true);

            // Alternative: Use changeSessionId() in Servlet 3.1+
            // request.changeSessionId();

            return ResponseEntity.ok(Map.of(
                "message", "Login successful",
                "user", user.getUsername()
            ));
        }

        return ResponseEntity.status(401)
            .body("Invalid credentials");
    }
}

// Spring Security provides session fixation protection by default:
// - sessionFixation().newSession() creates a new session
// - sessionFixation().migrateSession() migrates attributes to new session
// - sessionFixation().changeSessionId() changes ID (Servlet 3.1+)

Types of Session Fixation

Cookie-Based Session Fixation

The attacker sets the session cookie in the victim's browser through various methods. This can be accomplished via Cross-Site Scripting (XSS) vulnerabilities that allow the attacker to execute JavaScript and set cookies, HTTP Response Splitting (CRLF injection) to inject Set-Cookie headers, or by exploiting subdomain cookie scope where a cookie set on a subdomain (e.g., attacker.example.com) is sent to the main domain (example.com) if not properly scoped.

URL-Based Session Fixation

The session identifier is passed through URL parameters rather than cookies, such as https://app.com/login?JSESSIONID=abc123. The attacker sends the victim a crafted link containing the known session ID. When the application accepts session IDs from URL parameters and doesn't regenerate them after login, the victim authenticates using the attacker's session ID. This type is easier to exploit but also easier to detect and prevent by avoiding URL-based session management entirely.

Cross-Subdomain Session Fixation

Exploits cookie scope rules to set session cookies from attacker-controlled subdomains. If an attacker controls evil.example.com and the session cookie doesn't specify a restrictive domain attribute, the attacker can set a cookie like Set-Cookie: SESSIONID=xyz; Domain=.example.com. This cookie will be sent to all subdomains and the main domain. When the victim logs in at www.example.com, they use the attacker's session ID. Prevention requires proper Domain and Path cookie attributes.

Impact

A successful Session Fixation attack allows an attacker to completely bypass authentication and gain full access to a victim's account. The consequences can be severe and long-lasting.

Complete account takeover

The attacker gains full access to the victim's authenticated session without knowing their username or password. This allows the attacker to perform any action the victim is authorized to perform, including viewing sensitive data, modifying account settings, making transactions, or accessing private communications.

Persistent unauthorized access

Unlike some other session attacks, Session Fixation can provide long-term access to the victim's account as long as the session remains valid. The attacker can continue using the hijacked session for the entire session lifetime, which could be hours or days depending on the application's session timeout configuration.

Financial fraud and data theft

In financial applications, attackers can initiate unauthorized transactions, transfer funds, or steal sensitive financial information. In e-commerce applications, they can place orders, change shipping addresses, or access stored payment methods. In healthcare or government applications, they can access highly sensitive personal information.

Difficult detection and attribution

Session Fixation attacks are difficult to detect because the attacker's actions appear to come from the victim's legitimate session. Audit logs show the victim's authenticated session performing actions, making it hard to distinguish between legitimate user activity and attacker activity. This can complicate incident response and forensic investigations.

Prevention Checklist

Regenerate session IDs after authentication

Always invalidate the old session and create a new one with a fresh session identifier after successful login. In Java/Servlet, use request.changeSessionId() or invalidate the old session and create a new one. In Spring Security, session fixation protection is enabled by default. In PHP, use session_regenerate_id(true). This is the primary defense against Session Fixation.

Do not accept session IDs from URL parameters

Never accept session identifiers through URL parameters or GET requests. Session IDs should only be transmitted through secure, HTTP-only cookies. Disable URL rewriting for session IDs in your application server configuration. In Tomcat/Spring Boot, ensure URL encoding is disabled to prevent JSESSIONID from appearing in URLs.

Use secure cookie attributes

Set session cookies with Secure, HttpOnly, and SameSite attributes. The Secure flag ensures cookies are only sent over HTTPS. HttpOnly prevents JavaScript access, mitigating XSS-based cookie injection. SameSite=Strict or SameSite=Lax prevents cross-site cookie transmission. Additionally, set restrictive Domain and Path attributes to limit cookie scope.

Implement session timeout and absolute timeout

Configure appropriate session timeout values to limit the window of opportunity for attackers. Use both idle timeout (invalidate sessions after inactivity) and absolute timeout (invalidate sessions after a maximum lifetime regardless of activity). This limits the damage from a successful Session Fixation attack by ensuring hijacked sessions eventually expire.

Validate session metadata

Bind sessions to additional metadata such as User-Agent, IP address, or client fingerprints. While these can change legitimately, sudden changes may indicate session hijacking. Implement anomaly detection to flag suspicious changes in session context. Be cautious with IP validation as legitimate users may have changing IPs (mobile networks, VPNs), but major discrepancies should trigger re-authentication.

Prevent XSS and subdomain vulnerabilities

Since Session Fixation often relies on XSS or subdomain cookie injection, implement comprehensive XSS prevention through input validation, output encoding, and Content Security Policy (CSP). Properly configure cookie domain attributes to prevent subdomain cookie injection. Ensure all subdomains are under your control and properly secured, or use host-only cookies by omitting the Domain attribute.

Real-World Examples

2012

PayPal Session Fixation

Security researchers discovered a Session Fixation vulnerability in PayPal's authentication flow. The vulnerability allowed attackers to set session identifiers before authentication that remained valid after login, potentially enabling account takeover. PayPal responded by implementing proper session regeneration and additional security measures to prevent session fixation attacks across their platform.

2013

WordPress Session Fixation

A Session Fixation vulnerability was discovered in WordPress's authentication mechanism that affected versions prior to 3.5.1. The vulnerability allowed attackers to hijack user sessions by fixing session cookies before authentication. WordPress released a security update that implemented proper session regeneration during login to prevent the attack vector, affecting millions of WordPress installations worldwide.

2014

Joomla CMS Session Fixation

The popular Joomla content management system was found vulnerable to Session Fixation attacks due to improper session handling during the authentication process. Attackers could craft malicious URLs containing fixed session identifiers and trick administrators into logging in, potentially granting attackers full administrative access to Joomla websites. The vulnerability was patched in subsequent releases with proper session regeneration.

2016

Apache Tomcat Session Management

Several web applications running on Apache Tomcat were found vulnerable to Session Fixation due to improper session configuration and URL-based session tracking. Applications that accepted JSESSIONID from URL parameters and didn't regenerate sessions after login were exploitable. This led to widespread security advisories and best practice recommendations for Tomcat-based applications to disable URL session tracking and implement proper session lifecycle management.

Ready to Test Your Knowledge?

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