← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
tenable:100681 · CWE-755 · Disclosed 2017-06-06

Apache Tomcat 8

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

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.

"Internet-reachable, yes—but this is mostly an error-page edge case, not a practical enterprise compromise path."
02 · The Attack Path

3 steps from start to impact.

STEP 01

Trigger an error dispatch with a crafted method

Using 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.
Conditions required:
  • 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
Where this breaks in practice:
  • 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
Detection/coverage: Mostly version-based detection. Nessus plugin 100681 identifies vulnerable Tomcat versions; exploit-path validation is uncommon in scanners.
STEP 02

Abuse method handling on the error page

Tomcat forwards the original method to the error page instead of treating a static error page like a 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.
Conditions required:
  • 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
Where this breaks in practice:
  • 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
Detection/coverage: Web logs may show unusual non-GET requests that end in error dispatches, but there is no strong signature without app-aware telemetry.
STEP 03

Attempt write/delete side effects on the static error page

The most concrete impact Apache calls out is replacement or removal of the custom error page when 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.
Conditions required:
  • Static error page resource
  • DefaultServlet writable configuration or equivalent unsafe custom handling
  • Backend filesystem permissions allowing the write/delete operation
Where this breaks in practice:
  • readonly=false is 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
Detection/coverage: File integrity monitoring on webapps/ and access logs for PUT/DELETE against error-page resources provide the best signal.
03 · Intelligence Metadata

The supporting signals.

Primary CVECVE-2017-5664 — Apache Tomcat Default Servlet error-page method handling bug
In-the-wild statusNo 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 availabilityNo 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.
EPSS0.11061 probability from Vulners' current CVE view. Treat as a weak signal here because the environmental prerequisites dominate real risk.
KEV statusNot KEV-listed as of the current CISA catalog/search results reviewed.
CVSS vectorCVSS: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 versionsApache states 8.5.0 to 8.5.14 are affected for the 8.5 branch.
Fixed versionsUpstream fixed in 8.5.15. Downstream package streams may instead ship backported distro patches rather than that exact upstream version string.
Exposure realityTomcat 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.
DisclosureApache 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.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.2/10)

The decisive downshift is configuration dependence: this bug needs a reachable error-dispatch path plus an unsafe error-page implementation, and the most concrete impact usually needs a writable DefaultServlet, which is not the common enterprise baseline. That sharply limits both exposed population and blast radius compared with a normal unauthenticated Tomcat web bug.

HIGH Version mapping of Tenable plugin `100681` to **CVE-2017-5664**
MEDIUM Real-world exploitability downgrade based on typical hardened Tomcat deployments
MEDIUM Assessment that the bug is not a mainstream initial-access vector

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 DefaultServlet writes 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.

05 · Compensating Control

What to do — in priority order.

  1. Keep 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.
  2. Review custom error-page mappings — Find static error pages and custom JSP/Servlet error handlers, then confirm they do not perform state-changing behavior based on forwarded methods. For LOW, do this as part of normal hardening and app review rather than an emergency change.
  3. Block unnecessary HTTP methods upstream — Use the reverse proxy, WAF, or load balancer to deny methods your apps do not need, especially TRACE and stray PUT/DELETE to public paths. For LOW, roll this in through standard policy maintenance.
  4. Monitor webroot integrity — Place file integrity monitoring on Tomcat webapp directories so unexpected changes to static resources and error pages are caught quickly. This does not replace patching, but it narrows dwell time if a misconfigured host exists.
What doesn't work
  • 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.
06 · Verification

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.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/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()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: treat this as backlog hygiene, not a fire drill. For a LOW verdict there is no noisgate mitigation SLA and noisgate remediation SLA is no SLA (treat as backlog hygiene), so you should verify DefaultServlet is not writable and fold the actual Tomcat upgrade to 8.5.15+ into routine maintenance rather than interrupt-driven patching; absent KEV or exploitation evidence, this can sit behind materially stronger initial-access flaws.

Sources

  1. Tenable plugin 100681
  2. Apache Tomcat 8 security page
  3. NVD CVE-2017-5664
  4. Vulners CVE-2017-5664
  5. CISA weekly bulletin mentioning CVE-2017-5664
  6. CISA Known Exploited Vulnerabilities Catalog
  7. Bitsight Apache Tomcat Observation Footprint
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.