← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
tenable:162498 · CWE-79 · Disclosed 2022-06-23

Apache Tomcat 9

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

This is a sharp edge on the showroom model, not a flaw in the engine

Tenable plugin 162498 maps to CVE-2022-34305, a reflected XSS in Tomcat's examples web application, specifically the Form authentication example. The affected Tomcat line for this finding is 9.0.30 through 9.0.64, fixed in 9.0.65; other affected branches were 8.5.50-8.5.81, 10.0.0-M1-10.0.22, and 10.1.0-M1-10.1.0-M16.

The vendor's MEDIUM label is technically fair in a vacuum, but operationally inflated for enterprise patch triage. The bug is only reachable if the examples webapp is actually deployed and reachable, and exploitation still requires user interaction in a browser; that's a long way from the scanner's broad version-only match.

"This is a sample-app XSS, not a server takeover; most real Tomcat estates should downgrade it."
02 · The Attack Path

3 steps from start to impact.

STEP 01

Find a Tomcat host with the examples app still deployed

An attacker first identifies a Tomcat instance in the affected version range and then checks whether /examples/ is exposed. The practical weapon here is simple HTTP probing or search-engine-style reconnaissance; the vulnerable code is not in core request handling but in the sample Form authentication example.
Conditions required:
  • Unauthenticated network reachability to the Tomcat HTTP(S) listener
  • Tomcat version 9.0.30-9.0.64
  • The examples web application is installed and accessible
Where this breaks in practice:
  • Many production estates remove sample apps entirely
  • Reverse proxies often hide Tomcat directly and block /examples/
  • Version-only scanner findings do not prove the vulnerable webapp exists
Detection/coverage: Banner/version scanners like Nessus catch the version range well, but they over-report risk because they usually do not verify that /examples/jsp/security/protected/ is reachable.
STEP 02

Deliver a crafted XSS link

The attacker crafts a URL that injects script into the vulnerable Form authentication example and gets a victim to browse to it. Public detection content and PoC references exist, including a Nuclei template and GitHub PoC references, but exploitation is still classic reflected-XSS delivery rather than one-shot server compromise.
Conditions required:
  • A user must browse to the crafted URL
  • The request must hit the vulnerable example endpoint
  • Browser-side script execution must not be blocked by existing controls
Where this breaks in practice:
  • Requires social engineering or another delivery path
  • Modern email/web filtering may block obviously malicious URLs
  • If the examples app is not internet-exposed, the attacker needs internal reach or a victim already on-network/VPN
Detection/coverage: WAFs and secure web gateways may catch obvious XSS payloads; web logs can show probes to /examples/ and suspicious parameters.
STEP 03

Run script in the victim's browser under Tomcat origin

If the victim loads the link, the payload executes in the browser with the origin of the sample application. The likely payoff is session theft, forced actions, or pivoting into same-origin admin functions if the environment carelessly co-hosts sensitive interfaces on that origin.
Conditions required:
  • Successful browser execution
  • A victim with a meaningful session or access level
  • Same-origin access to anything worth stealing or invoking
Where this breaks in practice:
  • Impact is bounded to browser/session context, not server-side code execution
  • No direct JVM, OS, or filesystem compromise from this CVE alone
  • If no admin workflows share the origin, blast radius is modest
Detection/coverage: Browser-side compromise is hard to see directly; look for odd requests initiated by authenticated users after visiting /examples/.
03 · Intelligence Metadata

The supporting signals.

Primary CVECVE-2022-34305 — Tomcat examples webapp reflected XSS (CWE-79)
In-the-wild statusNo authoritative evidence found of broad active exploitation; not present in the public CISA KEV catalog in reviewed sources
Proof-of-concept availabilityPublic exploit references exist, including a GitHub PoC (zeroc00I/CVE-2022-34305) and a Nuclei check surfaced via Vulners/Wiz
EPSSTenable shows EPSS 0.16853 (~16.9%), which is elevated for a bug this operationally narrow; treat as threat interest, not business impact
KEV statusNot KEV-listed in reviewed CISA catalog sources; no KEV added date because none was found
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N — the big limiter is UI:R and the impact stays in the browser/session plane
Affected versionsTomcat 9.0.30-9.0.64 for this plugin; broader CVE scope also includes 8.5.50-8.5.81, 10.0.0-M1-10.0.22, 10.1.0-M1-10.1.0-M16
Fixed versionsUpstream fixed in 9.0.65; Debian tracks fix at tomcat9 9.0.65-1 and later distro backports (e.g. bullseye security currently fixed in newer backported package)
Exposure realityInternet-facing Tomcat is common, but this flaw only matters when the examples app is deployed; Apache's own security guidance says the examples webapp should always be removed from security-sensitive installs
Disclosure / reporterPublicly disclosed 2022-06-23; Apache says it was reported to the Tomcat Security Team on 2022-06-22 and does not name an external researcher in the advisory material reviewed
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (2.9/10)

The decisive downgrade factor is that exploitation depends on the examples sample webapp being deployed and reachable; a version-only Nessus hit does not prove that prerequisite. Even then, the attacker still needs user interaction, so this is not a wormable or direct server-side compromise class of issue.

HIGH CVE identification and fixed version mapping
HIGH Attack-path friction: examples app prerequisite and user interaction requirement
MEDIUM Current exploit prevalence beyond public PoC references

Why this verdict

  • Downward pressure: sample app required — the vulnerable code lives in Tomcat's examples web application, not in the core servlet container, so estates that remove sample apps are not actually exposed even if the version matches.
  • Downward pressure: user interaction required — the CVSS vector includes UI:R; the attacker needs a victim to load a crafted URL, which implies phishing, chat delivery, or another lure step.
  • Downward pressure: browser-side impact — this is XSS with session/origin abuse potential, not JVM RCE, container escape, or arbitrary file write.
  • Downward pressure: exposure fraction is narrow — in real enterprise deployments, the fraction of Tomcat servers with /examples/ still published externally should be far below the fraction merely running Tomcat 9.0.30-9.0.64.
  • Baseline kept above IGNORE — if a victim with meaningful privileges browses the page and admin functions share the same origin, the attacker can still steal session context or trigger actions.

Why not higher?

There is no evidence here of unauthenticated server-side code execution, privilege escalation on the host, or easy autonomous exploitation. The chain requires both a configuration mistake (examples left deployed) and a delivery step (victim interaction), which compounds the friction hard enough to push this well below MEDIUM in most estates.

Why not lower?

It is still a real remotely triggerable web bug when the sample app is exposed, and many orgs inherit Tomcat inside third-party products that leave default content behind. If the vulnerable examples app shares origin with admin or authenticated workflows, the resulting session theft or forced actions can still hurt.

05 · Compensating Control

What to do — in priority order.

  1. Remove the examples app — Delete or undeploy $CATALINA_BASE/webapps/examples (or the equivalent packaged sample app) because that removes the vulnerable surface entirely. For a LOW verdict there is no SLA from noisgate, but this is still cheap backlog hygiene and should be folded into the next normal hardening cycle.
  2. Block /examples/ at the proxy — If you cannot touch the application server immediately, deny access to /examples/* at the reverse proxy, ingress, or WAF. This is an effective temporary control because the bug is tied to a specific sample application path; for LOW, do it during routine config maintenance rather than emergency change windows.
  3. Verify same-origin admin exposure — Check whether Tomcat Manager, Host Manager, product admin consoles, or authenticated business apps share the same origin as the exposed examples app. If they do, the impact of this XSS rises because stolen cookies and browser-driven actions become more valuable.
  4. Patch during regular maintenance — Upgrade to 9.0.65+ or consume the relevant distro backport to close the finding cleanly. For a LOW verdict, keep it in scheduled remediation rather than front-of-queue emergency patching.
What doesn't work
  • Relying on MFA does not stop browser-side script execution once a victim is already authenticated to the origin.
  • Generic EDR on the server is not a strong control here because the exploit runs in the victim browser, not as a new process on the Tomcat host.
  • Only upgrading if the scanner sees Tomcat externally is insufficient; internal-only portals can still be exploitable if staff browse to the sample app.
06 · Verification

Crowdsourced verification payload.

Run this on the target host or on a mounted Tomcat installation directory. Invoke it as python3 check_tomcat_cve_2022_34305.py /opt/tomcat or python check_tomcat_cve_2022_34305.py "C:\Program Files\Apache Software Foundation\Tomcat 9.0"; no admin rights are required if you can read the Tomcat files.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
# check_tomcat_cve_2022_34305.py
# Exit codes:
#   0 = PATCHED
#   1 = VULNERABLE
#   2 = UNKNOWN

import os
import re
import sys
import zipfile
from pathlib import Path


def parse_version(v):
    m = re.match(r'^(\d+)\.(\d+)\.(\d+)', v or '')
    if not m:
        return None
    return tuple(int(x) for x in m.groups())


def read_manifest_version(catalina_jar):
    try:
        with zipfile.ZipFile(catalina_jar, 'r') as zf:
            data = zf.read('META-INF/MANIFEST.MF').decode('utf-8', errors='ignore')
        for line in data.splitlines():
            if line.startswith('Implementation-Version:'):
                return line.split(':', 1)[1].strip()
            if line.startswith('Specification-Version:'):
                spec = line.split(':', 1)[1].strip()
                if spec:
                    return spec
    except Exception:
        return None
    return None


def find_version(base):
    candidates = [
        base / 'lib' / 'catalina.jar',
        base / 'bin' / 'bootstrap.jar',
    ]
    for c in candidates:
        if c.exists():
            v = read_manifest_version(c)
            if v:
                return v

    release_notes = [
        base / 'RELEASE-NOTES',
        base / 'RUNNING.txt',
        base / 'webapps' / 'ROOT' / 'RELEASE-NOTES.txt',
    ]
    for rn in release_notes:
        if rn.exists():
            try:
                text = rn.read_text(errors='ignore')
                m = re.search(r'Apache Tomcat Version\s+([0-9]+\.[0-9]+\.[0-9]+)', text)
                if m:
                    return m.group(1)
            except Exception:
                pass
    return None


def examples_present(base):
    paths = [
        base / 'webapps' / 'examples',
        base / 'webapps' / 'examples.war',
        base / 'webapps-javaee' / 'examples',
        base / 'webapps-javaee' / 'examples.war',
    ]
    return any(p.exists() for p in paths)


def vulnerable_range(version_tuple):
    # Plugin scope: Tomcat 9.0.30 < 9.0.65
    return (9, 0, 30) <= version_tuple < (9, 0, 65)


def main():
    if len(sys.argv) != 2:
        print('UNKNOWN - usage: python3 check_tomcat_cve_2022_34305.py <CATALINA_BASE_or_HOME>')
        sys.exit(2)

    base = Path(sys.argv[1])
    if not base.exists() or not base.is_dir():
        print(f'UNKNOWN - path not found: {base}')
        sys.exit(2)

    version = find_version(base)
    if not version:
        print('UNKNOWN - could not determine Tomcat version from local files')
        sys.exit(2)

    vt = parse_version(version)
    if not vt:
        print(f'UNKNOWN - unparseable Tomcat version: {version}')
        sys.exit(2)

    has_examples = examples_present(base)

    if vulnerable_range(vt) and has_examples:
        print(f'VULNERABLE - Tomcat {version} with examples webapp present')
        sys.exit(1)
    elif vulnerable_range(vt) and not has_examples:
        print(f'PATCHED - Tomcat {version} is in affected range but examples webapp is absent; CVE-2022-34305 not reachable locally')
        sys.exit(0)
    else:
        print(f'PATCHED - Tomcat {version} is outside plugin affected range')
        sys.exit(0)


if __name__ == '__main__':
    main()
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: treat this finding as backlog hygiene unless you confirm /examples/ is actually exposed. For a LOW verdict there is no noisgate mitigation SLA and noisgate remediation SLA is essentially backlog hygiene, so verify presence of the sample app first, remove or block /examples/ during normal hardening work, and roll the Tomcat upgrade into your standard maintenance cycle rather than burning an emergency window.

Sources

  1. Tenable plugin 162498
  2. Apache Tomcat 9 security page
  3. NVD CVE-2022-34305
  4. Tenable CVE page with EPSS
  5. Debian security tracker CVE-2022-34305
  6. Ubuntu CVE-2022-34305
  7. Apache Tomcat security considerations
  8. CISA Known Exploited Vulnerabilities catalog
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.