Executive Summary
A critical session fixation vulnerability (CVE-2026-40010) has been identified in Apache Wicket, a widely used Java web application framework. The flaw arises from the framework's failure to invoke changeSessionId() after session binding during the HTTP request lifecycle — a standard web security requirement that prevents session fixation attacks.
The vulnerability carries a CVSS score of 9.1 and affects multiple major Wicket release lines. An attacker who can observe or inject session identifiers can pre-set a session token, wait for a legitimate user to authenticate, and then use that session to access the authenticated user's account without knowing their credentials.
Applications running any affected Wicket version should be treated as at risk and updated immediately to the patched releases.
Vulnerability Overview
| Attribute | Value |
|---|---|
| CVE ID | CVE-2026-40010 |
| CVSS Score | 9.1 (Critical) |
| CWE | CWE-384 — Session Fixation |
| Type | Session Fixation / Account Hijacking |
| Attack Vector | Network |
| Privileges Required | None |
| User Interaction | Required (victim must authenticate) |
| Patch Available | Yes — upgrade to latest patched version |
Affected Versions
| Product | Affected Range | Fixed Version |
|---|---|---|
| Apache Wicket | 8.0.0 – 8.17.0 | 8.18.0+ |
| Apache Wicket | 9.0.0 | 9.0.1+ |
| Apache Wicket | 10.0.0 – 10.8.0 | 10.9.0+ |
Technical Analysis
Root Cause
The vulnerability stems from missing invocation of Servlet.changeSessionId() after session binding in Apache Wicket's HTTP request handling pipeline. According to the OWASP Session Management Cheat Sheet and the Servlet specification, a web application must regenerate the session identifier after any privilege change — most critically after a user logs in.
When changeSessionId() is not called post-authentication, the session ID established before login remains valid after login. This is the classic session fixation condition:
- An attacker obtains a valid (but unauthenticated) session ID for the target application
- The attacker delivers that session ID to the victim (via URL parameter, cookie injection, subdomain attack, etc.)
- The victim navigates to the login page using the attacker-supplied session ID and authenticates successfully
- Wicket authenticates the session without regenerating the session token
- The attacker — who already holds the original session ID — is now authenticated as the victim
Exploitation Vectors
Session fixation attacks commonly work through:
- URL-based session IDs: If the application accepts
?jsessionid=ATTACKER_VALUEin URLs, the attacker can craft a link for the victim - Cookie injection via subdomain: A misconfigured subdomain (
static.example.com) can set cookies on the parent domain, fixing the session - Network interception: On shared or insecure networks, an attacker can observe session tokens before authentication
- Application-level injection: Any reflected injection point that sets cookie values can be abused
Attack Flow
1. Attacker visits target Wicket application → receives SESSION_ID=AAA111
2. Attacker crafts a login link: https://app.example.com/login?jsessionid=AAA111
OR injects Set-Cookie: JSESSIONID=AAA111 via a side-channel
3. Victim receives attacker's link, clicks it, and authenticates
4. Wicket does NOT call changeSessionId() — session AAA111 is now authenticated
5. Attacker sends request with Cookie: JSESSIONID=AAA111
6. Application responds as if attacker is the authenticated victimImpact Assessment
| Impact Area | Description |
|---|---|
| Full Account Takeover | Attacker inherits all privileges and data of the targeted user |
| Admin Access | If an admin user is targeted, full application administrative control is obtained |
| Data Exfiltration | Access to all application data visible to the compromised session |
| Actions on Behalf of Victim | Attacker can submit forms, make API calls, and perform any action the victim is permitted |
| Persistent Access | Until the victim logs out or the session expires, the attacker retains access |
| Audit Trail Contamination | All attacker actions appear in logs under the victim's identity |
The practical severity depends on the application: a low-privilege user session in a public forum is low-risk; an administrator session in a financial or healthcare application is critical.
Immediate Remediation
Step 1: Identify Wicket Version
# Check Maven dependency tree
mvn dependency:tree | grep wicket
# Or check the JAR manifest in your deployment
find /opt /app /srv -name "wicket-core-*.jar" 2>/dev/null
# Check version in pom.xml or build.gradle
grep -r "wicket" pom.xml build.gradleStep 2: Upgrade Apache Wicket
Maven (pom.xml):
<!-- Replace with the appropriate patched version for your stream -->
<!-- Wicket 10.x users -->
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-core</artifactId>
<version>10.9.0</version>
</dependency>
<!-- Wicket 8.x users -->
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-core</artifactId>
<version>8.18.0</version>
</dependency>Gradle (build.gradle):
dependencies {
implementation 'org.apache.wicket:wicket-core:10.9.0'
}Step 3: Verify Fix Is Applied
After upgrading, confirm that session ID rotation occurs on login by monitoring session tokens:
# Using curl, check that the session ID changes after authentication
SESSION_BEFORE=$(curl -c /tmp/cookies_before.txt -s -o /dev/null -D - \
https://app.example.com/login | grep -i set-cookie)
# After POST with credentials
SESSION_AFTER=$(curl -b /tmp/cookies_before.txt -c /tmp/cookies_after.txt \
-s -o /dev/null -D - -X POST https://app.example.com/login \
-d "username=test&password=test123" | grep -i set-cookie)
echo "Before: $SESSION_BEFORE"
echo "After: $SESSION_AFTER"
# The session token value MUST differ after successful authenticationStep 4: Application-Level Mitigations (If Immediate Upgrade Is Not Possible)
// Override sign-in logic to manually rotate session ID
// (Stopgap only — upgrade is required)
@Override
public void onSignIn() {
super.onSignIn();
// Manually rotate the session after authentication
getSession().replaceSession();
}Detection Indicators
| Indicator | Description |
|---|---|
| Same session ID before and after login events | Primary indicator of session fixation condition |
| Duplicate authenticated sessions from different IPs | Two clients using the same session token |
| Login events from IP addresses not in geographic norm | Successful authentication from unexpected locations |
| Session IDs received via URL parameter on login page | Potential fixation delivery mechanism |
Post-Remediation Checklist
- Upgrade Apache Wicket to a patched version for your release stream
- Rebuild and redeploy the application — the fix must be in the running binary
- Invalidate all active sessions to clear any existing fixed sessions
- Audit authentication logs for signs of session reuse across different IPs
- Disable URL-based session parameters (
jsessionidin URLs) if not required - Configure session expiration to limit the window of exposure for any stale sessions
- Enable SameSite=Strict and HttpOnly cookie flags to reduce session theft vectors
- Review all authentication and session management code for similar issues