
Uma ferramenta que cria automaticamente harnesses de fuzzing baseados em uma biblioteca
AutoHarness é uma ferramenta que gera automaticamente harnesses de fuzzing para você. Esta ideia surge de um problema atual no fuzzing de bases de código: grandes bases de código têm milhares de funções e trechos de código que podem estar bastante embutidos na biblioteca. É muito difícil ou às vezes até impossível para fuzzers inteligentes alcançarem esse caminho de código. Mesmo para grandes projetos de fuzzing como oss-fuzz, ainda há partes da base de código que não são cobertas pelo fuzzing. Portanto, este programa tenta aliviar esse problema em alguma medida, além de fornecer uma ferramenta que pesquisadores de segurança podem usar para testar inicialmente uma base de código. Este programa suporta apenas bases de código escritas em C e C++.
Este programa utiliza llvm e clang para libfuzzer, Codeql para encontrar funções e python para o programa geral. Este programa foi testado no Ubuntu 20.04 com llvm 12 e python 3. Aqui está a configuração inicial.
sudo apt-get update;
sudo apt-get install python3 python3-pip llvm-12* clang-12 git;
pip3 install pandas lief subprocess os argparse ast;
Siga o procedimento de instalação do Codeql em https://github.com/github/codeql. Certifique-se de instalar as ferramentas CLI e as bibliotecas. Para meus testes, armazenei ambas as ferramentas e bibliotecas em uma única pasta. Finalmente, clone este repositório ou baixe um lançamento. Aqui está a saída do programa após executar no nginx com o modo de múltiplos argumentos definido. Este é o comando que usei.
python3 harness.py -L /home/akshat/nginx-1.21.0/objs/ -C /home/akshat/codeql-h/ -M 1 -O /home/akshat/autoharness/ -D nginx -G 1 -Y 1 -F "-I /home/akshat/nginx-1.21.0/objs -I /home/akshat/nginx-1.21.0/src/core -I /home/akshat/nginx-1.21.0/src/event -I /home/akshat/nginx-1.21.0/src/http -I /home/akshat/nginx-1.21.0/src/mail -I /home/akshat/nginx-1.21.0/src/misc -I /home/akshat/nginx-1.21.0/src/os -I /home/akshat/nginx-1.21.0/src/stream -I /home/akshat/nginx-1.21.0/src/os/unix" -X ngx_config.h,ngx_core.h
Resultados:
Definitivamente é possível aumentar o sucesso depurando ainda mais a compilação e adicionando mais arquivos de cabeçalho e mais. Observe que o projeto nginx não possui objetos compartilhados após a compilação. No entanto, este programa possui um recurso que pode converter executáveis PIE em bibliotecas compartilhadas.
A forma atual implementada no programa para fazer fuzzing de funções com múltiplos argumentos é usando o fuzzing data provider. Há algumas melhorias a fazer nesta integração; no entanto, acredito que posso incorporar este recurso com estruturas de dados. Um problema que encontro ao codificar isso é com codeql e structs aninhadas. Torna-se especialmente difícil sem escrever várias consultas que variam para cada função. Em resumo, esta funcionalidade precisa de mais trabalho. Também estava pensando em uma solução simples usando protobufs.
Usando codeql, é possível gerar um grafo de fluxo de controle que mapeia como os parâmetros de uma função são inicializados. Usando essa informação, podemos criar um harness melhor. Outra forma é procurar implementações para a função que existem na biblioteca e usar essa informação para fazer uma estimativa fundamentada de uma implementação da função como harness. Os problemas que tenho atualmente com isso são gerar os grafos de fluxo de controle com codeql.
Posso criar um programa simples que executa todos os harnesses e detecta quaisquer falsos positivos comuns usando ASAN. Além disso, posso criar uma nova interface que executa todos os harnesses de uma vez e exibe suas estatísticas.
Se você encontrar algum bug neste programa, por favor crie uma issue. Tentarei encontrar uma correção. Além disso, se tiver ideias sobre novos recursos ou sobre como implementar melhorias de desempenho ou as funcionalidades planejadas atuais, por favor crie um pull request ou uma issue com a tag (contribution).
Esta ferramenta gera alguns falsos positivos. Primeiro, analise os crashes e veja se é um bug válido ou se é apenas um bug de implementação. Além disso, você pode ativar o modo de depuração se algumas funções não estiverem compilando. Isso ajudará a entender se há alguns arquivos de cabeçalho que estão faltando ou problemas de ligação. Se o projeto em que você está trabalhando não possui bibliotecas compartilhadas, mas um executável, certifique-se de compilar o executável no formato PIE para que este programa possa convertê-lo em uma biblioteca compartilhada.