This is a fire alarm an outsider can pull, but it doesn't unlock the vault
Plugin tenable:121121 maps to CVE-2018-1336 in Apache Tomcat's UTF-8 decoder. A specially crafted request containing supplementary UTF-8 characters can push the decoder into an infinite loop and hang request processing, producing denial of service only. Apache lists the issue as fixed in Tomcat 7.0.88; Tenable titles the check as 7.0.28 < 7.0.88, while the Apache/NVD affected-range text commonly cites 7.0.28 through 7.0.86. For defenders, the practical boundary is simple: 7.0.88+ is the upstream fix line.
The vendor-style CVSS baseline of 7.5 / High is technically defensible because the bug is unauthenticated, network-reachable, and easy to trigger. In real enterprise conditions, though, it falls short of High-priority patch chaos because the payoff is service disruption only—no RCE, no auth bypass, no data theft—and sustained impact usually needs repeated requests against a directly reachable Tomcat path. That makes this a downgrade to MEDIUM unless the affected Tomcat instance is revenue-critical and exposed with little edge protection.
4 steps from start to impact.
Find a reachable Tomcat endpoint
curl, httpx, or a version scanner like Nessus plugin 121121 to identify a Tomcat 7 endpoint that appears older than 7.0.88. Tenable's own plugin is version-based, not exploit-based, so this step is often just banner and package discovery rather than proof of exploitability.- HTTP(S) access to the Tomcat service or a reverse-proxied path
- Tomcat 7 deployment in the affected range
- Response metadata or package evidence sufficient to identify version
- Many enterprise Tomcat instances sit behind Apache, Nginx, ADCs, or application gateways
- Banner suppression and custom packaging make exact versioning noisy
- Tenable explicitly notes the check relies on self-reported version information
Send malformed supplementary UTF-8 input
curl, Burp Repeater, or a custom socket script, the attacker sends a request that forces Tomcat's UTF-8 decoder down the vulnerable path described by the Apache advisory. No authentication or user interaction is required.- The crafted bytes must reach Tomcat's decoder intact
- The request path must hit request parsing that exercises the vulnerable decoder logic
- Reverse proxies, WAFs, or URL normalization layers may reject or rewrite malformed input first
- Some deployments terminate bad requests at the edge before Tomcat sees them
Trap the decoder in an infinite loop
- Tomcat must be running a vulnerable build without a backported fix
- The malformed request must hit the exact parser behavior fixed by revision
r1830376
- Single-request impact may be limited by thread pools, timeouts, and upstream health checks
- Auto-restart and container orchestration can shorten the outage window
Repeat to sustain the outage
ab, wrk, or a trivial Python loop. This is where the real-world severity gets capped: they still only get availability impact, and they usually need sustained reachability plus enough volume to matter.- Direct or reliable indirect access to the target over time
- Sufficient request volume to overwhelm available workers or restart cadence
- Rate limits, upstream connection caps, bot filtering, autoscaling, and health-based failover reduce blast radius
- Internet-facing DDoS controls often catch repetitive malformed traffic faster than the app team does
The supporting signals.
| In-the-wild status | No strong public evidence of active exploitation found in CISA or vendor references for this CVE. This is *not* the kind of Tomcat bug that drove major KEV-style patch emergencies. |
|---|---|
| KEV status | Not listed in CISA KEV based on current CISA search results; CISA issued an informational alert on 2018-07-23 about Tomcat updates, not a known-exploited designation. |
| Public PoC / weaponization | No well-known public exploit kit or widely cited GitHub PoC surfaced in source review. Practical exploitation likely needs only a custom malformed HTTP request, but that is different from seeing broad attacker tooling. |
| EPSS | 15.01% EPSS, ~94th percentile per CVEDetails' current EPSS display. That says 'worth tracking,' not 'drop everything.' |
| CVSS baseline | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H = 7.5 High. The score is driven entirely by network-reachable availability loss, with zero confidentiality or integrity impact. |
| Affected versions | Apache states Tomcat 7.0.28 to 7.0.88 in the 7.x advisory page context, while NVD commonly renders 7.0.28 to 7.0.86 in the description text. Treat all 7.0.x below 7.0.88 as suspect for operations. |
| Fixed versions | Upstream fix is 7.0.88+. Distro backports matter: Ubuntu 16.04 ESM 7.0.68-1ubuntu0.4+esm1, Ubuntu 14.04 7.0.52-1ubuntu0.15, Debian Jessie 7.0.56-3+really7.0.88-1, RHEL 7 tomcat-7.0.76-8.el7_5. |
| Exposure / scanning footprint | This is a widely deployed platform, but not all exposed Tomcat is directly exploitable because proxies often sit in front. CVEDetails currently shows 215,883 affected IPs in its attack-surface feed, and Bitsight shows 41,946 total observations over a 30-day survey window—useful as exposure indicators, not proof of exploitability. |
| Disclosure timeline | Apache says the issue was reported publicly on 2018-04-06, fixed in Tomcat 7.0.88 on 2018-05-16, and formally announced as a vulnerability on 2018-07-22. |
| Researcher / reporter | Publicly reported; no named external researcher in the Apache advisory. The Apache Tomcat Security Team carried the formal announcement. |
noisgate verdict.
The decisive limiter is impact: this flaw is an unauthenticated remote trigger, but it only buys the attacker availability disruption, not execution or compromise. The second limiter is operational friction—many Tomcat deployments are buffered by reverse proxies, rate limits, and failover, so the reachable population and blast radius are both narrower than the raw CVSS implies.
Why this verdict
- Availability-only impact: CVSS is inflated by easy network reachability, but the attacker gets disruption, not code execution, auth bypass, or data access.
- Requires direct app-path reachability: if Tomcat is hidden behind Apache/Nginx/ADC/WAF layers, malformed UTF-8 may never hit the vulnerable decoder as intended.
- No strong exploitation signal: no KEV listing, no major campaign history, and no famous public exploit chain means this is not behaving like a patch-now internet fire.
Why not higher?
If this were paired with active exploitation, a public weaponized PoC, or a demonstrated ability to take down high-value internet services with low request volume, I'd keep it at High. It also stays below High because most enterprises can absorb pure app-layer DoS risk better than they can absorb initial-access or privilege-escalation flaws.
Why not lower?
This is still unauthenticated and remote, so you cannot hand-wave it away as local-only nuisance. If you run legacy Tomcat 7 directly on the internet without edge controls, a low-effort attacker can still turn this into a real outage.
What to do — in priority order.
- Put Tomcat behind a validating reverse proxy — Front vulnerable instances with Apache, Nginx, or an ADC that rejects malformed requests and normalizes URI handling before Tomcat sees them. For a MEDIUM verdict there is no mitigation SLA, but if you cannot patch soon, this is the cleanest exposure reduction to put in place before the 365-day remediation window closes.
- Rate-limit malformed and bursty requests — Apply per-IP request ceilings, connection caps, and anomaly rules for bad encoding, repeated 4xx spikes, and parser-error patterns. This reduces the attacker's ability to turn a one-request bug into a sustained outage; for MEDIUM, there is no mitigation SLA, so use this as opportunistic hardening while working toward remediation.
- Remove direct internet exposure where possible — If the app does not need to be publicly reachable, pin it behind VPN, allowlists, private load balancers, or internal-only routing. This sharply cuts reachable population and is especially worthwhile for old Tomcat 7 estates, even though MEDIUM carries no mitigation SLA.
- Alert on Tomcat thread and connector saturation — Monitor Java CPU, request backlog, connector busy threads, and rapid restart loops so app-layer DoS is visible before customers tell you. This does not fix the bug, but it shortens time-to-detect and helps the SOC distinguish parser abuse from generic traffic spikes.
- MFA does nothing here because the bug is unauthenticated and hits request parsing before login matters.
- EDR alone is a weak answer because this is not a malware-on-host problem; the failure mode is a Java service spinning or stalling under malformed traffic.
- Version-based exceptions are dangerous on their own because Tomcat is heavily backported by distros; you need package-advisory context, not just the banner string.
Crowdsourced verification payload.
Run this on the target Tomcat host as a local admin or service-support account that can read the Tomcat install tree and package database. Invoke it like bash verify_cve_2018_1336.sh /opt/tomcat or simply bash verify_cve_2018_1336.sh to let it auto-detect common paths; root is not strictly required, but package-manager queries may need normal local shell access.
#!/usr/bin/env bash
# verify_cve_2018_1336.sh
# Checks Apache Tomcat 7 exposure to CVE-2018-1336 (UTF-8 decoder DoS)
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
TARGET_DIR="${1:-}"
ver_ge() {
[ "$(printf '%s\n' "$1" "$2" | sort -V | tail -n1)" = "$1" ]
}
ver_lt() {
[ "$1" != "$2" ] && ! ver_ge "$1" "$2"
}
print_result() {
local state="$1"
local msg="$2"
echo "$state: $msg"
case "$state" in
PATCHED) exit 0 ;;
VULNERABLE) exit 1 ;;
*) exit 2 ;;
esac
}
check_upstream_version() {
local v="$1"
if [[ ! "$v" =~ ^7\.0\.[0-9]+$ ]]; then
print_result "UNKNOWN" "Detected Tomcat version '$v' is not Tomcat 7.0.x; this script only assesses Tenable plugin 121121 scope."
fi
if ver_ge "$v" "7.0.88"; then
print_result "PATCHED" "Upstream Tomcat version $v is at or above 7.0.88."
elif ver_ge "$v" "7.0.28" && ver_lt "$v" "7.0.88"; then
print_result "VULNERABLE" "Upstream Tomcat version $v falls in the affected Tenable range (< 7.0.88)."
else
print_result "PATCHED" "Tomcat version $v is below 7.0.28 and outside this plugin's affected range."
fi
}
get_server_number_from_tree() {
local base="$1"
local out=""
if [[ -x "$base/bin/version.sh" ]]; then
out="$($base/bin/version.sh 2>/dev/null || true)"
elif [[ -x "$base/bin/catalina.sh" ]]; then
out="$($base/bin/catalina.sh version 2>/dev/null || true)"
elif [[ -r "$base/lib/catalina.jar" ]] && command -v java >/dev/null 2>&1; then
out="$(java -cp "$base/lib/catalina.jar" org.apache.catalina.util.ServerInfo 2>/dev/null || true)"
fi
echo "$out" | awk '/Server number:/ {print $3}' | head -n1
}
check_dpkg() {
command -v dpkg-query >/dev/null 2>&1 || return 1
command -v dpkg >/dev/null 2>&1 || return 1
if dpkg-query -W -f='${Status} ${Version}\n' tomcat7 2>/dev/null | grep -q '^install ok installed '; then
local pkgver
pkgver="$(dpkg-query -W -f='${Version}' tomcat7 2>/dev/null)"
if grep -qi ubuntu /etc/os-release 2>/dev/null; then
if dpkg --compare-versions "$pkgver" ge '7.0.68-1ubuntu0.4+esm1'; then
print_result "PATCHED" "Ubuntu tomcat7 package $pkgver includes the CVE-2018-1336 fix or later backport."
fi
print_result "UNKNOWN" "Ubuntu tomcat7 package $pkgver detected. Older Ubuntu builds may carry backports; verify against Ubuntu CVE/advisory data if not on ESM-fixed package levels."
fi
if grep -qi debian /etc/os-release 2>/dev/null; then
if dpkg --compare-versions "$pkgver" ge '7.0.56-3+really7.0.88-1'; then
print_result "PATCHED" "Debian tomcat7 package $pkgver includes the Debian backport fix."
fi
print_result "UNKNOWN" "Debian tomcat7 package $pkgver detected below the known Jessie fixed build. Check distro support status and backport history."
fi
print_result "UNKNOWN" "tomcat7 package $pkgver detected on a dpkg-based system; unsupported distro-specific packaging needs manual review."
fi
return 1
}
check_rpm() {
command -v rpm >/dev/null 2>&1 || return 1
if rpm -q tomcat >/dev/null 2>&1; then
local vr
vr="$(rpm -q --qf '%{VERSION}-%{RELEASE}' tomcat 2>/dev/null)"
if grep -qi 'rhel\|red hat' /etc/os-release 2>/dev/null || [[ -f /etc/redhat-release ]]; then
if ver_ge "$vr" '7.0.76-8.el7_5'; then
print_result "PATCHED" "RHEL tomcat package $vr is at or above the RHSA-2018:2921 fixed build."
fi
print_result "UNKNOWN" "RHEL tomcat package $vr detected below the known fixed build; confirm with `rpm -q --changelog tomcat | grep CVE-2018-1336` or Red Hat advisory mapping."
fi
print_result "UNKNOWN" "RPM tomcat package $vr detected on a non-RHEL-identified system; distro backports require local advisory review."
fi
return 1
}
main() {
if [[ -n "$TARGET_DIR" && -d "$TARGET_DIR" ]]; then
v="$(get_server_number_from_tree "$TARGET_DIR")"
if [[ -n "$v" ]]; then
check_upstream_version "$v"
fi
fi
for d in /opt/tomcat /usr/share/tomcat /usr/share/tomcat7 /usr/local/tomcat /var/lib/tomcat7 /usr/local/apache-tomcat*; do
[[ -d "$d" ]] || continue
v="$(get_server_number_from_tree "$d")"
if [[ -n "$v" ]]; then
check_upstream_version "$v"
fi
done
check_dpkg || true
check_rpm || true
print_result "UNKNOWN" "Could not reliably determine Tomcat 7 version or package backport status from this host."
}
main
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.