Como realizar fuzzing até crashar uma aplicação binária
Este tutorial faz parte do GUIA COMPLETO do professional em Segurança Ofensiva de Software, saiba mais.
Aula 25: Fuzzing
25.1: Resumo
Fuzzing é uma forma de análise de vulnerabilidade, sendo uma técnica comum e relativamente simples empregada para descobrir novas vulnerabilidades em aplicações binárias.
O processo consiste em:
- Enviar à aplicação vários casos de teste levemente anômalos (ou malformados).
- Monitorar a aplicação para identificar qualquer sinal de erro ou comportamento inesperado.
- O objetivo final é encontrar falhas que permitam executar código arbitrário (explorar a vulnerabilidade).
- Teste de Usuário: Roda o programa com muitas entradas normais para evitar que usuários encontrem erros.
- Fuzzing: Roda o programa com muitas entradas anormais (entradas que a aplicação não esperaria) para forçar um mau comportamento. O objetivo é encontrar erros exploráveis antes que um atacante o faça, a fim de corrigi-los.
- Baseado em mutação: Também chamado de "Dumb Fuzzing". Coleta amostras de dados normais (entradas válidas) e as embaralha ou modifica para criar entradas anômalas. Assume pouco ou nenhum conhecimento da estrutura da entrada.
- Baseado em Geração: Chamado de "Smart Fuzzing". Define novos testes com base em modelos da entrada e em formatos específicos que possam aumentar a probabilidade de gerar um erro, como no exemplo do nome do arquivo em uma requisição HTTP. Requer conhecimento da estrutura da entrada.
- Evolucionário: Gera entradas baseadas na resposta da aplicação. O sistema tenta aprender sobre o comportamento do programa para evoluir os testes.
- Decisão de Parada: Em métodos baseados em mutação, o fuzzer pode executar para sempre, gerando mutações infinitas sem encontrar um erro. É preciso decidir quando parar os testes.
- Identificação do Erro: Muitas aplicações possuem mecanismos de recuperação de erro (como tratamento de exceção), o que dificulta a identificação de um erro explorável. Por exemplo, um buffer overflow pode ser recuperado pela aplicação.
25.2: Desenvolvimento de código Fuzzing
Vamos construir um template de fuzzing do Spike para identificar uma vulnerabilidade na aplicação Xitami Web Server versão 2.5b4 para Windows XP.
A ferramenta Spike é utilizada como um interpretador para enviar dados malformados a servidores TCP. Ela utiliza scripts (Spike Scripts) para gerar e modificar variáveis de comunicação, permitindo ao testador guiar o processo de Fuzzing.
Primeiramente inicie a aplicação vulnerável em sua máquina alvo. Em seguida, na máquina Kali inicie a captura de pacotes com o Wireshark.
![]() |
Figura 1: Captura de pacotes TCP |
Acesse o servidor HTTP via navegador Firefox do Kali. Depois, aperte F5 para que o navegador solicite a atualização da página. No Wireshark você conseguirá identificar que o pacote foi capturado (Figura 1).
![]() |
Figura 2: Construído template de teste |
Com o modelo de requisição de atualização da página registrado pelo Wireshark podemos utiliza-lo como base para construir o template de fuzzing do Spike (Figura 2).
![]() |
Figura 3: Teste conexão |
Antes de elaborar um template completo, teste se o básico está funcionando (Figura 3). Para executar o script de fuzzing utilize do comando: generic_send_tcp ip_alvo porta script.spk 0 0
![]() |
Figura 4: Template de fuzzing do Spike |
Identificado o funcionamento visualizando um pacotes das requisições enviadas, construa um template para realizar fuzzing. Para esta aplicação vamos variar 8 strings com o comando s_string_variable() (Figura 4).
![]() |
Figura 5: Crash na aplicação |
Identificado crash na aplicação ao executar a fuzzing variable de número 7. Como são 8 de 0 a 7 então o erro se dá na s_string_variable referente a "If-Modified-Since:" (Figura 5). Utilizando o software Immunity, mencionado em aulas anteriores, é possível visualizar que o crash foi causado pela string ""DAV:displayname" from scope()".
![]() |
Figura 6: Reconstrução template |
No Wireshark é certo que apareceu centenas de requisições. Então para filtrar menos requisições, o template foi reconstruído com apenas uma fuzzing variable (Figura 6).
![]() |
Figura 7: Realizando fuzzing |
Reinicie o Wireshark e realize o fuzzing (Figura 7).
![]() |
Figura 8: Identificando causa do crash |
A requisição que causou o crash foi identificada no Wireshark (Figura 8). No caso o crash ocorre após o primeiro caractere de "espaço" na string de "If-Modified-Since:" .
![]() |
Figura 9: Código e envio entrada maliciosa para a aplicação |
Agora podemos construir um script simples em python para enviar essa entrada maliciosa identificada e confirmar o disparo do erro na aplicação alvejada (Figura 9). Note que para evitar o error "TypeError: a bytes-like object is required, not 'str' " utilize python 2.7 em vez de python 3.
A partir de agora você consegue desenvolver um exploit para explorar a vulnerabilidade de Buffer Overflow na aplicação. Caso não consiga desenvolver, pesquise no Exploit-db alguns exemplos.
Próxima aula, clique aqui.