Write-up · HTTP Request Smuggling

HTTP Request Smuggling: Wenn Front-End und Back-End sich nicht einig sind

Moderne Webanwendungen bestehen selten aus einem einzigen Server. Vorne sitzt ein Load Balancer, Reverse Proxy oder CDN, dahinter ein oder mehrere Back-Ends. Beide Seiten müssen sich einig sein, wo eine HTTP-Anfrage aufhört und die nächste anfängt. Sind sie es nicht, entsteht eine der heimtückischsten Schwachstellenklassen im Web. Dieser Beitrag zerlegt die klassischen Varianten, die modernen HTTP/2-Vektoren und zeigt, wie man Smuggling im Pentest risikoarm erkennt.

Veröffentlicht: 17.08.2026 · Lesezeit: 14 Min · Autor: Niclas Zillmanns

Hinweis: Dieser Artikel basiert auf eigener Praxiserfahrung aus Pentests sowie auf verifizierten Primärquellen: dem Original-Research von James Kettle, dem ACM-CCS-Paper T-Reqs (Jabiyev et al., 2021), ReqsMiner (NDSS 2024) und HDHunter (USENIX Security 2025). Die gezeigten Techniken dienen ausschließlich dem Verständnis und der Verbesserung der Anwendungssicherheit.

Was ist HTTP Request Smuggling?

Moderne Webanwendungen bestehen selten aus einem einzigen Server. Meistens sitzt ein Front-End – ein Load Balancer, Reverse Proxy oder CDN – vor einem oder mehreren Back-End-Servern. Dieser Aufbau ist heute Standard, und er bringt ein grundsätzliches Problem mit sich: Beide Seiten müssen sich einig sein, wo eine HTTP-Anfrage aufhört und die nächste anfängt.

Sind sie es nicht, kann ein Angreifer eine mehrdeutige Anfrage so konstruieren, dass das Front-End sie als eine Anfrage interpretiert – das Back-End aber als zwei. Der Angreifer schmuggelt damit versteckten Inhalt an den Anfang der nächsten legitimen Nutzeranfrage.

Das ist HTTP Request Smuggling. Erstmals dokumentiert von Linhart et al. (Watchfire) im Jahr 2005, für viele Jahre ignoriert, und 2019 von James Kettle auf der Black Hat vollständig neu aufgearbeitet – mit modernen Angriffsvektoren, eigenem Tooling und über 70.000 US-Dollar in Bug Bounties. Seitdem ist die Forschung nicht stehengeblieben.

Warum passiert das? Das Content-Length / Transfer-Encoding Problem

Seit HTTP/1.1 können mehrere Anfragen über eine einzige TCP-Verbindung gesendet werden. Der Server muss anhand von Headern erkennen, wo eine Anfrage endet. Zwei Mechanismen existieren:

  • Content-Length – gibt die exakte Länge des Request-Bodys in Bytes an.
  • Transfer-Encoding – der Body wird in Chunks übertragen. Jeder Chunk beginnt mit seiner Größe in Hexadezimal, abgeschlossen mit einem Chunk der Größe 0.

RFC 7230 ist eindeutig: Wenn beide Header vorhanden sind, darf Content-Length nicht verarbeitet werden. Aber was passiert, wenn Front-End und Back-End diese Regel unterschiedlich auslegen – oder wenn einer von beiden den Transfer-Encoding-Header nicht erkennt, weil er minimal manipuliert wurde? Genau da liegt das Problem.

Die drei klassischen Angriffsklassen (HTTP/1.1)

CL.TE – Front-End liest Content-Length, Back-End liest Transfer-Encoding

Das Front-End liest den Content-Length-Header und leitet eine definierte Menge an Bytes weiter. Das Back-End erwartet chunked encoding – und liest dabei mehr, als das Front-End weitergeleitet hat. Der überschüssige Inhalt bleibt im Back-End-Socket und wird an die nächste eingehende Anfrage angehängt.

POST / HTTP/1.1
Host: example.com
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED

TE.CL – Front-End liest Transfer-Encoding, Back-End liest Content-Length

Umgekehrt: Das Front-End verarbeitet den chunked Body vollständig. Das Back-End liest nur so viele Bytes, wie im Content-Length angegeben – der Rest bleibt im Socket und vergiftet die nächste Anfrage.

POST / HTTP/1.1
Host: example.com
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0

TE.TE – Beide lesen Transfer-Encoding, aber einer lässt sich austricksen

Beide Server unterstützen chunked encoding, aber einer kann dazu gebracht werden, den Header zu ignorieren, wenn er leicht manipuliert ist. Beispiele, die in der Praxis funktioniert haben (Kettle, 2019):

Transfer-Encoding: xchunked
Transfer-Encoding : chunked        ← Leerzeichen vor dem Doppelpunkt
Transfer-Encoding:[tab]chunked     ← Tab statt Leerzeichen
X: X[\n]Transfer-Encoding: chunked ← Newline-Injektion

Jede dieser Varianten kann dazu führen, dass genau einer der beiden Server den Header übersieht und die Desynchronisierung entsteht.

Was das T-Reqs-Paper (Jabiyev et al., ACM CCS 2021) als erste systematische wissenschaftliche Studie gezeigt hat: Smuggling ist nicht nur ein CL/TE-Problem. Durch grammar-based differential fuzzing von zehn populären Server- und CDN-Technologien (Apache, NGINX, HAProxy, Squid, Varnish, Akamai, Cloudflare, CloudFront u. a.) wurden Diskrepanzen in Teilen des Requests gefunden, die bisher niemand als Angriffsvektor auf dem Radar hatte: Request-Line-Manipulation, Chunk Extensions, Trailer-Felder. HRS ist ein System-Interaktionsproblem – jeder einzelne Server kann korrekt implementiert sein. Erst die Kombination zweier Server führt zur Diskrepanz.

HTTP/2: Das eigentliche Problem heute

HTTP/2 löst das CL/TE-Problem auf Protokollebene: Jeder Frame hat eine explizit kodierte Länge, kein Parsing von Body-Grenzen mehr. Was viele unterschätzen: Die meisten Systeme fahren vorne HTTP/2, hinten HTTP/1.1. Das Front-End konvertiert beim Weiterleiten – und genau dort entstehen neue Angriffsvektoren.

Kettle hat das 2021 auf der Black Hat dokumentiert (HTTP/2: The Sequel is Always Worse). Emil Lerner hat parallel und unabhängig dieselbe Angriffsklasse entdeckt.

  • H2.CL: Ein HTTP/2-Request enthält einen Content-Length-Header, der in HTTP/2 keine Bedeutung hat. Beim Downgrade auf HTTP/1.1 übernimmt das Back-End diesen Wert und liest damit mehr oder weniger als vorgesehen.
  • H2.TE: Transfer-Encoding: chunked wird in HTTP/2-Headern mitgeschickt, obwohl es in HTTP/2 keine Funktion hat. Beim Downgrade landet es im HTTP/1.1-Request an das Back-End und erzeugt dort die Desynchronisierung.
  • Header-Injection: HTTP/2-Header-Werte können CRLF-Sequenzen enthalten, die beim Downgrade in separate HTTP/1.1-Header aufgespalten werden. Damit lassen sich beliebige interne Header injizieren – inklusive Authorization, X-Forwarded-For oder proprietärer Back-End-Header.
Aus eigener Praxiserfahrung: H2.CL und H2.TE sind heute im Pentest fast häufiger zu finden als klassisches HTTP/1.1-Smuggling. Der Grund ist einfach: Viele Teams migrieren das Front-End auf HTTP/2, lassen das Back-End aber auf HTTP/1.1 – und prüfen dabei die Header-Transformation nicht ausreichend.

Client-Side Desync: Angriff ohne klassische Infrastruktur

2022 hat Kettle auf der Black Hat eine weitere Angriffsklasse vorgestellt: Client-Side Desync (CSD). Der fundamentale Unterschied zu allem bisher: Es braucht keine klassische Front-End/Back-End-Architektur. Stattdessen wird der Browser des Opfers selbst zur Waffe.

  • CL.0-Angriffe: Manche Server ignorieren den Content-Length-Header bei bestimmten Endpoints vollständig – zum Beispiel bei GET-Requests auf statische Assets. Schickt ein Angreifer einen Cross-Origin-Request mit einem Body an solch einen Endpoint, verarbeitet der Browser den Body, der Server ignoriert ihn. Was übrig bleibt, vergiftet den Verbindungs-Pool des Browsers. Der nächste legitime Request des Opfers läuft in den vergifteten Socket.
  • Pause-Based Desync: Apache und Varnish reagieren auf bestimmte taktische Pausen beim Senden des Requests mit Timeouts, die einen inkompletten Request im Puffer hinterlassen – ein weiterer Weg zur Desynchronisierung ohne klassischen CL/TE-Konflikt.

Erkennung: Timing statt Poisoning

Der naheliegende Ansatz – eine mehrdeutige Anfrage schicken und schauen, ob die nächste Anfrage korrumpiert wird – ist auf Live-Systemen zu riskant: Trifft ein anderer Nutzer den poisoned Socket, bekommt er die kaputte Antwort. Das ist Kollateralschaden, der in einem autorisierten Pentest nicht entstehen darf.

Die risikoarme Alternative ist Timeout-basierte Detection.

CL.TE Detection

POST /about HTTP/1.1
Host: example.com
Transfer-Encoding: chunked
Content-Length: 4

1
Z
Q

Das Front-End liest 4 Bytes (Content-Length) und leitet weiter. Das Back-End erwartet chunked encoding und wartet auf die nächste Chunk-Größe nach dem Z – die nie kommt. Ergebnis: Timeout von mehreren Sekunden. Kein anderer Nutzer wird getroffen, keine fremden Requests vergiftet.

TE.CL Detection

POST /about HTTP/1.1
Host: example.com
Transfer-Encoding: chunked
Content-Length: 6

0

X

Das Front-End sieht den abschließenden 0-Chunk und leitet weiter. Das Back-End liest nur 6 Bytes (Content-Length) und wartet auf das X – Timeout.

Aus eigener Praxiserfahrung: Dieser Timeout ist das Signal. Mehrere Sekunden Verzögerung gegenüber der normalen Response-Zeit, reproduzierbar, ohne dass andere Requests betroffen sind. Wichtig: Immer zuerst CL.TE testen. Würde bei TE.CL-Orientierung mit dem X-Ansatz begonnen und liegt tatsächlich CL.TE vor, landet das X im Back-End-Socket und trifft einen echten Nutzer.

Wichtig: Viele Scanner-Meldungen sind False Positives. Latenz durch Netzwerkprobleme, WAF-Interferenz oder Connection-Timeouts sehen einem Desync-Timeout täuschend ähnlich. Eine Meldung gilt erst als bestätigt, wenn sie manuell und reproduzierbar nachgewiesen ist. Standard-Tool im Pentest: HTTP Request Smuggler (Burp-Extension von PortSwigger).

Was ein Angreifer damit machen kann – und wie Findings bewertet werden

  • Reiner Desync-Nachweis → Medium/High. Nachgewiesene Desynchronisierung ohne direkte Exploitierbarkeit im aktuellen Kontext. Das Risiko besteht, lässt sich aber nicht unmittelbar in Zugriff übersetzen.
  • Interne Header exfiltrieren. Front-Ends fügen interne Header hinzu: X-Forwarded-For, proprietäre Auth-Header, Back-End-Routing-Informationen. Mit einer geschmuggelten Anfrage an einen reflektierenden Endpoint lassen sich diese Header auslesen. Bei New Relic hat Kettle 2019 so die internen Header Server-Gateway-Account-Id und Service-Gateway-Is-Newrelic-Admin extrahiert und damit vollständigen Admin-Zugriff auf die interne API erlangt.
  • Zugriffskontrolle umgangen (Admin-Pfad) → High/Critical. Viele Systeme verlassen sich darauf, dass das Front-End Sicherheitsprüfungen übernimmt. Eine geschmuggelte Anfrage erreicht das Back-End direkt, ohne diese Prüfungen. Wird ein Admin-Endpoint dadurch erreichbar: Critical.
  • Fremde Anfragen abgefangen / Cache vergiftet → Critical. Wenn ein poisoned Socket die nächste legitime Nutzeranfrage korrumpiert, lassen sich Session-Tokens abgreifen oder Nutzer auf manipulierte Endpoints umleiten. In Kombination mit einem Caching-Layer kann eine manipulierte Response für alle Nutzer gecacht werden, die dieselbe URL aufrufen. Kettle hat das auf der Login-Seite von PayPal demonstriert.

Gegenmaßnahmen

  • HTTP/2 end-to-end erzwingen. Wenn Front-End und Back-End beide HTTP/2 sprechen, entfällt das CL/TE-Problem. Der häufigste Fehler: HTTP/2 am Front-End, HTTP/1.1 am Back-End – genau dort entstehen H2.CL und H2.TE.
  • Ambiguous Requests ablehnen. Requests, die sowohl Content-Length als auch Transfer-Encoding enthalten, sollten vom Front-End verworfen werden, nicht weitergeleitet.
  • Header-Injection-Schutz. CRLF-Sequenzen in HTTP/2-Header-Werten müssen beim Downgrade auf HTTP/1.1 bereinigt werden.
  • Back-End-Verbindungen nicht wiederverwenden. Keine Connection Reuse = kein poisoned Socket. Performance-intensiv, aber wirksam.
  • WAF-Regeln für bekannte Obfuskationstechniken. Transfer-Encoding-Varianten (xchunked, Whitespace-Manipulationen) sind auf WAF-Ebene erkennbar – sofern die WAF selbst korrekt implementiert ist. Amit Klein hat 2020 auf der Black Hat gezeigt, wie eine explizit für HRS-Schutz entwickelte Open-Source-WAF umgangen werden kann.
  • Nach dem Patchen prüfen. T-Reqs, ReqsMiner und HDHunter haben gezeigt, dass Smuggling-Diskrepanzen in Serverpaarungen entstehen, die individuell korrekt implementiert sind. Eine Lösung auf einer Seite löst das Problem nicht zwingend auf der anderen.

Quellen

  • James Kettle: HTTP Desync Attacks – Request Smuggling Reborn, Black Hat USA / DEF CON 2019: portswigger.net
  • James Kettle: HTTP/2: The Sequel is Always Worse, Black Hat USA 2021: portswigger.net
  • James Kettle: Browser-Powered Desync Attacks, Black Hat USA 2022: portswigger.net
  • James Kettle: HTTP 1.1 Must Die! The Desync Endgame, DEF CON 33, 2025: youtube.com
  • Jabiyev, Sprecher, Onarlioglu, Kirda: T-Reqs: HTTP Request Smuggling with Differential Fuzzing, ACM CCS 2021: swsprec.com
  • Zheng et al.: ReqsMiner, NDSS 2024: ndss-symposium.org
  • Mu et al.: HDHunter – The Silent Danger in HTTP, USENIX Security 2025: usenix.org
  • Amit Klein: HTTP Request Smuggling in 2020, Black Hat Webcast 2020
  • Martin Doyhenard: Response Smuggling, Black Hat USA 2021
  • Emil Lerner: HTTP Request Smuggling via Higher HTTP Versions, 2021

← Zurück zur Blog-Übersicht