This is a tenant peeking through the landlord's mailroom window, not a burglar kicking in the front door
The finding maps to CVE-2015-5174. In Apache Tomcat 7.0.0 through 7.0.64, a path validation bug lets code running inside a webapp call ServletContext.getResource() / getResourceAsStream() / getResourcePaths() with "/.." and get a directory listing of the parent deployment directory. Apache is explicit that this only matters when you are running untrusted web applications under a Java SecurityManager; the usual exposure is disclosure of $CATALINA_BASE/webapps, not arbitrary file read or code execution.
The scanner's MEDIUM label overstates real enterprise risk. Apache itself rated it Low, and that is the right instinct: the attacker typically needs to have already crossed a much bigger line first by deploying or controlling an app on the target Tomcat instance. In most enterprise fleets, Tomcat is not used as hostile multi-tenant shared hosting, and Java SecurityManager-based sandboxing is uncommon enough that the reachable population is narrow before the bug even starts to matter.
4 steps from start to impact.
Gain code execution inside a deployed webapp
- Authenticated remote access to deploy or modify an application, or prior compromise of an app on the Tomcat host
- Shared Tomcat instance hosting more than one relevant application
- Target is Apache Tomcat 7.x in the vulnerable range
- Requiring app deployment/control is already a substantial breach stage
- Many enterprises run one app per instance/container, which kills the cross-app value
- Tomcat 7 is legacy and the exact multi-tenant pattern is not common in modern estates
webapps/ should catch the prerequisite more reliably than vulnerability scanning catches the exploit.Rely on SecurityManager sandboxing being enabled
"/..".- Java SecurityManager is enabled for Tomcat
- The deployment model assumes the SecurityManager is providing isolation between applications
- SecurityManager-based isolation is niche in enterprise Tomcat deployments
- If you are not using untrusted multi-tenant apps, the boundary being bypassed often has no practical attacker value
Trigger the limited traversal primitive
ServletContext resource methods with a path of "/..". Apache notes this is limited: "/../" was already rejected, and the practical result is typically a listing of the parent deployment directory, not broad arbitrary traversal.- Application code can invoke the affected
ServletContextAPIs - Tomcat version is 7.0.0 through 7.0.64
- The primitive is narrow and leaks metadata, not immediate full file contents
- Exploded deployment directories make it more useful; packed or isolated layouts reduce impact
Use the directory listing as second-stage recon
$CATALINA_BASE/webapps. That can support lateral movement or targeted follow-on abuse, but this CVE alone does not grant arbitrary file read, integrity loss, or code execution.- There are other interesting applications or artifacts in the parent deployment directory
- The attacker has a follow-on weakness to exploit using the newly learned paths
- Requires a separate second-stage bug or secret exposure to become materially worse
- Single-app instances or per-app containers collapse the blast radius
7.0.65 string, because vendor backports may already contain the fix. For LOW, do this during normal vulnerability review and backlog hygiene.webapps/ for drift — File integrity monitoring and EDR on deployed WARs/JSPs and exploded app directories catch the real dangerous event here: unauthorized app deployment or modification. Again, LOW means no formal mitigation deadline, but the control is high-value broadly.- A WAF does not meaningfully solve this because the vulnerable action is typically performed by malicious application code already running inside Tomcat, not by a distinctive external request pattern.
- Generic network ACLs only help if they prevent the earlier deployment foothold; they do not stop one already-running webapp from asking Tomcat for the parent directory listing.
- Hardening TLS/ciphers is irrelevant to this flaw; the weakness is path validation inside Tomcat's application resource handling.
The supporting signals.
| In-the-wild status | I found no CISA KEV listing and no credible public reporting of active campaigns abusing this specific CVE as of 2025-06-04. |
|---|---|
| PoC availability | There is a public Packet Storm reference linked from NVD/Tenable, but this is a niche sandbox-bypass/info-leak primitive, not a broadly weaponized internet exploit chain. |
| EPSS | 0.30% (~53rd percentile) in the CVE Details snapshot, which is low and consistent with limited attacker demand. |
| KEV status | Not listed in the CISA Known Exploited Vulnerabilities Catalog as checked on 2025-06-04. |
| CVSS view | CVSS 3.0 4.3 / CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N. Translation: network reachable in theory, but it still needs low privileges / authenticated control and only yields low confidentiality impact. |
| Affected versions | Upstream Apache says Tomcat 7.0.0 to 7.0.64 are affected by CVE-2015-5174. |
| Fixed version | Upstream fix is Apache Tomcat 7.0.65. Distro builds may be fixed via backports without reporting 7.0.65 literally, so package provenance matters. |
| Backport examples | Debian tracker shows wheezy tomcat6 fixed in 6.0.45+dfsg-1~deb7u1; Ubuntu addressed related Tomcat packages in USN-3024-1. Do not treat raw upstream version strings as authoritative on packaged systems. |
| Exposure/scanning reality | CVE Details surfaces SecurityScorecard data showing broad internet association, but that is a coarse version/exposure signal and does not prove the rare SecurityManager + untrusted-app prerequisite is present. |
| Disclosure / reporter | Apache says the issue was identified by the Tomcat Security Team on 2015-08-12 and made public on 2016-02-22. |
Sources.
Why this verdict
- Major friction: attacker needs app control first — this is not a clean unauthenticated edge exploit; it assumes authenticated deployment rights or an already-compromised app.
- Population narrows again with SecurityManager — Apache explicitly scopes impact to deployments running untrusted webapps under a SecurityManager, a pattern that is uncommon in modern enterprise application hosting.
- Impact is bounded — the primitive usually exposes a parent directory listing like
$CATALINA_BASE/webapps, which is useful recon but not arbitrary file read or code execution by itself. - Vendor baseline is inflated for operations — a scanner's generic MEDIUM is understandable from raw CVSS mechanics, but it ignores that the path to exploitation starts after a bigger compromise milestone.
Why not higher?
It is not higher because this is not an internet-edge RCE, not a credential bypass, and not even a general file-read primitive. The chain depends on rare deployment assumptions: shared Tomcat hosting, untrusted apps, SecurityManager isolation, and an attacker who already has application-level foothold.
Why not lower?
It is not IGNORE because the bug does break an intended sandbox boundary, and in the specific shared-hosting model it can leak deployment structure for neighboring apps. If you actually run adversarial or separately managed tenants on one Tomcat instance, that is a real cross-app isolation failure.
Crowdsourced verification payload.
Run this on the target Tomcat host as a user with read access to the Tomcat install. Invoke it with the Tomcat base path, for example: bash check_cve_2015_5174.sh /opt/tomcat. It needs no root privileges, but distro-packaged/backported builds may return UNKNOWN by design.
#!/usr/bin/env bash
# check_cve_2015_5174.sh
# Detects likely exposure to CVE-2015-5174 for Apache Tomcat 7.x
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
TARGET="${1:-${CATALINA_HOME:-}}"
if [[ -z "$TARGET" ]]; then
echo "UNKNOWN - usage: $0 /path/to/tomcat"
exit 2
fi
if [[ ! -d "$TARGET" ]]; then
echo "UNKNOWN - target path does not exist: $TARGET"
exit 2
fi
get_version() {
local base="$1"
local out=""
if [[ -x "$base/bin/version.sh" ]]; then
out=$("$base/bin/version.sh" 2>/dev/null | awk -F': ' '/Server number/ {print $2; exit}')
if [[ -n "$out" ]]; then
echo "$out"
return 0
fi
fi
local jar=""
for jar in "$base/lib/catalina.jar" "$base/server/lib/catalina.jar"; do
if [[ -f "$jar" ]]; then
out=$(unzip -p "$jar" META-INF/MANIFEST.MF 2>/dev/null | awk -F': ' '/Implementation-Version/ {print $2; exit}')
if [[ -n "$out" ]]; then
echo "$out"
return 0
fi
fi
done
return 1
}
ver=$(get_version "$TARGET") || {
echo "UNKNOWN - could not determine Tomcat version from $TARGET"
exit 2
}
ver=$(echo "$ver" | tr -d '\r' | xargs)
# Distro/backport hinting: raw upstream comparison is unsafe when suffixes are present.
if [[ "$ver" =~ [+-] || "$ver" =~ (deb|el|ubuntu|redhat|amzn|suse|dfsg) ]]; then
echo "UNKNOWN - version '$ver' looks distro-packaged/backported; verify package advisory instead"
exit 2
fi
if [[ ! "$ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "UNKNOWN - unrecognized version format: $ver"
exit 2
fi
IFS='.' read -r major minor patch <<< "$ver"
# This check is scoped to Tomcat 7.x because the finding presented is Tenable plugin 121117.
if [[ "$major" != "7" ]]; then
echo "UNKNOWN - detected Tomcat $ver; this script is scoped to Tomcat 7.x"
exit 2
fi
if (( minor != 0 )); then
echo "UNKNOWN - unexpected Tomcat 7 minor version format: $ver"
exit 2
fi
if (( patch < 65 )); then
echo "VULNERABLE - Tomcat version $ver is earlier than 7.0.65"
exit 1
else
echo "PATCHED - Tomcat version $ver is 7.0.65 or later"
exit 0
fi