
Una herramienta que crea automáticamente arneses de fuzzing basados en una biblioteca
AutoHarness es una herramienta que genera automáticamente harnesses de fuzzing para ti. Esta idea surge de un problema concurrente en el fuzzing de bases de código hoy en día: las bases de código grandes tienen miles de funciones y piezas de código que pueden estar incrustadas bastante profundamente en la biblioteca. Es muy difícil o a veces incluso imposible para los fuzzers inteligentes alcanzar esa ruta de código. Incluso para proyectos de fuzzing grandes como oss-fuzz, todavía hay partes de la base de código que no están cubiertas en el fuzzing. Por lo tanto, este programa intenta aliviar este problema en cierta medida, además de proporcionar una herramienta que los investigadores de seguridad pueden usar para probar inicialmente una base de código. Este programa solo admite bases de código escritas en C y C++.
Este programa utiliza llvm y clang para libfuzzer, Codeql para encontrar funciones, y python para el programa general. Este programa fue probado en Ubuntu 20.04 con llvm 12 y python 3. Aquí está la configuración 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;
Sigue el procedimiento de instalación para Codeql en https://github.com/github/codeql. Asegúrate de instalar las herramientas CLI y las bibliotecas. Para mis pruebas, he almacenado tanto las herramientas como las bibliotecas en una sola carpeta. Finalmente, clona este repositorio o descarga un release. Aquí está la salida del programa después de ejecutarlo en nginx con el modo de múltiples argumentos activado. Este es el comando que usé.
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 es posible aumentar el éxito depurando aún más la compilación y agregando más archivos de cabecera, etc. Ten en cuenta que el proyecto nginx no tiene ningún objeto compartido después de compilar. Sin embargo, este programa tiene una función que puede convertir ejecutables PIE en bibliotecas compartidas.
La forma actual implementada en el programa para fuzzear funciones con múltiples argumentos es usando fuzzing data provider. Hay algunas mejoras que hacer en esta integración; sin embargo, creo que puedo incorporar esta característica con estructuras de datos. Un problema que encuentro al codificar esto es con Codeql y estructuras anidadas. Se vuelve especialmente difícil sin escribir múltiples consultas que varían para cada función. En resumen, esta función necesita más trabajo. También estaba pensando en una solución simple usando protobufs.
Usando Codeql, es posible generar un gráfico de flujo de control que mapee cómo se inicializan los parámetros en una función. Con esa información, podemos crear un mejor harness. Otra forma es buscar implementaciones de la función que existan en la biblioteca y usar esa información para hacer una suposición fundamentada sobre una implementación de la función como harness. Los problemas que tengo actualmente con esto son generar los gráficos de flujo de control con Codeql.
Puedo crear un programa simple que ejecute todos los harnesses y detecte cualquier falso positivo común usando ASAN. Además, puedo crear una nueva interfaz que ejecute todos los harnesses a la vez y muestre sus estadísticas.
Si encuentras algún error en este programa, por favor crea un issue. Intentaré encontrar una solución. Además, si tienes alguna idea sobre nuevas funcionalidades o cómo implementar mejoras de rendimiento o las funcionalidades planificadas actuales, por favor crea un pull request o un issue con la etiqueta (contribution).
Esta herramienta genera algunos falsos positivos. Primero analiza los crashes y verifica si es un error válido o solo un error de implementación. Además, puedes habilitar el modo de depuración si algunas funciones no se compilan. Esto te ayudará a entender si te faltan algunos archivos de cabecera o si hay problemas de enlace. Si el proyecto en el que trabajas no tiene bibliotecas compartidas sino un ejecutable, asegúrate de compilar el ejecutable en forma PIE para que este programa pueda convertirlo en una biblioteca compartida.