El fuzzing es una técnica de pruebas que envía automáticamente entradas inesperadas al software para encontrar fallos. Esta página explica cómo funciona y cómo empezar con tu propio código (no cubre las pruebas sobre sistemas de otras personas).
Qué es el fuzzing
OWASP describe el fuzzing como una técnica de pruebas de software orientada a identificar errores, vulnerabilidades o comportamientos inesperados. Suministra automáticamente entradas no válidas, inesperadas o parcialmente no válidas, y observa si el programa se comporta mal. El glosario del NIST (citando el NIST SP 800-95) describe igualmente el fuzz testing como herramientas llamadas fuzzers que envían combinaciones de entradas a un objetivo de prueba para revelar cómo responde.
Su fortaleza es que hace pocas suposiciones sobre cómo debería comportarse el sistema. Las pruebas escritas a mano cubren solo los casos que alguien ha previsto. Un fuzzer puede encontrar puntos que fallan con entradas que nadie imaginó.
Cómo funciona
La mayoría de los fuzzers modernos están guiados por cobertura. Miden qué código se ejecuta, conservan las entradas que alcanzan código nuevo y las mutan para crear las siguientes. Así llegan más profundo en el programa que con entradas aleatorias. libFuzzer, de LLVM, está documentado como un motor de fuzzing evolutivo, guiado por cobertura y en el mismo proceso, que se enlaza con la biblioteca bajo prueba.
Herramientas habituales
| Herramienta | Objetivos principales | Notas |
|---|---|---|
| libFuzzer | C/C++ y otros (LLVM) | Se enlaza con el objetivo. Según su documentación, los autores originales pasaron al motor Centipede y ahora solo recibe correcciones de errores importantes |
| AFL++ | C/C++ y otros | Un fuzzer guiado por cobertura muy usado |
| Fuzzing integrado de Go | Go (1.18 o posterior) | Se ejecuta con go test -fuzz. Las entradas que fallan se guardan en testdata y las pruebas normales las reproducen |
| OSS-Fuzz | Software de código abierto | Servicio gratuito de fuzzing continuo de Google, que usa varios motores y sanitizers |
Un fuzz target de libFuzzer es una función (LLVMFuzzerTestOneInput) que recibe los bytes de entrada y su longitud. En Go escribes una función de prueba llamada FuzzXxx que recibe un *testing.F y añades entradas semilla con f.Add.
Cómo empezar con tu propio software
- Elige una función que analice entradas (un analizador de formato de archivo, un cargador de configuración, un manejador de protocolo)
- Escribe un fuzz target pequeño que simplemente pase la entrada a esa función. Mantenlo rápido y determinista, sin estado que se arrastre entre llamadas
- Añade algunas entradas válidas típicas como semillas
- Activa un sanitizer como AddressSanitizer y ejecuta durante un tiempo establecido (en Go,
-fuzztimedefine la duración) - Convierte cada entrada que falle en una prueba reproducible y consérvala como prueba de regresión tras la corrección
- Para seguir, ejecuta sesiones cortas en CI o, en el caso de código abierto, considera unirte a OSS-Fuzz
El fuzzing de Go tiene un límite de 1 segundo por ejecución, y la guía por cobertura funciona en AMD64 y ARM64. Consulta la documentación oficial para conocer los límites de tu entorno.
Haz fuzzing solo del software que gestionas
El fuzzing envía continuamente grandes volúmenes de entradas malformadas. Hacerlo contra un servicio o servidor que no tienes permiso para probar puede considerarse acceso no autorizado o interrupción del servicio. Limítalo al software que desarrollas o gestionas, en tu propio entorno.
Qué puede y qué no puede hacer
OWASP señala que el fuzzing complementa, pero no sustituye, la revisión manual del código y la depuración. También indica que los fuzzers tienden a encontrar errores simples y que, con pruebas de caja negra, es más difícil valorar el impacto de un hallazgo.
Por tanto, el fuzzing es fuerte para "dejar que una máquina busque formas en que el código se rompe", y débil frente a problemas de diseño como la falta de autorización. Para estos, como IDOR, confía en pruebas que verifiquen las reglas previstas.
Nota de este sitio: encontrar la entrada es la mitad del trabajo; consérvala como prueba de regresión
Lo importante no es solo ejecutar un fuzzer, sino guardar lo que encuentra como prueba de regresión. El fuzzing integrado de Go, que almacena una entrada que falla en testdata y la reproduce en las pruebas normales, sigue esta idea. Evita que un error corregido vuelva a aparecer tras un cambio posterior. Si tienes código que analiza entradas, un primer paso realista es hacer fuzzing de una sola función.
Fuentes (primarias)
- OWASP Community, "Fuzzing" — owasp.org (definición, características, límites)
- Glosario NIST CSRC, "fuzz testing" — csrc.nist.gov (fuente: NIST SP 800-95)
- LLVM, "libFuzzer" — llvm.org (cómo funciona, fuzz target, estado de mantenimiento)
- Go, "Fuzzing" — go.dev (Go 1.18 o posterior, cómo ejecutarlo, límites)
- Google, "OSS-Fuzz" — google.github.io (descripción general, motores compatibles). Las cifras de errores cambian con el tiempo, por lo que no se citan aquí. Para AFL++, consulta su documentación oficial para el uso actual