OWASP FSTM, etapa 7: Análisis dinámico
Tabla de contenidos
La fase de análisis dinámico se define como el estudio del dispositivo en ejecución en un entorno real o emulado. Para ello, se analiza el dispositivo en su conjunto, tratando de profundizar en las posibles vulnerabilidades que se hayan encontrado en fases anteriores (imprescindibles para realizar hacking de dispositivos IoT).
Para esta fase, se puede utilizar un entorno de emulación que permita ejecutar el firmware sin necesidad del hardware original, como se muestra en el artículo de emulación de firmware. Este método permite un análisis en mayor profundidad del sistema cuando no se ha encontrado un puerto de depuración en el hardware, ya que, en muchos casos, los frameworks de emulación permiten conectar un depurador como GDB para controlar el flujo de ejecución. Alternativamente, y si no se han encontrado puertos hardware de depuración disponibles, se puede utilizar el hardware original para el análisis dinámico. Esta opción es más sencilla de implementar y es menos propensa a fallos, pero el análisis que permite es menos profundo que con la emulación. Si se han encontrado puertos de depuración en el hardware, también será posible conectar un depurador al puerto y controlar la ejecución en el hardware original.
Los objetivos de estudio durante el análisis dinámico deben ser establecidos según los hallazgos de las fases anteriores, especialmente las de análisis del firmware y del sistema de ficheros. La información recabada hasta el momento es esencial para la ejecución del análisis dinámico: provee de una idea general del funcionamiento del sistema e indica los puntos débiles y los servicios más vulnerables.
Existen una gran cantidad de pruebas que se pueden ejecutar dependiendo del tipo de servicios que se encuentren disponibles y, en algunos casos, esta fase del análisis puede asemejarse a un pentesting tradicional, con la salvedad del conocimiento adquirido en las fases anteriores.
En este artículo se presentarán algunas de las técnicas y herramientas que son de utilidad en el análisis dinámico.
1. Depuración con emulación
En caso de haber logrado construir un entorno de emulación para el firmware del dispositivo, una de las técnicas más interesantes de análisis dinámico consiste en utilizar un depurador software para controlar el flujo de ejecución y observar el estado del sistema en cada momento. En el caso de la emulación completa del sistema, estas técnicas suelen estar dirigidas al estudio de las funciones del bootloader o elementos del kernel, cuyo análisis por separado es especialmente complejo.
Para la emulación completa del sistema se dispone de múltiples herramientas y frameworks, basados mayoritariamente en el emulador QEMU, que permiten controlar los dispositivos conectados al sistema, sus entradas, sus salidas y el flujo de ejecución. En muchos casos, también permiten conectar un cliente de GDB con el que observar el estado del sistema en cada momento.
Entre las principales alternativas se encuentran QEMU, Renode, Unicorn, Qiling y Firmadyne, que se tratan en el artículo 6 de esta serie.
El conocido y popular depurador GDB puede ser utilizado en integración con todas estas herramientas de depuración para observar detenidamente la ejecución de programas y sistemas completos. Para el software emulado, el framework o sistema de emulación habitualmente ofrece la posibilidad de ejecutar un servicio de gdbserver al que conectar un cliente, incluso de forma remota.
Las técnicas de depuración con emulación pueden combinarse con fuzzing para ejecutar ataques sobre elementos del bootloader, el kernel o el sistema operativo, lo que resulta especialmente complejo en un pentesting tradicional. Tambíen son muy útiles para obtener el firmware descifrado o desempaquetado: se identifica el punto de arranque del sistema (script init o similar), se instala un breakpoint antes del inicio, se ejecuta el arranque hasta el breakpoint y se extrae la imagen de firmware de la memoria con el depurador.
2. Depuración con puertos físicos
También, en algunos casos, el propio hardware original tiene disponibles puertos físicos de depuración a través de una interfaz JTAG o UART para los desarrolladores y que no fueron desactivadas o protegidas correctamente en los dispositivos en producción.
A través de la interacción con interfaces JTAG, habitualmente puede encontrarse la capacidad de leer y escribir contenidos a las memorias ROM y RAM, de forma que se puede observar el estado del sistema. Si se conocen las correspondencias en memoria de los dispositivos que requiere el firmware, se puede interactuar con él a través de los dispositivos, aunque esto requeriría un trabajo previo de estudio y automatización para ejecutarlo en tiempo real.
Las interfaces UART de depuración pueden ofrecer acceso al bootloader y permitir la interacción con él a través de un terminal y, en combinación con el acceso a la memoria, puede utilizarse para controlar el flujo de ejecución.
3. Pentesting tradicional
Una vez que el firmware se encuentra en ejecución, ya sea en un entorno emulado o en el hardware original, pueden aplicarse técnicas y metodologías tradicionales de pentesting, el llamado pentesting hardware, como el reconocimiento de red con herramientas como nmap, búsquedas de vulnerabilidades en los servicios descubiertos y búsquedas de vulnerabilidades web.
Existen multitud de herramientas y técnicas que pueden ser aplicadas en esta fase dependiendo de los servicios que se descubran en el sistema. Al igual que ocurre con el resto de las tareas, los resultados de las fases previas en un análisis pueden ser determinantes para seleccionar los objetivos prioritarios. Generalmente, se pueden utilizar técnicas como las siguientes:
- Reconocimiento de red: nmap es la herramienta por excelencia en este aspecto, ya que ofrece capacidades de descubrimiento de red con múltiples técnicas diferentes y a diferentes niveles de la pila TCP/IP. El resultado de este análisis es el listado de puertos abiertos en el dispositivo en ejecución y, con las extensiones de nmap habilitadas, también se pueden obtener datos sobre el sistema operativo, los servicios ejecutando en cada puerto y los nombres y versiones de los servidores.
- Descubrimiento de vulnerabilidades: a partir de las versiones de los servidores en ejecución y del sistema operativo, una búsqueda en bases de datos de vulnerabilidades y exploits, como la NVD (https://nvd.nist.gov) o exploit-db (https://www.exploit-db.com), puede ofrecer resultados útiles para la explotación.
- Pentesting web: En caso de encontrar un servicio web, que es un caso habitual en dispositivos IoT, este puede ser un objetivo interesante para la explotación. Los servicios web son sistemas complejos que pueden introducir bugs y vulnerabilidades en el sistema y para los que existen gran cantidad de herramientas y técnicas disponibles.
- Análisis de comunicaciones: Muchos dispositivos IoT disponen de servicios con protocolos especializados o con implementaciones particulares de un estándar y que son propios del fabricante. Es habitual que estos servicios contengan protocolos poco probados y que los servidores tengan vulnerabilidades no descubiertas. Utilizando el conocimiento ya adquirido del sistema como guía, un estudio exhaustivo de las comunicaciones no convencionales del dispositivo puede destapar sorpresas inesperadas.
- Explotación de vulnerabilidades: Una vez analizadas las posibles vulnerabilidades, deben realizarse las pruebas necesarias para confirmar su viabilidad. En el caso más favorable, se encontrarán exploits o pruebas de concepto preparadas para la explotación de la vulnerabilidad, de forma que estas puedan ejecutarse directamente o a través de frameworks como el conocido Metasploit. En la mayoría de los casos, sin embargo, las vulnerabilidades requerirán un trabajo de estudio más profundo, para lo cual puede ser útil volver a la fase 5 de análisis del sistema de ficheros para estudiar los ejecutables y elementos del firmware en detalle.
Para el análisis de servicios web empotrados, la guía de OWASP puede resultar particularmente útil, así como suites y herramientas ampliamente conocidas como Burp, ZAP o DirBuster. También conviene tener en cuenta el entorno en el que se ejecuta la web: elementos como la autenticación de usuarios y la ejecución de tareas en backend dependen del sistema que ya se ha estudiado y pueden dirigirse las pruebas hacia objetivos sospechosos.
En general, aunque el firmware y, especialmente, el software de los dispositivos IoT puede estar desactualizado en comparación con otro tipo de sistemas, los aspectos más vulnerables suelen encontrarse en las implementaciones propias del fabricante, que habitualmente no se encuentran tan probadas como el resto de los componentes donde el hardware hacking obtiene frutos comúnmente.
4. Fuzzing
El fuzzing es una técnica de búsqueda de vulnerabilidades que tradicionalmente se ha asociado a la validación y pruebas de software. En el contexto de la ciberseguridad es especialmente relevante porque permite automatizar las pruebas y encontrar errores que de otra forma hubiese sido más difícil. El fuzzing IoT se aplica a dispositivos inteligentes para encontrar errores de implementación en el código fuente.
Existen diferentes técnicas de fuzzing con diferentes resultados y objetivos:
- Fuzzing de aplicación (application fuzzing): Consiste en la modificación de datos de entrada para localizar fallos en el código. Es la modalidad de fuzzing más conocida y se suele implementar sobre el código fuente (análisis de caja blanca) en las pruebas de software. En el contexto de la ciberseguridad se suele emplear también en análisis de caja negra o gris para encontrar posibles fallos en los sistemas a través de la ingesta de datos (como desbordamientos de buffer).
- Fuzzing de formato (file format fuzzing): Además de modificar los datos de entrada, esta técnica de fuzzing modifica el formato, generando paquetes y ficheros mal formados. Por ejemplo, alterar bits de las propiedades de un mp4 o un pdf. Es muy útil para identificar fallos de implementación no alineados con el estándar.
- Fuzzing de protocolo (protocol fuzzing): Puede actuar creando paquetes modificados para un protocolo de comunicación específico o como un proxy, modificando los paquetes y reenviándolos al destino. Es análogo al fuzzing de formato, pero especializado en un protocolo de comunicaciones (TCP, Bluetooth…).
Existen numerosas herramientas disponibles para realizar ataques de fuzzing como AFL++, FormatFuzzer, CryptoFuzz. Una de las herramientas más potentes es ClusterFuzz, desarrollada por Google y con la que han detectado, a fecha de mayo 2022, 25.000 bugs en sus productos y más de 36.000 bugs en 550 proyectos open source. Estas cifras ponen de manifiesto el potencial de este tipo de ataques automatizados y su importancia en el contexto de la ciberseguridad. En este contexto, el fuzzing de dispositivos IoT es una forma automatizada de encontrar defectos software en sistemas en modelo de caja negra.
5. Modificación del bootloader
Uno de los trucos conocidos para evitar al login manager y acceder directamente a un terminal con permisos de administrador es manipular los parámetros del kernel en el bootloader. Esta técnica se basa en aprovechar la falta de seguridad que algunos fabricantes pueden dejar en el arranque del dispositivo para acceder al script de arranque del bootloader y modificarlo para beneficio del auditor. Este mismo mecanismo puede utilizarse para cargar imágenes de firmware o u-boot modificadas, además de inspeccionar las funcionalidades de depuración habilitadas.
Dependiendo del sistema y del bootloader (información que puede haber sido obtenida en análisis previos) el acceso al terminal difiere, pero, en general, se requiere tener acceso a un puerto de depuración o tener un monitor y teclado conectados al dispositivo. Si es el caso, se suele poder acceder pulsando “códigos mágicos” o combinaciones de teclas específicas durante el arranque.
Si el bootloader no ha sido protegido correctamente, se mostrará un terminal con el que interactuar. Estas son algunas de las modificaciones interesantes que se pueden hacer en U-Boot:
- Para modificar los parámetros de arranque del bootloader, se debe modificar la variable de entorno bootargs, cuyos valores por defecto se encuentran almacenados en un fichero de configuración en texto. La variable bootargs suele estar definida de manera similar a la siguiente línea:
setargs=setenv bootargs console=${console} root=${nand_root} init=${init} loglevel=${loglevel}
Si se modifica el parámetro init, se puede obtener un terminal con permisos de administrador en el arranque del sistema.
setargs=setenv bootargs console=${console} root=${nand_root} init=/bin/bash loglevel=${loglevel}
También se puede modificar la misma variable con el mandato setenv, consultando previamente el resto de las variables:
#printenv #Consulta de variables
#setenv bootargs=console=ttyS0,115200 mem=63M root=<rootDevice> mtdparts=sflash:<partitionInfo> rootfstype=<fstype> hasEeprom=0 5srst=0 int=/bin/bash
#saveenv
#boot
- Mediante el terminal de bootloader, también se pueden cargar imágenes de U-Boot y escribirlas en memoria para obtener acceso como root. Para ello, puede utilizarse un servidor TFTP de la siguiente manera:
#setenv ipaddr 192.168.2.2 # IP local del dispositivo
#setenv serverip 192.168.2.1 #IP del servidor tftp
#saveenv
#reset
#ping 192.168.2.1 #check if network access is available
#tftp ${loadaddr} <ubootImage> #loadaddr tiene dos argumentos: la dirección de memoria en la que cargar el archivo y el nombre del archivo en el servidor TFTP
Tras modificar la IP local y establecer la del servidor TFTP externo que contiene la imagen, se accede al servidor con un cliente TFTP y se carga la imagen uImage-3.6.35 en la posición de memoria desde la que se carga en el siguiente arranque. Alternativamente, ubootwrite.py realiza el mismo proceso a través de una interfaz UART.
- Además, se pueden configurar funciones de depuración como logs, carga de kernels arbitrarios y arranque desde fuentes no confiables.
6. Modificación del firmware
En dispositivos que no comprueben apropiadamente el origen del firmware que ejecutan se pueden llevar a cabo ataques a su integridad, cargando una copia modificada que incluya vulnerabilidades, como un terminal con permisos de administrador en un puerto SSH.
Para ello, primero debe extraerse y analizarse el sistema de ficheros. El objetivo, en este caso, es obtener las herramientas necesarias para desempaquetar y empaquetar la imagen de firmware, al mismo tiempo que se analiza el proceso de arranque para localizar dónde modificar el firmware. La mejor forma de asegurar que el firmware siga ejecutándose sin problemas tras la modificación es evitar modificar el tamaño final de la imagen, por lo que conviene ser muy cuidadoso con los archivos que se modifican o eliminan.
Una vez localizado el modo de introducir modificaciones en el firmware, existen múltiples pruebas que pueden realizarse, de entre las cuales destaca la introducción de una puerta trasera o backdoor (por ejemplo, un terminal ssh con permisos de administrador que arranque en el inicio).
Uno de los mayores retos para esta prueba consiste en encontrar el toolchain correcto para la compilación del backdoor. Esto es diferente para cada arquitectura, y fabricante, pero, en la mayoría de los casos, se utilizan arquitecturas para las que la suite de gcc tiene compiladores disponibles (MIPS, ARM…).
Una vez diseñado y compilado el backdoor, atendiendo a las restricciones de tamaño, se recomienda hacer una prueba en un entorno virtualizado con alguna de las herramientas del artículo 6 (por ejemplo, QEMU y chroot).
Una vez probado, se crea la nueva imagen de firmware con las herramientas de empaquetado y se sube como una actualización de firmware al dispositivo. Si el proceso de actualización y de arranque no está protegido debidamente, una variación de esta prueba puede dar como resultado un dispositivo con un backdoor instalado con el que continuar con el análisis dinámico, con acceso al usuario administrador.
7. Conclusiones
Existen multitud de técnicas y herramientas aplicables al análisis dinámico de dispositivos IoT. Muchas de ellas coinciden con las técnicas y herramientas de un pentesting tradicional, por lo que se puede aprovechar muchas de estas habilidades. Sin embargo, otras de las técnicas, como la modificación de firmware o el uso de un depurador para controlar la ejecución en un entorno emulado, son específicas del análisis de firmware, por lo que abren aún más el abanico de posibilidades.
Es muy útil, por tanto, establecer objetivos claros antes de comenzar el análisis basándose en los resultados del análisis estático, de forma que se dirijan los esfuerzos a los componentes más probablemente vulnerables.
Referencias
- https://github.com/scriptingxss/owasp-fstm
- https://securelist.com/dynamic-analysis-of-firmware-components-in-iot-devices/106901/
- https://www.opensourceforu.com/2018/09/dynamic-analysis-of-firmware-using-firmadyne/
- https://ics-cert.kaspersky.com/publications/reports/2022/07/06/dynamic-analysis-of-firmware-components-in-iot-devices/
- https://etutorials.org/Linux+systems/embedded+linux+systems/Chapter+9.+Setting+Up+the+Bootloader/9.5+U-Boot/
- https://u-boot.readthedocs.io/en/latest/usage/environment.html
- https://linux-sunxi.org/U-Boot/Configuration
Este artículo forma parte de una serie de articulos sobre OWASP
- Metodología OWASP, el faro que ilumina los cíber riesgos
- OWASP: Top 10 de vulnerabilidades en aplicaciones web
- Análisis de seguridad en IoT y embebidos siguiendo OWASP
- OWASP FSTM, etapa 1: Reconocimiento y búsqueda de información
- OWASP FSTM, etapa 2: Obtención del firmware de dispositivos IoT
- OWASP FSTM, etapa 3: Análisis del firmware
- OWASP FSTM, etapa 4: Extracción del sistema de ficheros
- OWASP FSTM, etapa 5: Análisis del sistema de ficheros
- OWASP FSTM etapa 6: emulación del firmware
- OWASP FSTM, etapa 7: Análisis dinámico
- OWASP FSTM, etapa 8: Análisis en tiempo de ejecución
- OWASP FSTM, Etapa 9: Explotación de ejecutables
- Análisis de seguridad IOT con OWASP FSTM
- OWASP SAMM: Evaluar y mejorar la seguridad del software empresarial
- OWASP: Top 10 de riesgos en aplicaciones móviles