
Fuzzer HTTP/1 baseado em gramática com capacidade de mutação
T-Reqs (Two Requests) é um Fuzzer HTTP baseado em gramática escrito como parte do artigo intitulado "T-Reqs: HTTP Request Smuggling with Differential Fuzzing" que foi apresentado no ACM CCS 2021.
BibTeX of the 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}
}
O T-Reqs é para fuzzing de servidores HTTP enviando requisições HTTP mutadas com versões 1.1 e anteriores. Ele tem três componentes principais: 1) gerar entradas, 2) mutar entradas geradas e 3) entregá-las ao(s) servidor(es) alvo.
Uma gramática CFG alimentada no fuzzer é usada para gerar requisições HTTP. Como a gramática de exemplo mostrada abaixo é adaptada para fuzzing da linha de requisição, cada componente da linha de requisição e os valores possíveis para cada um deles são explicitamente especificados. Isso nos permite gerar requisições válidas com várias formas da linha de requisição e também tratar cada componente da linha de requisição como uma unidade separada da perspectiva de mutação.
'<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'],
Cada componente pode ser marcado de duas formas: mutável por string e mutável por árvore (veja a configuração de exemplo). Se um componente é mutável por string, então um caractere aleatório pode ser deletado, substituído ou inserido em uma posição aleatória. No exemplo mostrado abaixo (lado esquerdo), o último caractere na versão do protocolo (1) é deletado, a terceira letra no nome do método (S) é substituída por R, e uma barra é inserida no início da URI. Enquanto isso, se um componente é mutável por árvore, então um componente aleatório pode ser deletado, substituído ou inserido em uma posição aleatória sob aquele componente. O exemplo abaixo (lado direito) mostra três mutações de árvore aplicadas ao componente da linha de requisição: 1) method é substituído por protocol, 2) uma URI extra é inserida após a URI atual, e 3) o proto existente é deletado.

O fuzzer deve ser informado sobre as preferências do usuário em relação à geração e mutação das entradas. Mais especificamente, a gramática de entrada, os componentes mutáveis, preferências de mutação entre outras coisas devem ser especificadas no arquivo de configuração (veja um exemplo de configuração).
Para ser capaz de reproduzir as entradas geradas e mutadas em cada iteração, um número de semente é usado. Na verdade, esse número de semente serve como uma semente para gerações de números aleatórios durante a formação e mutação de uma entrada. Dependendo de como essas sementes são alimentadas no fuzzer, ele executa em um desses dois modos: individual e em lote. No modo individual, as entradas são geradas e mutadas com base nas sementes especificadas por um usuário. No comando abaixo, uma única semente (i.e., 505) é especificada. Alternativamente, uma lista de sementes poderia ser especificada com a opção -f (veja a página de ajuda para mais).
python3 main.py -i -c config -s 505
Enquanto isso, no modo em lote (que é o padrão), ele começa do zero como valor de semente e o incrementa a cada iteração até que o número final seja alcançado. Os números inicial e final podem ser personalizados.
python3 main.py -c config
Também estamos compartilhando um Dockerfile para que você possa executar o código do t-reqs. Você pode executar os comandos abaixo para começar:
# run the command below under the directory which has the Dockerfile
docker build -t test/treqs .
# create a container after you built the image using the command above
docker run -ti test/treqs bash
# run the commands below in the started docker shell
cd t-reqs/
python3 code/main.py -c config -n -i -s90
O Smuggling de Requisições HTTP depende de comportamentos diferentes de análise de corpo entre servidores onde um servidor usa o cabeçalho Transfer-Encoding enquanto o outro prefere o cabeçalho Content-Length para decidir os limites de um corpo de requisição, ou um servidor ignora um corpo de requisição, enquanto o outro o processa.
Para analisar a análise de corpo dos servidores em resposta a várias mutações em várias formas de uma requisição HTTP, precisamos ter um mecanismo de feedback instalado nesses servidores para nos informar sobre o comportamento de análise de corpo. Uma maneira de instalar um mecanismo de feedback em um servidor é executar o servidor no modo proxy reverso e fazê-lo encaminhar requisições para um script "provedor de feedback" executando como um serviço. Esse serviço mede o comprimento do corpo nas requisições recebidas e o salva para compará-lo posteriormente com outros servidores.
Um script de exemplo de "provedor de feedback" está disponível neste repositório. No entanto, este script envia as informações de comprimento do corpo de volta em uma resposta assumindo que essas informações são armazenadas no lado do cliente.
T-Reqs é licenciado sob a licença MIT.