Five flaws walk into a servlet container, and two of them brought a firehose aimed at your heap
Tenable plugin 240060 bundles five CVEs fixed in Apache Tomcat 9.0.106, spanning the full 9.0.0.M1–9.0.105 range (one narrows to 9.0.23+). The headline act is a pair of denial-of-service bugs in multipart upload handling: CVE-2025-48988 (parts count with no cap → heap exhaustion) and CVE-2025-48976 (Commons FileUpload header size limit too generous → same outcome). Both are unauthenticated, network-reachable, and have public PoC exploit scripts targeting Docker lab environments. Alongside them sits CVE-2025-49125, an authentication-bypass via PreResources/PostResources path confusion (CVSS 7.5, no auth, no interaction — but only fires when resources are mounted at non-root paths). CVE-2025-55668 is a session-fixation flaw gated on the non-default rewrite valve *and* a victim click. CVE-2025-49124 is a Windows-installer-only DLL side-loading issue Apache itself rates Low.
The vendor's aggregate HIGH rating is fair and needs no adjustment. The two DoS CVEs carry EPSS scores of 59.5% and 62.7% respectively — both in the 99th percentile — signaling that weaponization is either happening now or imminent. That alone anchors the bundle at HIGH. The auth bypass (CVE-2025-49125) would push toward CRITICAL *if* PreResources/PostResources at non-root were a common deployment pattern, but in practice this is a minority configuration. The session-fixation and installer bugs are low-friction additions that don't move the needle on their own.
4 steps from start to impact.
Identify internet-facing Tomcat instance
- Target runs Apache Tomcat 9.0.0.M1–9.0.105
- Target accepts HTTP/HTTPS connections from the internet or attacker's network position
- Well-configured reverse proxies strip Tomcat version banners
- WAF or load balancer may sit in front, masking the Tomcat layer
DoS via multipart upload (CVE-2025-48988 / CVE-2025-48976)
- At least one endpoint on the target accepts multipart/form-data uploads
- No request-rate or body-size limiting in front of Tomcat
- A WAF with request-body inspection or multipart-part-count limits blocks the payload
- Cloud load balancers often enforce default body-size caps that truncate the attack
- Tomcat instances behind CDN edge may never see raw multipart traffic
Auth bypass via path confusion (CVE-2025-49125)
PreResources or PostResources elements mounted at a path other than the web application root, an attacker crafts a request to an alternate path that maps to the same resource but is not covered by the <security-constraint> definitions in web.xml. This yields unauthenticated access to protected resources — potentially admin panels, API endpoints, or sensitive data. CVSS 7.5, network vector, no auth, no user interaction.- Target uses PreResources or PostResources mounted at a non-root path
- Security constraints are defined on the expected path but not the alternate path
- Attacker can reach the Tomcat HTTP connector directly
- PreResources/PostResources at non-root is a minority deployment pattern; most apps use default resource mapping
- Reverse-proxy path normalization may block the alternate path before it reaches Tomcat
- Applications using Spring Security or container-managed auth at the filter level may enforce constraints regardless of path
Session fixation via rewrite valve (CVE-2025-55668)
- Rewrite valve is explicitly enabled in the target's Tomcat configuration
- Victim clicks attacker-crafted URL
- Application does not regenerate session ID on authentication
- Rewrite valve is not enabled by default — most deployments use Apache httpd or nginx for URL rewriting instead
- Modern frameworks (Spring Security, etc.) regenerate session IDs on login, neutralizing fixation
- Email gateways and browser safe-browsing may flag or rewrite suspicious URLs
maxPartCount and maxPartHeaderSize on the Tomcat Connector — Directly mitigates CVE-2025-48988 and CVE-2025-48976 without a full upgrade. Set maxPartCount="10" and maxPartHeaderSize="512" in your <Connector> element in server.xml. These are the new defaults in 9.0.106. Deploy within 30 days per the noisgate mitigation SLA for HIGH.client_max_body_size, Apache LimitRequestBody) to cap multipart request sizes and part counts. This blocks the DoS payload before it reaches Tomcat.context.xml to eliminate the CVE-2025-49125 attack surface entirely. If needed, ensure <security-constraint> definitions cover both the expected and alternate access paths.RewriteValve from your Tomcat pipeline configuration if URL rewriting is handled upstream (nginx, Apache httpd, CDN). This eliminates CVE-2025-55668.Content-Type: multipart/form-data. This reduces the effectiveness of the DoS exploit even if Tomcat connector limits are not yet tuned.- Java Security Manager — deprecated since Java 17 and removed in Java 24. Even when available, it does not limit memory allocation from multipart parsing, so CVE-2025-48988/48976 bypass it entirely.
- Network segmentation alone — if the Tomcat instance is internet-facing (and ~100K are), network segmentation between internal zones does not help. The DoS arrives on the same port serving legitimate traffic.
- Upgrading only Commons FileUpload — CVE-2025-48988 is in Tomcat's own multipart handling code, not just Commons FileUpload. You must upgrade Tomcat itself, not just the library.
The supporting signals.
| In-the-Wild Exploitation | No confirmed active exploitation for these five CVEs. Not on CISA KEV as of 2026-09-17. However, EPSS scores for the DoS pair (CVE-2025-48988: 59.5%, CVE-2025-48976: 62.7%) are in the 99th percentile, indicating exploitation is statistically imminent. |
|---|---|
| Proof-of-Concept | Public PoCs available. Python DoS exploit script targets CVE-2025-48988/48976 against Docker labs. GitHub repos by *gregk4sec* cover CVE-2025-49125 (auth bypass) and CVE-2025-55668 (session fixation). |
| EPSS Scores | CVE-2025-48976: 0.6265 (99.2%) · CVE-2025-48988: 0.5946 (99.1%) · CVE-2025-49125: 0.0354 (88.7%) · CVE-2025-55668: 0.0083 (55.8%) · CVE-2025-49124: 0.0037 (30.9%) |
| CISA KEV Status | Not listed for any of the five CVEs as of 2026-09-17. |
| CVSS Vectors | CVE-2025-49125: CVSS:3.1 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N) · CVE-2025-48988: CVSS:4.0 8.7 · CVE-2025-55668: CVSS:3.1 6.5 · CVE-2025-49124: CVSS:3.1 8.4 (local) |
| Affected Versions | 9.0.0.M1–9.0.105 (CVE-2025-49125, 48988, 48976, 55668) · 9.0.23–9.0.105 (CVE-2025-49124, Windows installer only). Also affects Tomcat 10.1.x through 10.1.41 and 11.0.x through 11.0.7. |
| Fixed Versions | Tomcat 9.0.106, 10.1.42, 11.0.8. For CVE-2025-48976 standalone: Commons FileUpload 1.6 or 2.0.0-M4. |
| Exposure Data | ~100,000 internet-facing Apache Tomcat instances per Shodan. Tomcat is embedded in thousands of Java applications (Spring Boot, JBoss/WildFly, commercial products). |
| Disclosure Timeline | CVE-2025-48988/48976 reported to ASF 2025-05-16, public 2025-06-16. CVE-2025-55668 disclosed on oss-security 2025-08-13. Tomcat 9.0.106 released to address all five. |
| Credit | Reported by various researchers to the Apache Security Team. PoCs published by gregk4sec on GitHub. |
Sources.
Why this verdict
- EPSS signal is loud: Both DoS CVEs sit above 59% EPSS / 99th percentile. This is the strongest statistical predictor of near-term exploitation available. Public PoC scripts lower the bar further.
- Unauthenticated, network-reachable DoS: CVE-2025-48988 and CVE-2025-48976 require only the ability to POST multipart data to any upload-capable endpoint — a condition met by the vast majority of Tomcat deployments. No credentials, no user interaction, no non-default config.
- Auth bypass gated on non-default config: CVE-2025-49125 is a serious flaw (CVSS 7.5, no auth, no interaction) but only fires when PreResources/PostResources are mounted at non-root paths. This is a minority configuration pattern, applying downward pressure that prevents escalation to CRITICAL.
- Role multiplier: Tomcat is a *typical-role* component (line-of-business Java app server) in most environments. In high-value roles — e.g., Tomcat embedded in Jenkins, Atlassian products, or custom identity apps — the auth bypass could yield access to sensitive admin interfaces or CI/CD pipelines. However, the auth bypass requires the non-default PreResources config even in those roles, and the DoS CVEs cap out at availability impact (no code execution, no data exfil). The worst plausible high-value-role outcome is service disruption of a critical application tier, not fleet compromise or domain takeover. This keeps the floor at HIGH, not CRITICAL.
- Session fixation and installer flaws add marginal risk: CVE-2025-55668 requires rewrite valve (non-default) plus victim click. CVE-2025-49124 is install-time Windows-only. Neither moves the needle above HIGH.
Why not higher?
CRITICAL would require either active KEV exploitation, a chain that ends in remote code execution, or a blast radius reaching domain/fleet/supply-chain compromise. None of the five CVEs enable RCE. The auth bypass (the most impactful from a confidentiality standpoint) is gated on a non-default PreResources configuration that limits the reachable population. The DoS pair, while broadly exploitable, caps out at availability impact — it crashes the JVM but does not yield shells or lateral movement.
Why not lower?
MEDIUM would undercount the risk given two CVEs with 99th-percentile EPSS scores, public PoC exploit code, ~100K internet-facing Tomcat instances, and unauthenticated network-reachable attack vectors. The DoS pair alone can take production Java applications offline with a single crafted HTTP request. Downgrading past HIGH without evidence that the population is materially shielded (e.g., <1% exposed) is not defensible when Shodan shows 100K exposed hosts.
Crowdsourced verification payload.
Run this script on each Tomcat host (or from an auditor workstation with SSH access). Invoke as: bash check_tomcat_240060.sh /opt/tomcat (pass the Tomcat installation directory as the first argument). Requires read access to the Tomcat lib/ directory. No root required.
#!/usr/bin/env bash
# check_tomcat_240060.sh — Verify Apache Tomcat patched for Tenable plugin 240060
# Usage: bash check_tomcat_240060.sh /path/to/tomcat
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
CATALINA_HOME="${1:-}"
if [[ -z "$CATALINA_HOME" ]]; then
echo "UNKNOWN — Usage: $0 /path/to/tomcat"
exit 2
fi
# Try version.sh first
if [[ -x "$CATALINA_HOME/bin/version.sh" ]]; then
VERSION=$("$CATALINA_HOME/bin/version.sh" 2>/dev/null | grep -oP 'Server number:\s*\K[0-9]+\.[0-9]+\.[0-9]+' || true)
fi
# Fallback: parse catalina.jar MANIFEST
if [[ -z "${VERSION:-}" ]]; then
JAR=$(find "$CATALINA_HOME/lib" -name 'catalina.jar' -print -quit 2>/dev/null || true)
if [[ -n "$JAR" ]]; then
VERSION=$(unzip -p "$JAR" META-INF/MANIFEST.MF 2>/dev/null | grep -oP 'Implementation-Version:\s*\K[0-9]+\.[0-9]+\.[0-9]+' || true)
fi
fi
if [[ -z "${VERSION:-}" ]]; then
echo "UNKNOWN — Could not determine Tomcat version in $CATALINA_HOME"
exit 2
fi
echo "Detected Tomcat version: $VERSION"
# Compare version — fixed in 9.0.106
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
if [[ "$MAJOR" -ne 9 ]]; then
echo "UNKNOWN — This check targets Tomcat 9.x; detected $VERSION"
exit 2
fi
if [[ "$MINOR" -eq 0 && "$PATCH" -ge 106 ]]; then
echo "PATCHED — Tomcat $VERSION >= 9.0.106"
exit 0
else
echo "VULNERABLE — Tomcat $VERSION < 9.0.106 (affected by CVE-2025-49125, CVE-2025-48988, CVE-2025-48976, CVE-2025-55668, CVE-2025-49124)"
exit 1
fi