This is a side door into the janitor closet, not the vault
The Tenable plugin maps to CVE-2017-5664 in Apache Tomcat's Default Servlet. Affected versions are Tomcat 8.5.0 through 8.5.14, fixed in 8.5.15. When an error occurs and Tomcat forwards the original request to a configured error page, static error pages were incorrectly handled with the original HTTP method instead of being treated like GET; that can produce unexpected behavior, and in the worst case can let an attacker overwrite or remove a static custom error page if the DefaultServlet is configured to allow writes.
On paper this scores high for integrity because it is network-reachable and unauthenticated. In real enterprise deployments, that overstates the risk. The exploit chain depends on a very specific application pattern: a request that triggers an error dispatch, a static custom error page, and usually a non-default writable DefaultServlet or similarly unsafe custom error-page logic. Most Tomcat estates do not intentionally expose writable static resources through DefaultServlet, so the vendor-style severity is too generous for Monday-morning patch triage.
3 steps from start to impact.
Trigger an error dispatch with a crafted method
curl or Burp, the attacker sends a non-GET request such as PUT, DELETE, OPTIONS, or TRACE to an application path that predictably throws an error mapped to a custom error page. The whole bug only comes alive if the request is forwarded into Tomcat's error-page mechanism.- Unauthenticated network reachability to the Tomcat application
- A request path that reliably triggers an error response with a configured error page
- The target app or container must actually use custom error-page mappings
- Many apps return framework-generated errors instead of static servlet-container error pages
- Reverse proxies and API gateways often normalize or block unusual methods before Tomcat sees them
- Finding a deterministic error path takes app-specific probing
100681 identifies vulnerable Tomcat versions; exploit-path validation is uncommon in scanners.Abuse method handling on the error page
GET. That means method restrictions expected by the Java Servlet Specification are bypassed for that error-page path, creating odd edge-case behavior around static or poorly coded custom error pages.- The configured error page must be static, or a custom JSP/Servlet that mishandles the forwarded method
- The target must depend on method-based protections for the error-page resource
- This is not a generic request smuggling or auth bypass primitive across the app
- JSP/servlet error pages can be coded defensively and many are not state-changing anyway
- Impact is usually confined to the error-page path, not arbitrary application routes
GET requests that end in error dispatches, but there is no strong signature without app-aware telemetry.Attempt write/delete side effects on the static error page
DefaultServlet is configured to permit writes (readonly=false). An attacker can then tamper with the error page content or break error handling for that mapped condition.- Static error page resource
DefaultServletwritable configuration or equivalent unsafe custom handling- Backend filesystem permissions allowing the write/delete operation
readonly=falseis not the normal hardened Tomcat posture- Filesystem permissions and deployment packaging often make static web resources effectively immutable at runtime
- This still does not give straightforward remote code execution by itself
webapps/ and access logs for PUT/DELETE against error-page resources provide the best signal.DefaultServlet read-only — Verify readonly=true for the Default Servlet so the most concrete overwrite/delete path is shut down. For a LOW verdict there is no SLA; treat as backlog hygiene, but this is the single best hardening check.TRACE and stray PUT/DELETE to public paths. For LOW, roll this in through standard policy maintenance.- A generic WAF-only story is weak here because the trigger can be an application-specific error path and the bad behavior occurs in servlet error dispatch logic.
- Relying on method-based controls on the error page itself does not help; the bug is that the forwarded method handling is wrong for static error pages.
- MFA is irrelevant because the attack path is unauthenticated and hits the HTTP service directly.
The supporting signals.
| Primary CVE | CVE-2017-5664 — Apache Tomcat Default Servlet error-page method handling bug |
|---|---|
| In-the-wild status | No authoritative evidence located for active exploitation. It does not appear in CISA KEV based on CISA search results for the CVE and catalog pages. |
| Proof-of-concept availability | No widely cited public exploit repo stood out in primary-source search. This looks more like a low-interest logic flaw than a mainstream offensive primitive. |
| EPSS | 0.11061 probability from Vulners' current CVE view. Treat as a weak signal here because the environmental prerequisites dominate real risk. |
| KEV status | Not KEV-listed as of the current CISA catalog/search results reviewed. |
| CVSS vector | CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N (7.5 HIGH). That assumes the integrity impact is broadly reachable; in practice it is heavily gated by deployment choices. |
| Affected versions | Apache states 8.5.0 to 8.5.14 are affected for the 8.5 branch. |
| Fixed versions | Upstream fixed in 8.5.15. Downstream package streams may instead ship backported distro patches rather than that exact upstream version string. |
| Exposure reality | Tomcat is broadly internet-exposed as a product family, but open-source search did not yield authoritative public counts for this exact vulnerable version/configuration. Bitsight shows a large global Tomcat footprint, which matters for prevalence, not for exploitability of this specific edge case. |
| Disclosure | Apache made the issue public on 2017-06-06; the 8.5.15 fix shipped on 2017-05-10. Reported by Aniket Nandkishor Kulkarni of Tata Consultancy Services, with broader impact identified by the Tomcat Security Team on 2017-04-24. |
Sources.
Why this verdict
- Requires an error-page edge case: the attacker does not get a generic app-wide primitive; they need a request that lands in Tomcat's error-page forwarding path.
- Depends on unsafe implementation choices: practical damage usually requires a static error page plus
DefaultServletwrites enabled or a custom JSP/Servlet error page that mishandles methods. - Blast radius is narrow: even when reachable, the impact is mostly limited to tampering with error-page handling or bypassing method assumptions on that path, not arbitrary code execution or broad auth bypass.
Why not higher?
This is not a clean RCE, deserialization, traversal, or generic auth bypass. The exploit path compounds friction at every step: specific method, specific error route, specific error-page type, and often a non-default writable servlet setting. That is classic downward pressure on severity.
Why not lower?
It is still unauthenticated and remote, and the integrity impact is not imaginary. If you inherited a sloppy Tomcat deployment with writable static resources or brittle custom error-page logic, an external attacker can abuse it without credentials, so it is not something to ignore outright.
Crowdsourced verification payload.
Run this on the target Tomcat host or from a config-management runner with filesystem access to the Tomcat install path. Invoke it as python3 check_tomcat_100681.py /opt/tomcat or point directly at catalina.jar; no admin rights are required unless directory permissions block read access.
#!/usr/bin/env python3
"""
check_tomcat_100681.py
Detects whether a Tomcat installation matches the affected range for CVE-2017-5664
as surfaced by Tenable plugin 100681 (Apache Tomcat 8.5.0 < 8.5.15).
Usage:
python3 check_tomcat_100681.py /path/to/tomcat
python3 check_tomcat_100681.py /path/to/tomcat/lib/catalina.jar
Exit codes:
0 = PATCHED
1 = VULNERABLE
2 = UNKNOWN / usage error
"""
import os
import re
import sys
import zipfile
def parse_version(s):
m = re.search(r'(\d+)\.(\d+)\.(\d+)', s or '')
if not m:
return None
return tuple(int(x) for x in m.groups())
def read_manifest_version(jar_path):
try:
with zipfile.ZipFile(jar_path, 'r') as zf:
for name in ('META-INF/MANIFEST.MF', 'meta-inf/manifest.mf'):
if name in zf.namelist():
data = zf.read(name).decode('utf-8', errors='ignore')
for line in data.splitlines():
if line.lower().startswith('implementation-version:'):
return line.split(':', 1)[1].strip()
if line.lower().startswith('specification-version:'):
candidate = line.split(':', 1)[1].strip()
if candidate:
return candidate
except Exception:
return None
return None
def locate_jar(path_arg):
if os.path.isfile(path_arg) and path_arg.endswith('.jar'):
return path_arg
if os.path.isdir(path_arg):
candidate = os.path.join(path_arg, 'lib', 'catalina.jar')
if os.path.isfile(candidate):
return candidate
return None
def main():
if len(sys.argv) != 2:
print('UNKNOWN - usage: python3 check_tomcat_100681.py /path/to/tomcat_or_catalina.jar')
sys.exit(2)
target = sys.argv[1]
jar = locate_jar(target)
if not jar:
print('UNKNOWN - could not locate catalina.jar from input: {}'.format(target))
sys.exit(2)
version_str = read_manifest_version(jar)
version = parse_version(version_str)
if not version:
print('UNKNOWN - could not determine Tomcat version from {}'.format(jar))
sys.exit(2)
affected_min = (8, 5, 0)
fixed = (8, 5, 15)
if affected_min <= version < fixed:
print('VULNERABLE - Apache Tomcat {} is in affected range 8.5.0-8.5.14 for CVE-2017-5664 / Tenable 100681'.format(version_str))
sys.exit(1)
elif version >= fixed:
print('PATCHED - Apache Tomcat {} is not in affected range for Tenable 100681'.format(version_str))
sys.exit(0)
else:
print('PATCHED - Apache Tomcat {} is below 8.5.x affected branch for Tenable 100681'.format(version_str))
sys.exit(0)
if __name__ == '__main__':
main()