● Critical · CVSS 9.8 ⚠ ACTIVELY EXPLOITED — CISA KEV

How to Fix CVE-2016-8735: Remote Code Execution in Apache Tomcat

By the Sai Kiran Pandrala · Reviewed and edited by Sai Kiran Pandrala, Editor

⚡ At a glance
SeverityCVSS 9.8 - Critical
Actively exploited?Yes, listed in CISA KEV (added 2023-05-12)
AffectedApache Tomcat: before 6.0.48; Apache Tomcat: 7.x before 7.0.73; Apache Tomcat: 8.x before 8.0.39; Apache Tomcat: 8.5.x before 8.5.7; Apache Tomcat: 9.x before 9.0.0.M12
Fixed inTomcat 6.0.48, 7.0.73, 8.0.39, 8.5.7, and 9.0.0.M12 (upgrade to the fixed build on your branch)
Type (CWE)Remote code execution (deserialization of untrusted JMX credentials)
PreconditionOnly exploitable when JmxRemoteLifecycleListener is enabled and the JMX ports are reachable by the attacker

Exploitation status

CVE-2016-8735 is actively exploited in the wild. CISA added it to the Known Exploited Vulnerabilities (KEV) catalog on as “Apache Tomcat Remote Code Execution Vulnerability”, which makes patching mandatory for U.S. federal agencies under Binding Operational Directive 22-01. Federal agencies were required to remediate it by . If you run an affected system, treat this as an emergency change, not a scheduled one.

Public exploit availability: although a public exploit is not directly linked in this CVE’s primary references, its place on the CISA KEV catalog confirms working attack code is in active use in the wild, treat weaponization as certain and patch on an emergency timeline.

Authoritative references:

Patch immediately. CISA's Known Exploited Vulnerabilities catalog lists this CVE, which means active exploitation has been confirmed. CISA KEV entry added 2023-05-12, federal due date 2023-06-02.

What is CVE-2016-8735?

CVE-2016-8735 is a remote code execution flaw in Apache Tomcat, the Apache Software Foundation's Java servlet container. It is not a flaw in the Apache HTTP Server (httpd / apache2). the two products are unrelated despite the shared “Apache” name. The affected branches are Tomcat before 6.0.48, 7.x before 7.0.73, 8.x before 8.0.39, 8.5.x before 8.5.7, and 9.x before 9.0.0.M12.

The bug lives in JmxRemoteLifecycleListener, an optional listener you add to server.xml so JMX clients can manage Tomcat over fixed RMI ports through a firewall. When Oracle fixed CVE-2016-3427 in the JDK, it tightened which object types are accepted during JMX credential deserialization. Tomcat's listener was never updated to stay consistent with that change, so a remote client that can reach the configured JMX ports can supply a crafted serialized object that gets deserialized into a malicious payload, yielding remote code execution as the user running Tomcat. Because the attack rides the standard JMX/RMI authentication exchange, it needs no valid Tomcat application credentials.

The single most important fact about this CVE: it only applies if you have explicitly enabled JmxRemoteLifecycleListener and the JMX ports it opens are reachable from the attacker's network position. A default Tomcat install does not load this listener. If you have never added it, you are not exposed to this specific bug: but you should still upgrade, because the fixed builds also carry other security fixes for the same branch.

Why this CVE matters

CVSS scores it 9.8 (Critical): network attack vector, low complexity, no privileges, no user interaction, and full compromise of confidentiality, integrity, and availability. CISA added it to the Known Exploited Vulnerabilities catalog on 2023-05-12, which only happens after active exploitation is observed. CISA's own SSVC assessment marks exploitation as active, the attack as automatable, and the technical impact as total. A successful exploit runs arbitrary code as the Tomcat process account, which on many deployments has read access to application secrets, datasource passwords, and keystores. If your deployment ran an affected build with the listener enabled and the JMX ports exposed during the disclosure window, treat it as compromise-likely and review logs accordingly.

Are you affected?

Two conditions both have to be true. First, your Tomcat build is inside an affected range. Second, JmxRemoteLifecycleListener is enabled. Check the version first:

# Print the exact Tomcat version from the install you run
$CATALINA_HOME/bin/version.sh        # Linux / macOS
# or, from a running JVM:
java -cp $CATALINA_HOME/lib/catalina.jar org.apache.catalina.util.ServerInfo

Then confirm whether the vulnerable listener is configured. If this grep returns nothing, the exploitable code path is not active on this instance:

# Look for the JMX remote listener in server.xml
grep -R "JmxRemoteLifecycleListener" "$CATALINA_BASE/conf/server.xml"
# Also confirm which RMI ports it binds (rmiRegistryPortPlatform / rmiServerPortPlatform)
grep -R "rmiRegistryPortPlatform\|rmiServerPortPlatform" "$CATALINA_BASE/conf/server.xml"

How to fix CVE-2016-8735

Upgrade Tomcat to the first fixed build on your branch. The Apache Software Foundation patched this in the following releases, and you should move to that version or later on the same major line:

Because every one of these branches is now end of life, the right long-term move is to jump to a currently supported Tomcat release (10.1.x or 11.0.x at time of writing). The version-specific upgrade below stops the bleeding; the major upgrade is what keeps you patched going forward.

Fastest mitigation: remove the listener

If you cannot upgrade in the next few minutes, the exploit path can be closed immediately by removing or commenting out the listener in $CATALINA_BASE/conf/server.xml and restarting Tomcat. Delete this line:

<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener"
          rmiRegistryPortPlatform="10001" rmiServerPortPlatform="10002" />

If you need JMX management but can drop the listener, switch to standard JVM JMX flags (-Dcom.sun.management.jmxremote.*) bound to localhost and reach it over an SSH tunnel instead. This sidesteps the vulnerable Tomcat code entirely. Either way, upgrade as soon as the change window allows.

Linux (tarball / manual install)

Most Tomcat deployments are unpacked from the official .tar.gz, not from apt or dnf (the distro tomcat packages lag well behind upstream). The clean upgrade is to install the fixed build alongside the old one and re-point CATALINA_HOME:

# Example: 8.5.x branch upgrading to the first fixed build (8.5.7) or later
sudo systemctl stop tomcat
sudo cp -a "$CATALINA_BASE/conf" "/var/backups/tomcat-conf-$(date +%Y%m%d-%H%M)"

# Download the fixed (or a later, supported) build and verify its signature/checksum
VER=8.5.7
curl -fsSLO "https://archive.apache.org/dist/tomcat/tomcat-8/v${VER}/bin/apache-tomcat-${VER}.tar.gz"
curl -fsSLO "https://archive.apache.org/dist/tomcat/tomcat-8/v${VER}/bin/apache-tomcat-${VER}.tar.gz.sha512"
sha512sum -c "apache-tomcat-${VER}.tar.gz.sha512"

sudo tar -xzf "apache-tomcat-${VER}.tar.gz" -C /opt/
# Carry over your conf/ and webapps/, then re-point the symlink your service uses
sudo ln -sfn "/opt/apache-tomcat-${VER}" /opt/tomcat
sudo systemctl start tomcat

Distro package (if you installed Tomcat from the OS repo)

# Debian / Ubuntu: the package is named after the major version (e.g. tomcat9)
sudo apt-get update
sudo apt-get install --only-upgrade tomcat9
dpkg-query -W -f='${Version}\n' tomcat9

# RHEL / Rocky / AlmaLinux
sudo dnf upgrade --refresh tomcat -y
rpm -q tomcat

Confirm the upstream version the package wraps actually meets the fixed build above, distro version strings differ from Apache's, so cross-check with version.sh after the upgrade.

Container image

# Pull an official Tomcat tag at or above the fixed build, then rebuild your app image.
# Prefer a currently supported line (10.1 / 11.0) over the EOL 8.5/9.0 branches.
docker pull tomcat:9.0
docker build -t <your-app>:patched .   # FROM tomcat:9.0 in your Dockerfile
docker stop <your-app> && docker rm <your-app>
docker run -d --name <your-app> <your-app>:patched

Windows service upgrade (PowerShell)

# CVE-2016-8735 remediation for a Tomcat Windows service install.
$log = "C:\Logs\CVE-2016-8735-fix.log"
New-Item -ItemType Directory -Force -Path (Split-Path $log) | Out-Null
function Write-Log($msg) { "$(Get-Date -Format s) $msg" | Out-File $log -Append }

try {
    $svc = "Tomcat9"   # adjust to your service name
    Write-Log "Detect: reading current Tomcat version"
    $catalina = "C:\Program Files\Apache Software Foundation\Tomcat 9.0"
    & "$catalina\bin\version.bat" | Tee-Object -Variable ver | Out-Null
    Write-Log "Found: $ver"

    Write-Log "Stop + backup conf"
    Stop-Service $svc -ErrorAction SilentlyContinue
    $stamp  = Get-Date -Format yyyyMMdd-HHmm
    Copy-Item "$catalina\conf" "C:\Backup\tomcat-conf-$stamp" -Recurse -Force

    Write-Log "Upgrade: install the fixed (or supported) build, then restore conf\ + webapps\"
    # Install the official Windows installer / unzip the fixed apache-tomcat-*.zip here,
    # then copy your conf\ and webapps\ back over the new install directory.

    Write-Log "Verify + restart"
    Start-Service $svc
    & "$catalina\bin\version.bat" | Tee-Object -Variable after | Out-Null
    Write-Log "Post-patch: $after"
} catch {
    Write-Log "ERROR: $_"
    throw
}

After any of these paths, restart Tomcat so the new catalina.jar is the code actually serving requests.

If you can't patch immediately

Patching is the only durable fix. These mitigations cut exposure while the change window is scheduled, they do not remove the vulnerability.

Restrict the JMX ports (iptables / nftables)

This bug is reached through the RMI ports the listener binds (rmiRegistryPortPlatform and rmiServerPortPlatform in server.xml. commonly 10001/10002). Lock those ports to your management network so no one else can speak JMX to the instance. These are not your HTTP/HTTPS ports; leave 80/443 alone.

# Replace 10.0.0.0/8 with your management network and 10001/10002 with your JMX ports.
sudo iptables -I INPUT -p tcp -m multiport --dports 10001,10002 -s 10.0.0.0/8 -j ACCEPT
sudo iptables -A INPUT -p tcp -m multiport --dports 10001,10002 -j DROP
sudo iptables-save | sudo tee /etc/iptables/rules.v4
# nftables equivalent
sudo nft add rule inet filter input tcp dport { 10001, 10002 } ip saddr != 10.0.0.0/8 drop

Confirm the fix landed

After upgrading, confirm the running version is at or above the fixed build for your branch (6.0.48 / 7.0.73 / 8.0.39 / 8.5.7 / 9.0.0.M12):

$CATALINA_HOME/bin/version.sh        # prints "Server version: Apache Tomcat/X.Y.Z"
# And confirm the listener is gone or its ports are now firewalled:
grep -c "JmxRemoteLifecycleListener" "$CATALINA_BASE/conf/server.xml"

Run an authenticated vulnerability scan with a current signature set and confirm the scanner no longer flags CVE-2016-8735. For instances that exposed the JMX ports during the disclosure window, review logs for unexpected JMX connections, rotate any datasource passwords and keystore credentials the Tomcat process account could read, and look for new accounts, scheduled tasks, or outbound connections from the host.

Frequently asked questions

Is my default Tomcat install affected by CVE-2016-8735?

Only if you added JmxRemoteLifecycleListener to conf/server.xml and the JMX ports it opens are reachable by an attacker. A stock Tomcat install does not load that listener, so the exploit path is inactive, but you should still move off the affected build because the fixed releases carry other security fixes too.

Does this affect Apache HTTP Server (apache2 / httpd)?

No. CVE-2016-8735 is a flaw in Apache Tomcat, the Java servlet container. The Apache HTTP Server is a separate project and is not affected. Do not try to fix this by upgrading the apache2 or httpd package: upgrade Tomcat itself.

Which version do I upgrade to?

Move to the first fixed build on your branch or later: 6.0.48, 7.0.73, 8.0.39, 8.5.7, or 9.0.0.M12. Every one of those branches is now end of life, so the better choice is to jump to a currently supported line (10.1.x or 11.0.x).

Do I need to assume compromise if the JMX ports were exposed and unpatched?

For a CVE that CISA confirms is under active exploitation, yes. Review logs over the entire exposure window, rotate datasource passwords and keystore credentials the Tomcat process could read, and look for unexpected accounts, scheduled tasks, or outbound connections.

References


This guide was assembled from the official vendor advisory, the NVD record, and the CISA KEV catalog entry on 2026-05-25. Always confirm against the vendor advisory before applying changes in production.

Related weaknesses in the same component worth addressing at the same time:

People also ask

Is my default Tomcat install affected by CVE-2016-8735?

Only if you added JmxRemoteLifecycleListener to conf/server.xml and the JMX ports it opens are reachable by an attacker. A stock Tomcat install does not load that listener, so the exploit path is inactive, but you should still upgrade because the fixed builds carry other security fixes.

Does CVE-2016-8735 affect Apache HTTP Server (apache2 / httpd)?

No. It is a flaw in Apache Tomcat, the Java servlet container. The Apache HTTP Server is a separate project and is not affected. Do not fix this by upgrading the apache2 or httpd package. upgrade Tomcat itself.

Which Tomcat version fixes CVE-2016-8735?

Move to the first fixed build on your branch or later: 6.0.48, 7.0.73, 8.0.39, 8.5.7, or 9.0.0.M12. All of those branches are end of life, so a supported line (10.1.x or 11.0.x) is the better target.