Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
cve-2026-69243-poc-aiohttp-smuggling — Reproduziert aiohttp CWE-444 Request-Smuggling über abgelehnte WebSocket-Upgrades, mit Python/Rust-Payloads und Docker-Lab zur Demonstration der Umgehung der Proxy-Zugriffskontrolle. | Kitploit
Tools/GitHubGitHub/jvbotelho/cve-2026-69243-poc-aiohttp-smuggling
Payload-GenerierungSchwachstellenanalyseExploitationWebanwendungs-ExploitationWebsicherheitFuzzing
GitHubjvbotelho/cve-2026-69243-poc-aiohttp-smuggling

cve-2026-69243-poc-aiohttp-smuggling

Reproduziert aiohttp CWE-444 Request-Smuggling über abgelehnte WebSocket-Upgrades, mit Python/Rust-Payloads und Docker-Lab zur Demonstration der Umgehung der Proxy-Zugriffskontrolle.

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Repository anzeigenWebseite
129vor 2 MonatenNoch nicht geprüft
Teilen

CVE-2026-69243 — aiohttp Request-Smuggling (CWE-444)

Request-Smuggling über abgelehntes WebSocket-Upgrade in aiohttp < 3.14.2. Wenn ein Reverse-Proxy Connection: Upgrade + Upgrade: websocket-Header weiterleitet, überspringt der verwundbare aiohttp-Parser den Request-Body und interpretiert nachfolgende Bytes als gepipelinte Anforderung – und umgeht so Edge-Zugriffskontrollen.

Behoben in aiohttp 3.14.2 (Commit 6ae358f).

Autor: João Victor Botelho (JV Botelho) — https://glitchedcat.com

60-Sekunden-Testlauf

Python-Version kopieren und einfügen (keine Abhängigkeiten, nur Standardbibliothek):

curl -O https://raw.githubusercontent.com/JVBotelho/cve-2026-69243-poc-aiohttp-smuggling/main/poc.py
python3 poc.py <proxy-host> <proxy-port> <backend-host>

Oder die Rust-Version bauen (keine Abhängigkeiten, nur Standardbibliothek):

git clone https://github.com/JVBotelho/cve-2026-69243-poc-aiohttp-smuggling
cd cve-2026-69243-poc-aiohttp-smuggling/poc
cargo build --release
./target/release/cve-2026-69243-poc <proxy-host> <proxy-port> <backend-host>

Vorgefertigte Binärdateien werden über den Release-Workflow auf Releases veröffentlicht.

Beide erzeugen byte-identische Payloads (durch einen CI-Paritätstest erzwungen). Wenn das Labor läuft:

python3 poc.py nginx-upgrade 80 backend-vuln

Erwartete Ausgabe: 1 HTTP-Antwort (WebSocket upgrade rejected). Danach prüfen:

# Backend processed 2 requests (/ws + smuggled /admin):
docker logs backend-vuln | grep -c '"path".*"/admin"'

# Nginx only logged 1 request (the /ws):
docker exec nginx-upgrade cat /logs/nginx-upgrade.access.log | grep -c '/admin'

Ein Backend-Zähler > 0 und ein Nginx-Zähler = 0 bedeutet, dass die CWE-444-Aufspaltung bestätigt ist. Dieser PoC sendet ein einzelnes TCP-Segment – der Body ist die geschmuggelte Anforderung; Nginx behandelt ihn als Body, aiohttp als zweite Anforderung.

Was das beweist

  • Parser-Konfusion: aiohttp 3.14.1 _http_parser.pyx liefert bei Erkennung des Upgrades den Wert 2 (Body überspringen), bevor der Body verarbeitet wurde (Zeile ~863). Die Body-Bytes verbleiben in _message_tail und werden in web_protocol.py finish_response (Zeile ~771) dem Parser erneut zugeführt.
  • CWE-444-Aufspaltung: Das Frontend sieht 1 Anforderung mit Body; das Backend sieht 2 gepipelinte Anforderungen. Abweichung der Anforderungszählung in den Logs.
  • Umgehung der Zugriffskontrolle: Wenn Nginx location /admin { deny all; } konfiguriert hat, erreicht das geschmuggelte /admin trotzdem das Backend, weil Nginx seine Routing-Entscheidungen nur anhand der äußeren Anforderung trifft.
  • Kein Fix auf Handler-Ebene: await request.read() liefert bei Upgrade-Anforderungen in 3.14.1 0 Bytes zurück – der Body wird unterhalb der Handler-Ebene zurückgehalten. Patchen Sie, oder entfernen Sie die Upgrade-Header am Proxy auf Routen, die keine Protokollwechsel erlauben dürfen.

Vollständiges Labor

git clone https://github.com/JVBotelho/cve-2026-69243-poc-aiohttp-smuggling
cd cve-2026-69243-poc-aiohttp-smuggling
docker compose up -d

# Run the PoC:
docker compose run --rm --entrypoint /app/poc attacker nginx-upgrade 80 backend-vuln

Dienste:

ContainerZweck
backend-vulnaiohttp 3.14.1 (verwundbar), READ_BODY=false
backend-vuln-readaiohttp 3.14.1, READ_BODY=true (beweist, dass der Handler nicht helfen kann)
backend-patchedaiohttp 3.14.2 (behoben)
nginx-upgradeLeitet Upgrade-Header weiter (deny all auf /admin)
nginx-defaultKeine Upgrade-Weiterleitung (neutralisiert den Fehler)
nginx-stripConnection ""-Entfernung (neutralisiert den Fehler)
attackerRust-Binärdateien: reproduce, fase2, poc

Vollständige Erkenntnisse der Phasen 1-3 in findings/.

Einschränkungen (ehrlich)

  • Der Proxy muss Upgrade-Header weiterleiten. Nginx-Konfigurationen, die Connection: close an das Backend senden oder die Connection-/Upgrade-Header entfernen, sind nicht verwundbar. Die Konfiguration, die die Aufspaltung ermöglicht, ist das kanonische WebSocket-map-Snippet aus Nginxs eigener Proxying-Dokumentation.
  • Die geschmuggelte Antwort wird vom Proxy absorbiert. In der demonstrierten Nginx-Kette erhält der Angreifer nur die äußere /ws-Antwort. Belege für das Schmuggeln finden sich in den Backend-Logs, nicht in der Antwort an den Angreifer – eine blinde, einseitige Primitive in dieser Topologie. Andere Proxy-Topologien wurden nicht getestet.
  • Chunked-Framing ist in seiner Wirkung an Content-Length gebunden. Direkt gegen aiohttp schmuggelt Transfer-Encoding: chunked NICHT – die rohe Chunk-Größenzeile (z. B. 3e) trifft als ungültige Methode auf den Parser und die Verbindung stirbt. Über Nginx funktioniert es, jedoch über Normalisierung: Nginx entfernt die Chunk-Kodierung des Bodys und leitet eine synthetisierte Content-Length weiter, sodass das Backend über denselben CL-Pfad ausgenutzt wird. Das --chunked-Flag demonstriert den Proxy-Pfad.
  • Erfordert einen Endpunkt, der WebSocket-Upgrades ablehnt. Der Handler muss eine Nicht-WebSocketResponse zurückgeben. Die meisten Apps, die auf einer Route keine WebSockets verwenden, lehnen standardmäßig ab (das Framework gibt 404 zurück oder fällt auf den nächsten Handler zurück).

Dateien

poc/                       # Rust cargo project
├── Cargo.toml
├── src/main.rs            # CLI binary
├── src/lib.rs             # Library + unit tests
├── tests/parity.rs        # Cross-language payload parity test
└── fuzz/                  # cargo-fuzz targets
poc.py                     # Python PoC (copy-paste from blog)
attacker/ backend/ frontend/   # Docker lab services
docker-compose.yml         # 7-service lab
findings/                  # Research notes (Phase 1-3)
.github/workflows/
├── ci.yml                 # Build, test, clippy, parity, integration, fuzz
└── release.yml            # Cross-compile + GitHub Release

Erkennung

Siehe findings/fase3-deteccao.md für die vollständige Analyse. Zusammenfassung, mit den Einschränkungen, die in der Produktion relevant sind:

  1. Abweichung der Anforderungszählung (Backend > Frontend) auf derselben Verbindung. Beachten Sie: Das Backend protokolliert die IP des Proxys, nicht die des Clients – die Korrelation erfordert die Normalisierung von X-Forwarded-For/Proxy Protocol oder das Protokollieren einer Upstream-Verbindungs-ID + der Anforderungssequenz pro Verbindung. Allein Client-IP + Zeitfenster ist schwach (NAT, Keep-alive, Nebenläufigkeit).
  2. Backend-Anforderung ohne Frontend-Entsprechung: ein eingeschränkter Pfad im Backend-Log ohne zugehörigen Eintrag im Frontend-Access-Log. Interne Subnetze herausfiltern (Health Checks, die den Proxy umgehen, erzeugen False Positives).
  3. Upgrade-Ablehnung + anderer Pfad vom selben Client in ~100 ms. Mittlere Konfidenz – legitimes Pipelining erzeugt ähnliche Intervalle; der Labor-Logger zeichnet keine Remote-Port-/Verbindungs-ID auf, daher ist "kein neuer TCP-Handshake" KEINE Aussage, die diese Daten belegen.
  4. Middleware für zurückgehaltene Bodies (content_length vs. Bytes aus request.read()): schlägt bei 3.14.1 an, bleibt bei 3.14.2 ruhig. Erkennt, entschärft aber nicht. Eingrenzen (Routen mit Upgrade-Kandidaten, kleine Bodies, Nicht-101-Status) – die naive Version puffert jeden Body im Speicher.
  5. Edge-reqlen über der Header-Basislinie an WebSocket-Endpunkten – allein betrachtet geringe Konfidenz (Cookies/JWT/Tracing-Header sind verrauscht), aber das einzige Edge-Signal, wenn der Client kein Content-Length sendet (Chunked-Eingang).
Tool herunterladen