Fuzz testing: del fallo a un informe reproducible

Prepara un informe de fuzz testing que otro ingeniero pueda reproducir: compilación, entrada, comando, resultados, responsable y verificación de la corrección.

Ernest Bursa

Ernest Bursa

Founder · · 10 min de lectura
Man inspecting a board at a workbench beside a closed laptop

Un informe útil de un fallo detectado mediante fuzz testing reúne la entrada que provoca el fallo, la compilación exacta del programa, el comando, el entorno y el fallo observado. Registra con qué fiabilidad se reproduce, quién se encarga de investigarlo y qué falta por averiguar sobre su impacto en la seguridad. Cuando el parche esté listo, conserva los resultados de repetir el caso con ese parche.

Conviene preparar ese traspaso antes de dedicar otra tarde a generar entradas. Una carpeta de archivos que provocan fallos puede dejar a quien los recibe con preguntas básicas: ¿qué ejecutable los produjo? ¿Se produce el fallo fuera del proceso de fuzzing? ¿Se compiló el programa con un sanitizador que detecta errores de memoria? ¿Qué resultado permitiría dar el fallo por corregido?

Los consejos de Chris Wellons sobre las pruebas con AFL++ volvieron al debate de Hacker News, observado el 2 de noviembre de 2026. El artículo es del 5 de febrero de 2025: una guía técnica anterior ha despertado de nuevo interés. Su enfoque práctico sirve como punto de partida para otra pregunta: ¿cómo conviertes un hallazgo en una tarea que otra persona pueda retomar?

El flujo que sigue es una propuesta para traspasar la investigación dentro de un equipo pequeño de ingeniería. Se apoya en la documentación de AFL++ y ClusterFuzz. No describe una campaña de fuzzing que hayamos realizado, y el ejemplo ilustrativo del analizador de documentos no corresponde a una vulnerabilidad descubierta.

Conserva el experimento antes de simplificarlo

Guarda suficiente contexto para reconstruir la ejecución que falló. La entrada importa, pero también el ejecutable, el código de pruebas, la configuración y las observaciones que permiten interpretarla.

El harness, o código de pruebas, introduce las entradas generadas en la función o el programa que se quiere probar. Registra su revisión junto a la del programa. Si alguien cambia cómo inicializa un analizador o cómo le pasa un búfer, la misma entrada puede poner a prueba un experimento distinto.

Guarda la entrada original en una ubicación con acceso restringido y añade al informe una referencia estable. Conserva la salida pertinente antes de sustituir los binarios o reconstruir el entorno. Incluye la plataforma, el compilador, las opciones de compilación, la configuración del sanitizador y las opciones de ejecución que sepas que se utilizaron. Indica qué datos faltan en lugar de reconstruirlos de memoria.

Supongamos que un código de pruebas ficticio para un analizador de documentos falla al recibir un archivo guardado. «El analizador se bloquea con este adjunto» deja abiertas varias posibilidades. El archivo podría revelar un defecto del programa, el código de pruebas podría invocar incorrectamente al analizador o podría hacer falta una opción concreta de ejecución para observar el fallo. La primera nota debe conservar lo ocurrido sin decantarse antes de tiempo por una explicación.

Wellons analiza dos problemas del código de pruebas dentro del ámbito que aborda: C/C++ con código fuente disponible sobre Linux con glibc. Son la persistencia de estado entre iteraciones del modo persistente y los búferes de entrada sobredimensionados que ocultan a AddressSanitizer algunas lecturas fuera de límites. Estos ejemplos justifican revisar el propio experimento. No implican que debas copiar todas las opciones del compilador a una tecnología distinta.

Evita que la única copia de una entrada sensible sea un adjunto de una incidencia pública. Un caso generado puede ser inocuo, pero una investigación también puede incluir documentos reales, rutas internas o salida de diagnóstico. Decide quién necesita acceso y guarda los archivos donde esas personas puedan recuperarlos. Un enlace que el siguiente ingeniero no puede abrir sigue siendo un traspaso incompleto.

Haz que el comando de reproducción funcione en otro entorno

Las instrucciones de reproducción deben permitir al siguiente ingeniero ejecutar el caso previsto sin adivinar las convenciones de tu entorno local. Escribe el comando junto con su directorio de trabajo, la entrada necesaria y las variables de entorno pertinentes.

El flujo de corrección de ClusterFuzz facilita el caso de prueba que desencadena el fallo y la compilación, y registra la línea de comandos y las variables de entorno importantes. Su documentación advierte de que esas variables pueden ser necesarias para reproducir el fallo. Es un modelo útil aunque tu equipo utilice otra herramienta.

Al traspasar la investigación, identifica el binario mediante una referencia estable de la compilación y la revisión del código fuente. Explica si el programa lee un archivo, la entrada estándar u otra interfaz. Indica cómo obtener o compilar el ejecutable. Sustituye las rutas propias de tu máquina por ubicaciones documentadas solo después de comprobar que las instrucciones revisadas siguen describiendo la misma ejecución.

Separa la preparación de la ejecución. Si quien recibe el caso necesita una imagen de contenedor concreta, un directorio de datos de prueba o una configuración de compilación, indica ese requisito antes de las instrucciones de reproducción. No dejes un paso necesario de preparación enterrado en un mensaje antiguo del chat.

Después describe con precisión lo observado. «Falla» puede significar un diagnóstico del sanitizador, una señal del proceso, un tiempo de espera agotado o una salida inesperada. Conserva el diagnóstico pertinente e indica qué comportamiento esperabas. Una captura de pantalla puede ayudar a reconocer un resultado, pero no debe ser el único registro de un comando o error que haya que copiar y examinar.

Registra los intentos como observaciones. Si el caso se reproduce de forma intermitente, indícalo y describe las condiciones que probaste. Un único intento fallido de reproducción no demuestra que el hallazgo original careciera de validez. Asigna un experimento que pueda explicar la diferencia, como comparar la compilación original o comprobar el estado del código de pruebas.

Distingue la reducción del caso de prueba de la evaluación de seguridad

Reducir una entrada puede facilitar la investigación. Por sí solo, no demuestra que el fallo sea explotable ni que pueda alcanzarse en tu producto.

AFL++ documenta afl-tmin para minimizar casos de prueba. Conserva el caso original junto al reducido y registra cómo obtuviste este último. Repite la observación pertinente antes de utilizar el caso reducido como sustituto. El archivo más pequeño debe ayudar a explicar el fallo que investigas, no limitarse a provocar cualquier fallo.

La misma documentación advierte de que evaluar la explotabilidad puede requerir un trabajo considerable de depuración y análisis del código. Mantén esa distinción en el informe. «Se ha reproducido un fallo detectado por el sanitizador» es un resultado útil. «Se ha confirmado una vulnerabilidad explotable de forma remota» exige pruebas de mucho más que la detención del proceso.

En el ejemplo ficticio del analizador, las siguientes preguntas podrían ser si el código afectado está presente en la compilación distribuida, si los documentos no fiables pueden llegar hasta él y con qué privilegios se ejecuta el proceso de análisis. Son preguntas para investigar, no hechos establecidos sobre el ejemplo. Registra por separado la exposición conocida y las suposiciones.

La agrupación también debe servir para organizar la investigación. Varios archivos guardados o trazas de pila parecidas no bastan para determinar cuántas causas raíz distintas o vulnerabilidades explotables existen. Mantén enlaces entre las observaciones relacionadas y deja margen para revisar los grupos a medida que avance la investigación.

Si la investigación requiere un proceso de divulgación pública, utiliza tu programa de divulgación de vulnerabilidades. Las pruebas de reproducción ayudan en ese proceso; no determinan cuándo divulgar el hallazgo ni autorizan a publicar archivos sensibles.

Entrega un informe con un próximo experimento claro

El informe debe responder rápidamente a dos preguntas: ¿qué puede reproducir la siguiente persona y qué incertidumbre debe resolver después?

Puedes adaptar esta plantilla a tu sistema de seguimiento. Es una propuesta de registro, no un requisito de una herramienta. Utiliza enlaces a archivos de acceso restringido en lugar de pegarlo todo en la descripción.

Programa y revisión del código fuente:
Revisión del código de pruebas y punto de entrada:
Plataforma, compilador, opciones de compilación y configuración del sanitizador:
Entrada original y ubicación de los archivos:
Entrada reducida y método de reducción, si está disponible:
Comando de reproducción y directorio de trabajo:
Fallo observado y salida pertinente:
Comportamiento esperado:
Intentos de reproducción y resultados:
Exposición conocida e impacto pendiente de evaluar:
Responsable de la investigación y próximo experimento:
Revisión del parche, resultados de la nueva ejecución y prueba de regresión:

No necesitas todas las respuestas para crear un informe. Sí necesitas distinguir un campo vacío de una conclusión verificada. «Revisión del programa desconocida; se ha pedido a quien envió el informe la referencia de la compilación» comunica más que un estado categórico respaldado por pruebas incompletas.

La documentación de triaje de ClusterFuzz considera información útil para la investigación la fiabilidad de la reproducción, el tipo de fallo, la plataforma y los intervalos de regresión. Estos intervalos están disponibles para fallos que se reproducen de forma fiable. Tu registro puede conservar las mismas distinciones sin afirmar que has identificado el commit que introdujo el fallo.

Utiliza una tabla breve de decisiones para mostrar el siguiente paso:

Pruebas disponibles Próxima acción útil Conclusión pendiente
Entrada sin una compilación o un comando correspondientes Solicitar el contexto de reproducción que falta Si otro ingeniero puede repetir el fallo
Fallo reproducible en el entorno registrado Asignar la investigación de la causa y la exposición Impacto en la seguridad y alcance en el producto
Fallo intermitente Conservar los intentos e investigar las diferencias entre condiciones Por qué cambia la fiabilidad
Varios casos aparentemente relacionados Comparar los datos y mantener enlaces Número de causas raíz distintas
Parche sin resultados de una nueva ejecución Probar el caso registrado con la compilación corregida Si el fallo observado se ha corregido

Asigna el próximo experimento a una persona concreta. En el ejemplo del analizador, podría ser quien pueda comparar el comportamiento del código de pruebas con el punto de entrada en producción. El informe debe indicar qué comprobará y dónde registrará el resultado.

Si un hallazgo confirmado se atasca después por una decisión de compatibilidad o de publicación de una versión, el problema pasa a ser otro. Nuestra guía para escalar decisiones sobre correcciones de seguridad explica cómo asignar un responsable y una fecha de revisión a esa decisión.

Verifica el parche frente al fallo registrado

La referencia de un parche indica qué ha cambiado. Los resultados de volver a ejecutar el caso indican qué ocurrió al probarlo con ese cambio.

Conserva juntos la revisión que fallaba, la revisión corregida, la configuración, la referencia del caso de prueba y los resultados. Siempre que sea viable, incorpora el caso a tus pruebas de regresión para que los cambios futuros comprueben el comportamiento que corregiste. Registra el resultado esperado con suficiente claridad para que otro ingeniero entienda después por qué existe la prueba.

El flujo de corrección de ClusterFuzz describe cómo volver a probar los casos con compilaciones posteriores. Esa automatización pertenece a ClusterFuzz. Si tu equipo vuelve a ejecutar un caso manualmente o en otro sistema, registra el método y el resultado reales en lugar de adoptar la etiqueta de verificación de una herramienta.

Comprueba que el experimento no haya cambiado por accidente. Un resultado sin fallos después de desactivar el sanitizador pertinente o cambiar el código de pruebas puede responder a otra pregunta. Explica los cambios de configuración intencionados y cómo afectan a las conclusiones posibles.

En un fallo intermitente, describe la incertidumbre que queda y el periodo de observación o las pruebas adicionales que elegiste. No existe un número universal de intentos que demuestre que cualquier defecto de este tipo ha desaparecido. Del mismo modo, volver a ejecutar con éxito un caso permite afirmar algo sobre ese caso y esa configuración; no certifica que todo el analizador sea seguro.

Mantén juntos los resultados y el ciclo de vida del informe en Kit

Tu herramienta de fuzzing, el sistema de compilación, el depurador y los ingenieros producen las pruebas técnicas. Un sistema de seguimiento de informes ayuda a mantenerlas vinculadas a la investigación y a la comunicación sobre ella.

Los informes de seguridad de Kit admiten notas de reproducción, evaluaciones y estados del ciclo de vida como pendiente de aclaración, validado, resuelto y corrección verificada. Puedes conservar el resumen de reproducción y las referencias junto al informe mientras avanza el trabajo. Kit cifra en reposo los campos de texto de los informes, incluidos los pasos de reproducción; esa afirmación no se extiende a todos los archivos que puedas guardar en otros lugares.

El estado del ciclo de vida debe resumir el trabajo registrado. Antes de marcar un hallazgo como verificado, enlaza el resultado real de volver a ejecutar el caso y deja visibles los límites de su alcance. Kit no ejecuta AFL++, no minimiza un corpus de archivos que provocan fallos, no determina la explotabilidad ni ejecuta tus pruebas de regresión.

Empieza por el próximo hallazgo que ya esté pendiente de atención. Comprueba si otro ingeniero puede obtener la entrada, identificar la compilación, ejecutar el comando y entender el fallo observado. Completa lo que falte, define el próximo experimento y conserva su resultado junto al informe. Así tu equipo tendrá una investigación concreta que continuar.

Artículos relacionados

Prueba Kit durante 30 días.

Contratación, informes de seguridad y formación en una sola cuenta, para equipos donde nada de eso es un trabajo a tiempo completo. 30 días gratis, con tarjeta. Cancela antes de que termine y no pagas nada.

Empieza gratis