Fuzzing y testing en sistemas de control industrial
¿Qué es el fuzzing?
Se conoce como fuzzing o técnicas de fuzzing al conjunto de pruebas de caja negra que permiten descubrir errores en los programas o protocolos mediante la introducción de datos al azar, inválidos y malformados. El fin último de estas pruebas es provocar comportamientos inesperados, como fallos que lleguen a hacer que el dispositivo, aplicación o servicio, dejen de funcionar. Este tipo de pruebas permiten, de forma automática o semiautomática, detectar potenciales vulnerabilidades de una forma rápida. Además, en caso de disponer del código fuente, arreglar la vulnerabilidad será mucho más fácil. Las herramientas utilizadas para llevar a cabo estas pruebas se conocen con el nombre de fuzzers.
Diagrama de funcionamiento de un fuzzer
Todas estas herramientas deberán contar con al menos la siguiente estructura:
- Generador: responsable de crear los diferentes valores que serán enviados como parámetros de entrada al programa. Si se tiene en cuenta el entorno a la hora de generar los datos con los que realizar las pruebas, entonces será del tipo “smart fuzzer” o fuzzer inteligente; en cambio, si son totalmente aleatorios y no tienen en cuenta el entorno, hablaremos de tipo “dumb fuzzer”.
- Interfaz de entrega: este módulo es el encargado de recoger los datos del generador y enviárselos al sistema y por ello, esta interfaz estará fuertemente ligada al sistema donde se deseen realizar las pruebas. Por ejemplo, es posible que el sistema reciba la entrada como un paquete de red o sea la entrada de un fichero.
- Monitorización: el sistema de monitorización es una de las piezas fundamentales para que un fuzzer funcione correctamente, ya que será el encargado de detectar y buscar errores, así como determinar cuál puede ser crítico y explotable.
Fuzzing en sistemas de control
La detección de vulnerabilidades mediante fuzzing se realiza en base a pruebas altamente intrusivas que buscan causar inestabilidad en el sistema, comportamientos extraños o incluso la denegación total del mismo. Si ya en entornos corporativos el uso de este tipo de herramientas no está aconsejado, en entornos de preproducción o producción, teniendo en cuenta los requisitos de disponibilidad de cualquier sistema de control, este tipo de pruebas se deben hacer en un laboratorio controlado y debidamente aislado.Además, se ha de tener en cuenta que determinadas pruebas altamente intrusivas pueden estar restringidas por los fabricantes debido a que pueden hacer que el dispositivo quede inservible. Siempre que se vayan a realizar pruebas de fuzzing es conveniente contar con el apoyo del fabricante o desarrollador para conocer las limitaciones y fijar adecuadamente los alcances.
Ventajas y desventajas
Un fuzzer permite obtener resultados con poco esfuerzo, ya que puede probar miles de casos sin necesidad de interacción del usuario y extenderse durante un largo periodo de tiempo, lo que permite descubrir errores que de forma manual no sería posible debido al tiempo que sería necesario emplear. Gracias a todas las pruebas realizadas, se obtiene una imagen de la robustez y el rendimiento del sistema analizado.
A pesar del elevado número de pruebas, es muy probable que no se descubran todos los errores, ya que es posible que muchos solo se generen por una serie de parámetros específicos o por la lógica del propio programa. Hay que tener en cuenta que la configuración del fuzzer determinará los casos de prueba. En algunas ocasiones, analizar los errores y/o fallos generados por una cierta entrada puede ser una tarea muy complicada. Además, los programas complejos pueden requerir de un esfuerzo mucho mayor o de un fuzzer más evolucionado y costoso, que cuente con inteligencia.
Detección de vulnerabilidades
Actualmente existen diferentes fuzzers, algunos son de uso general y se adaptan a todo tipo de necesidades, en cambio otros son más específicos y están limitados por la tecnología y el protocolo que se desee analizar. Algunos de los más utilizados son:
- Peach: es el framework más conocido en la comunidad, ya que dispone de múltiples pruebas tanto para sistemas como para protocolos de red, incluyendo protocolos del mundo industrial (ej. Modbus, DNP3). Además, cuenta con bastante documentación para poder crear y modelar los diferentes tests que se deseen crear.
- Aegis: fuzzer inteligente centrado exclusivamente en protocolos industriales, actualmente soporta: DNP3, ModbusTCP e IEC104. Este proyecto ha permitido detectar múltiples vulnerabilidades 0-day en la implementación de soluciones SCADA a nivel internacional.
- Radamsa: fuzzer de propósito general, fácil de utilizar y que contiene gran cantidad de algoritmos de mutación para poder generar datos de entrada de forma aleatoria basados en números, cadenas o patrones. Además, es posible enviar los datos al sistema analizado en paquetes TCP/IP.
- Sulley: solución escrita en Python, permite generar estructuras de datos complejas para la generación de posibles parámetros de entrada al sistema. Dispone de componentes capaces de guardar los casos de prueba y detectar los posibles crashes.
Detección de vulnerabilidades mediante testing
Además de la detección de vulnerabilidades utilizando técnicas anteriormente descritas, es posible realizar pruebas de caja blanca si se conoce el código fuente o se tiene acceso a él. Este tipo de pruebas permiten detectar y mitigar potenciales vulnerabilidades que de otra forma llevarían mucho más trabajo y esfuerzo. En el mundo del desarrollo de software para TI está muy expandido el concepto de pruebas de software, incluso existen equipos exclusivos para realizar estas tareas (por ejemplo, los equipos de aseguramiento de la calidad –quality assurance-).
Si estas buenas prácticas de desarrollo de software se extendieran a los equipos de desarrollo del entorno TO, se detectarían y evitarían vulnerabilidades ocasionadas por el propio desarrollo y no por la configuración del dispositivo o del sistema.
Para realizar pruebas de caja blanca (ej. pruebas funcionales, flujos de control, pruebas unitarias) es necesario acceder al código fuente, lo cual permite también utilizar herramientas de análisis de código estático. Este tipo de soluciones son capaces de detectar tanto potenciales vulnerabilidades como aquellos fragmentos de código que se desvíen de las buenas prácticas y estándares del propio lenguaje, entre las que se pueden identificar usuarios y contraseñas embebidos, puertas traseras o excepciones no controladas, entre otras.
A diferencia de la detección de vulnerabilidades mediante fuzzing, que se debe hacer de forma controlada y en entornos de laboratorio ya que son mucho más agresivas e intrusivas, el análisis de código estático podría incluso llevarse a cabo sobre entornos de producción. A pesar de eso, estas últimas tienen como hándicap el acceso limitado al código fuente de los aplicativos, a pesar de que un acceso total permitiría mitigar muchas de las vulnerabilidades que se descubren cada día en los sistemas de control industrial. Este acceso al código restringido hace que tengan que ser los propios desarrolladores o los equipos de seguridad de las compañías que desarrollen el software quienes realicen dicha tarea.
Las funcionalidades que permiten tanto el fuzzing como el análisis de código permiten identificar diferentes vulnerabilidades siempre que se disponga de un acceso y unos permisos adecuados. Sin embargo y pese a todo el esfuerzo que pueda poner el analista, este tipo de pruebas no son la panacea, y será necesario seguir realizando auditorias de seguridad tanto a los dispositivos como a los protocolos de red y las comunicaciones, de forma periódica y controlada.
Fuente: CERTSI
0 Comments:
Publicar un comentario
Gracias por dejar un comentario en Segu-Info.
Gracias por comentar!