
Fuzzer HTTP/1 basato su grammatiche con capacità di mutazione
T-Reqs (Two Requests) è un fuzzer HTTP basato su grammatica scritto come parte del paper intitolato "T-Reqs: HTTP Request Smuggling with Differential Fuzzing" presentato ad ACM CCS 2021.
BibTeX del paper:
@inproceedings{ccs2021treqs,
title={T-Reqs: HTTP Request Smuggling with Differential Fuzzing},
author={Jabiyev, Bahruz and Sprecher, Steven and Onarlioglu, Kaan and Kirda, Engin},
booktitle={Proceedings of the 2021 ACM SIGSAC Conference on Computer and Communications Security},
pages={1805--1820},
year={2021}
}
T-Reqs serve per fuzzare server HTTP inviando richieste HTTP mutate con versioni 1.1 e precedenti. Ha tre componenti principali: 1) generazione degli input, 2) mutazione degli input generati e 3) consegna degli stessi al/i server target.
Una grammatica CFG fornita al fuzzer viene utilizzata per generare richieste HTTP. Come mostrato nell'esempio di grammatica sotto, adattato per il fuzzing della request line, ogni componente della request line e i possibili valori per ciascuno sono specificati esplicitamente. Questo ci permette di generare richieste valide con varie forme di request line e anche di trattare ogni componente della request line come un'unità separata dal punto di vista della mutazione.
'<start>':
['<request>'],
'<request>':
['<request-line><base><the-rest>'],
'<request-line>':
['<method-name><space><uri><space><protocol><separator><version><newline>'],
'<method-name>':
['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'],
'<space>':
[' '],
'<uri>':
['/_URI_'],
'<protocol>':
['HTTP'],
'<separator>':
['/'],
'<version>':
['0.9', '1.0', '1.1'],
'<newline>':
['\r\n'],
'<base>':
['Host: _HOST_\r\nConnection:close\r\nX-Request-ID: _REQUEST_ID_\r\n'],
'<the-rest>':
['Content-Length: 5\r\n\r\nBBBBBBBBBB'],
Ogni componente può essere contrassegnata in due modi: mutable come stringa e mutable come albero (vedi la configurazione di esempio). Se un componente è mutable come stringa, allora un carattere casuale può essere cancellato, sostituito o inserito in una posizione casuale. Nell'esempio mostrato sotto (lato sinistro), l'ultimo carattere nella versione del protocollo (1) viene cancellato, la terza lettera nel nome del metodo (S) viene sostituita con R, e una barra in avanti viene inserita all'inizio dell'URI. Invece, se un componente è mutable come albero, allora un componente casuale può essere cancellato, sostituito o inserito in una posizione casuale sotto quel componente. L'esempio sotto (lato destro) mostra tre mutazioni ad albero applicate al componente request line: 1) method viene sostituito da protocol, 2) un URI extra viene inserito dopo l'URI corrente, e 3) il proto esistente viene cancellato.

Il fuzzer deve essere informato sulle preferenze dell'utente riguardo alla generazione e mutazione degli input. Più specificamente, la grammatica di input, i componenti mutabili, le preferenze di mutazione tra le altre cose devono essere specificati nel file di configurazione (vedi una configurazione di esempio).
Per poter riprodurre gli input generati e mutati in ogni iterazione, viene utilizzato un numero seed. In effetti, questo numero seed funge da seme per le generazioni di numeri casuali durante la formazione e mutazione di un input. A seconda di come questi seed vengono forniti al fuzzer, esso opera in una di queste due modalità: individuale e bulk. Nella modalità individuale, gli input vengono generati e mutati in base ai seed specificati da un utente. Nel comando sotto, viene specificato un singolo seed (es., 505). In alternativa, una lista di seed può essere specificata con l'opzione -f (vedere la pagina di aiuto per maggiori informazioni).
python3 main.py -i -c config -s 505
Mentre, nella modalità bulk (che è quella predefinita), parte da zero come valore seed e lo incrementa in ogni iterazione fino a raggiungere il numero finale. I numeri di inizio e fine possono essere personalizzati.
python3 main.py -c config
Condividiamo anche un Dockerfile per permettervi di eseguire il codice t-reqs. Potete eseguire i comandi sotto per iniziare:
# esegui il comando sotto nella directory che contiene il Dockerfile
docker build -t test/treqs .
# crea un container dopo aver costruito l'immagine usando il comando sopra
docker run -ti test/treqs bash
# esegui i comandi sotto nella shell docker avviata
cd t-reqs/
python3 code/main.py -c config -n -i -s90
HTTP Request Smuggling si basa su diversi comportamenti di parsing del body tra server dove un server utilizza l'intestazione Transfer-Encoding mentre l'altro preferisce l'intestazione Content-Length per decidere i confini di un corpo richiesta, o un server ignora un corpo richiesta, mentre l'altro lo elabora.
Per analizzare il parsing del body dei server in risposta a varie mutazioni in varie forme di una richiesta HTTP, abbiamo bisogno di avere un meccanismo di feedback installato su quei server per informarci sul comportamento di parsing del body. Un modo per installare un meccanismo di feedback su un server è eseguire il server in modalità reverse-proxy e fargli inoltrare le richieste a uno script "feedback provider" in esecuzione come servizio. Questo servizio misura la lunghezza del body nelle richieste ricevute e la salva per confrontarla successivamente con altri server.
Uno script di "feedback provider" di esempio è disponibile in questo repository. Tuttavia, questo script invia le informazioni sulla lunghezza del body di nuovo in una risposta assumendo che queste informazioni siano memorizzate sul lato client.
T-Reqs è concesso in licenza sotto licenza MIT.