Rückblick: Die Grundlage
In Teil 1 haben wir HTTP Request Smuggling als eine Art „Missverständnis“ zwischen Proxy und Backend erklärt. Der Angreifer baut seinen Request so, dass Proxy und Backend unterschiedlich interpretieren, wo der Request endet – und dadurch wird ein zweiter Request eingeschleust.
Jetzt gehen wir tiefer rein:
- Welche Header sind schuld?
- Welche Varianten gibt es?
- Wie sieht so ein Request genau aus?
Die beiden Stars: Content-Length & Transfer-Encoding
- Content-Length (CL)
- Gibt die Länge des HTTP-Bodys in Bytes an.
- Beispiel:
Content-Length: 20
→ Es folgen genau 20 Bytes.
- Transfer-Encoding (TE)
- Sagt, wie der Body übertragen wird.
Transfer-Encoding: chunked
bedeutet: Der Body wird in „Chunks“ gesendet. Jeder Chunk beginnt mit seiner Länge in Hex.- Ende des Bodys: ein Chunk mit Länge 0 (
0\r\n\r\n
).
Beide Header sind für sich genommen harmlos. Das Problem: Was passiert, wenn beide gleichzeitig im Request stehen?
Warum das Chaos entsteht
Nicht alle Systeme verarbeiten Header gleich:
- Manche bevorzugen Content-Length.
- Manche bevorzugen Transfer-Encoding.
- Manche versuchen, beide zu interpretieren → Rezept für Chaos.
Wenn Proxy und Backend unterschiedliche Regeln haben, „sehen“ sie verschiedene Requests. Das ist der Kern von HTTP Request Smuggling.
Drei Hauptvarianten
1. CL.TE – Proxy nutzt Content-Length, Backend nutzt Transfer-Encoding
ASCII-Skizze:
[Proxy-Sicht] [Backend-Sicht]
+---------------+ +---------------+
| CL=13 | | TE=chunked |
| Body: abc... | | Body: chunk |
| Ende Request | | 0 = Ende |
+---------------+ | Neuer Request |
+---------------+
Beispiel-Request:
POST / HTTP/1.1
Host: victim.com
Content-Length: 13
Transfer-Encoding: chunked
0
GET /admin HTTP/1.1
Host: victim.com
- Proxy liest:
Content-Length: 13
→ denkt, Request ist beendet. - Backend liest:
Transfer-Encoding: chunked
→ sieht nach dem0
einen neuen Request (GET /admin
).
Ergebnis: Der Angreifer schmuggelt /admin
durch.
2. TE.CL – Proxy nutzt Transfer-Encoding, Backend nutzt Content-Length
ASCII-Skizze:
[Proxy-Sicht] [Backend-Sicht]
+---------------+ +--------------------+
| TE=chunked | | CL=4 |
| Body: 4\r\nABCD\r\n | Body: ABCD\nGET... |
| 0\r\n\r\n | | Rest → neuer Body |
| Ende Request | | (Request „verschmiert“) |
+---------------+ +--------------------+
Beispiel-Request:
POST / HTTP/1.1
Host: victim.com
Transfer-Encoding: chunked
Content-Length: 4
4
ABCD
0
GET /admin HTTP/1.1
Host: victim.com
- Proxy liest: „Ah, chunked.“ Er verarbeitet brav
ABCD
und denkt: Request fertig. - Backend liest: „CL=4.“ Es nimmt
ABCD
+ die nächsten Zeilen (GET /admin
) als Body. - Ergebnis: Request wird verschoben/vermischt – das kann zu Cache Poisoning führen.
3. TE.TE – beide nutzen Transfer-Encoding, aber unterschiedlich
ASCII-Skizze:
[Proxy-Sicht] [Backend-Sicht]
+---------------+ +-----------------+
| TE=chunked | | TE=chunked |
| Body: 0 | | Body: längerer… |
| Ende Request | | Request im Body |
+---------------+ +-----------------+
Das ist die komplizierteste Variante: Proxy und Backend nutzen beide TE, aber interpretieren die Chunks unterschiedlich – z. B. wegen Groß/Kleinschreibung oder doppelter Header.
Beispiel (verkürzt):
POST / HTTP/1.1
Host: victim.com
Transfer-Encoding: chunked
Transfer-Encoding: cow
0
GET /admin HTTP/1.1
Host: victim.com
- Proxy akzeptiert nur den ersten TE-Header → chunked.
- Backend akzeptiert den zweiten → ignoriert chunked.
- Ergebnis: Requests driften auseinander.
Visualisierung mit Zeitstrahl
Man kann sich das wie eine verschobene Zeitleiste vorstellen:
Proxy: |----Request A----| Request B
Backend: |---Request A--------|Request B
Die Systeme sind sich uneinig, wann Request A endet. Dadurch „rutscht“ ein Teil in den nächsten Request hinein.
Was passiert im echten Leben?
Session Hijacking
Angreifer kann Cookies einschleusen:
0
GET /profile HTTP/1.1
Host: victim.com
Cookie: session=attacker
→ Proxy sieht nur harmlosen Request, Backend nutzt aber manipulierten Cookie.
Cache Poisoning
Angreifer schmuggelt einen Request, der eine manipulierte Antwort im Cache ablegt. Alle nachfolgenden Nutzer bekommen die falsche Antwort.
WAF-Bypass
Eine Web Application Firewall (WAF) prüft nur, was der Proxy sieht – der eigentliche Angriff steckt aber im Teil, den nur das Backend interpretiert.
Tools zum Reproduzieren
Burp Suite
- Repeater: ermöglicht manuelles Basteln von Raw HTTP-Requests.
- HTTP Request Smuggler (Extension): automatisiert viele Payloads.
Manuell mit Netcat
printf 'POST / HTTP/1.1\r\nHost: victim.com\r\nContent-Length: 13\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nGET /admin HTTP/1.1\r\nHost: victim.com\r\n\r\n' | nc victim.com 80
Eigene Scripts
Mit Python und socket
lassen sich Requests exakt so senden, wie man will – ohne dass ein Browser oder eine Library „korrigierend eingreift“.
Warum Proxies besonders anfällig sind
- CDNs und Load Balancer (Akamai, Cloudflare, HAProxy, Nginx) verarbeiten Requests oft anders als Backend-Server (Apache, Node.js, Tomcat).
- In komplexen Infrastrukturen sind solche Unterschiede fast unvermeidlich.
- Ein Angreifer testet gezielt, wie Requests durch die Kette „wandern“.
Was du bis hier mitnehmen solltest
- HRS basiert auf uneinheitlicher Interpretation von Requests durch Proxy und Backend.
- Die drei Hauptvarianten:
- CL.TE (Proxy CL, Backend TE)
- TE.CL (Proxy TE, Backend CL)
- TE.TE (beide TE, aber verschieden interpretiert)
- Mit widersprüchlichen Headern kann ein Angreifer Requests „einschmuggeln“.
- Folgen: Session Hijacking, Cache Poisoning, WAF-Bypass.
Schreibe einen Kommentar