Las pruebas diferenciales , [1] también conocidas como fuzzing diferencial , son una técnica de pruebas de software que detecta errores al proporcionar la misma entrada a una serie de aplicaciones similares (o a diferentes implementaciones de la misma aplicación) y observar las diferencias en su ejecución. Las pruebas diferenciales complementan las pruebas de software tradicionales porque son adecuadas para encontrar errores semánticos o lógicos que no exhiban comportamientos erróneos explícitos como fallas o fallas de aserción. Las pruebas diferenciales también se denominan pruebas consecutivas.
Las pruebas diferenciales encuentran errores semánticos al usar diferentes implementaciones de la misma funcionalidad como oráculos de referencia cruzada , señalando diferencias en sus salidas sobre la misma entrada: cualquier discrepancia entre los comportamientos del programa en la misma entrada se marca como un error potencial.
Las pruebas diferenciales se han utilizado para encontrar errores semánticos con éxito en diversos dominios como implementaciones de SSL/TLS , [2] [3] [4] [5] compiladores de C , [6] implementaciones de JVM , [7] firewalls de aplicaciones web , [8] políticas de seguridad para API , [9] software antivirus , [4] [10] y sistemas de archivos . [11] Las pruebas diferenciales también se han utilizado para la generación automatizada de huellas dactilares a partir de diferentes implementaciones de protocolos de red . [12]
Las herramientas de prueba diferencial no guiadas generan entradas de prueba de forma independiente a lo largo de las iteraciones sin tener en cuenta el comportamiento del programa de prueba en las entradas anteriores. Este proceso de generación de entradas no utiliza ninguna información de las entradas anteriores y, en esencia, crea nuevas entradas al azar a partir de un espacio de entrada prohibitivamente grande. Esto puede hacer que el proceso de prueba sea muy ineficiente, ya que se deben generar grandes cantidades de entradas para encontrar un solo error.
Un ejemplo de un sistema de pruebas diferenciales que genera entradas sin guía es "Frankencerts". [2] Este trabajo sintetiza Frankencerts combinando aleatoriamente partes de certificados reales. Utiliza certificados sintácticamente válidos para probar violaciones semánticas de la validación de certificados SSL/TLS en múltiples implementaciones. Sin embargo, dado que la creación y selección de Frankencerts no se realiza de forma guiada, es significativamente ineficiente en comparación con las herramientas guiadas.
El proceso de generación de entradas guiadas tiene como objetivo minimizar la cantidad de entradas necesarias para encontrar cada error teniendo en cuenta la información sobre el comportamiento del programa para las entradas anteriores.
Un ejemplo de un sistema de prueba diferencial que realiza una generación de entrada guiada por cobertura específica del dominio es Mucerts. [3] Mucerts se basa en el conocimiento de la gramática parcial del formato de certificado X.509 y utiliza un algoritmo de muestreo estocástico para impulsar su generación de entrada mientras rastrea la cobertura del programa.
Otra línea de investigación se basa en la observación de que el problema de la generación de nuevas entradas a partir de entradas existentes se puede modelar como un proceso estocástico. Un ejemplo de una herramienta de prueba diferencial que utiliza un modelado de proceso estocástico de este tipo para la generación de entradas es la herramienta de Chen et al. [7] Realiza pruebas diferenciales de máquinas virtuales Java (JVM) utilizando el muestreo de Monte Carlo de cadena de Markov (MCMC) para la generación de entradas. Utiliza mutaciones personalizadas específicas del dominio aprovechando el conocimiento detallado del formato de archivo de clase Java.
NEZHA [4] es un ejemplo de una herramienta de prueba diferencial que tiene un mecanismo de selección de ruta orientado a la prueba diferencial independiente del dominio. Utiliza métricas específicas (denominadas diversidad delta) que resumen y cuantifican las asimetrías observadas entre los comportamientos de múltiples aplicaciones de prueba. Estas métricas que promueven la diversidad relativa del comportamiento observado del programa han demostrado ser efectivas para aplicar pruebas diferenciales de manera independiente del dominio y de caja negra.
Para aplicaciones como filtros de secuencias de comandos entre sitios (XSS) y verificación de nombres de host de certificados X.509, que se pueden modelar con precisión con autómatas de estados finitos (FSA), se pueden utilizar técnicas de aprendizaje de FSA basadas en contraejemplos para generar entradas que tengan más probabilidades de encontrar errores. [8] [5]
La ejecución simbólica [13] es una técnica de caja blanca que ejecuta un programa simbólicamente, calcula restricciones a lo largo de diferentes rutas y utiliza un solucionador de restricciones para generar entradas que satisfacen las restricciones recopiladas a lo largo de cada ruta. La ejecución simbólica también se puede utilizar para generar entradas para pruebas diferenciales. [12] [14]
La limitación inherente de las herramientas de prueba asistidas por ejecución simbólica (explosión de rutas y escalabilidad) se magnifica especialmente en el contexto de pruebas diferenciales donde se utilizan múltiples programas de prueba. Por lo tanto, es muy difícil escalar las técnicas de ejecución simbólica para realizar pruebas diferenciales de múltiples programas grandes.