IoT - Goat
Descripción
El Proyecto IoTGoat es un firmware deliberadamente inseguro basado en OpenWrt y mantenido por OWASP como una plataforma para educar a los desarrolladores de software y profesionales de ciberseguridad mediante pruebas de vulnerabilidades comúnmente encontradas en dispositivos IoT.
La maquina virtual de IoTGoat presenta las 10 principales vulnerabilidades del IoT de OWASP.
Dirección IP: 192.168.172.129
Sistema operativo: Linux
Dificultad: Media
Técnicas Vistas:
• Hardcoded user credentials compiled into firmware
• Insecure Network Services
• Information Leakage
• Cracking with John
• Unshadow passwd & shadow files
• Insecure Ecosystem Interfaces
• XSS
• Wireshark to sniff plaintext credentials
• Lack of Secure Update Mechanism
• Insecure Data Transfer and Storage
• Insecure Default Settings
• OWASP Firmware Security Testing Methodology
IoT Goat
En este writeup, les mostraré mis soluciones a este Laboratorio. Este Laboratorio ofrece diferentes maneras de iniciarse en el hacking de IoT. En mi caso, descargué el firmware precompilado IoTGoat-x86.img.gz para el análisis estático y también descargué IoTGoat-x86.vmdk para realizar pruebas dinámicas usando VMware.
Agradecimientos
Quiero agradecer a fen1x1a por compartirme esta guía práctica para la extracción y análisis de firmware de routers. Su documentación fue la base del procedimiento que muestro a continuación, donde se explica paso a paso cómo realizar el volcado del firmware desde un dispositivo físico utilizando un programador CH341A y herramientas como flashrom y binwalk.
Nota sobre el alcance y relación con IoTGoat
La guía que sigue documenta únicamente el proceso de extracción y análisis estático del firmware de un router TP-Link TL-WR840N. Este procedimiento se presenta como una sección independiente del laboratorio IoTGoat, aunque ambos trabajos están estrechamente relacionados por su enfoque en la seguridad de dispositivos IoT y firmware embebido.
En el caso de IoTGoat, yo partí de un firmware ya disponible (el archivo IoTGoat-x86.img.gz) y comencé el análisis directamente desde la fase de extracción con binwalk y exploración del sistema de archivos. Es decir, los pasos que se muestran aquí —desde la extracción con binwalk -Me y la inspección del contenido del firmware— son prácticamente los mismos que utilicé en el laboratorio de IoTGoat, solo que en ese caso no fue necesario extraer físicamente el firmware desde el hardware.
Extracción del firmware de un router - guía práctica (TP-Link TL-WR840N)
Requisitos previos:
- Sistema GNU/Linux con los siguientes paquetes instalados:
flashrom,binwalk. - Programador SPI: CH341A con pinzas de 8 pines (o equivalente).

- Equipo objetivo: router (en este caso: TP-Link TL-WR840N).

Preparación y localización de componentes
- Abre el router con cuidado y localiza el chip FLASH (EEPROM / SPI flash).

- Identifica pines útiles: UART (Tx/Rx/GND/Vcc) y pines SPI (CS, MISO, MOSI, SCLK, Vcc, GND).

Conexión del programador CH341A
- Coloca las pinzas en modo SPI y alinea el cable rojo con el pin CS del chip.
- Conecta GND entre programador y placa; confirma el voltaje (habitualmente 3.3 V).
- Si el CH341A no es detectado, revisa la orientación/posición de las pinzas y vuelve a intentar.



Precaución: una mala conexión puede corromper la lectura o dañar el chip. Toma medidas ESD.
Lectura de la ROM (volcado)
Volca la memoria a un archivo binario local:
1 | sudo flashrom -V -r firmware.bin -p ch341a_spi --progress |
Para verificar, si procede:
1 | sudo flashrom -V -v firmware.bin -p ch341a_spi |


Nota: si el dispositivo no detecta el CH341A, revisa la presión/orientación de las pinzas antes de volver a conectar.
Extracción y análisis estático con binwalk
Extrae el contenido y busca sistemas de archivos:
1 | binwalk -Me firmware.bin |
Mbúsqueda recursiva;eextrae automáticamente.- En Arch Linux puede aparecer
Failed to execute command sasquatch; la solución habitual es instalarsasquatchdesde AUR (actúa con precaución).



Búsqueda de credenciales y hashes
Revisa /etc, passwd.bak, shadow.bak, etc

Identifica el tipo de hash con hashid u otra herramienta.

Ejemplo de crack con hashcat (MD5crypt — modo 500):
1 | sudo hashcat -m 500 hash.txt /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt |

Acceso dinámico vía UART
Conecta un adaptador USB-TTL (CP2102, FTDI, Flipper Zero, etc.) a los pines UART y usa screen o minicom:
1 | screen /dev/ttyUSB0 115200 |
Prueba las credenciales encontradas o logins por defecto para obtener una consola.



Conclusión práctica
El proceso (localizar chip → conectar CH341A → volcar con flashrom → extraer con binwalk → inspeccionar credenciales → usar UART) permite trasladar un firmware cerrado a un entorno controlado para análisis estático y pruebas. En el TP-Link TL-WR840N estudiado se identificó un rootfs con BusyBox, un kernel obsoleto y hashes MD5crypt, lo que ejemplifica por qué muchos dispositivos IoT son riesgosos si no reciben actualizaciones.
IoT GOAT

IP de la Maquina
192.168.172.129
1. Credenciales de usuario incrustadas en el firmware (Hardcoded user credentials compiled into firmware)
Las credenciales por defecto o hardcodeadas en firmware permiten acceso inicial sin necesidad de explotación sofisticada. En dispositivos IoT esto es crítico: se convierten en una puerta de entrada para los ciberdelincuentes.
Lo primero que hacemos es descargar el firmware y extraerlo usando binwalk.

Una vez descargado el firmware lo descomprimimos.
1 | gunzip IoTGoat-x86.img.gz |

Ahora extraemos el sistema de archivos de la imagen del firmware con binwalk.
1 | binwalk -e IoTGoat-x86.img |


Como no está cifrado, podemos acceder al sistema de archivos. Una vez extraído el sistema de archivos procedemos a buscar los archivos donde se almacenan las contraseñas en Linux.
Buscamos el /etc/passwd y comprobamos que usuarios poseen una shell /bin/ash
1 | find . -name "passwd" |

Observamos que los usuarios root y iotgoatuser poseen una shell
1 | cat ./squashfs-root/etc/passwd |

Buscamos las contraseñas en el /etc/shadow
1 | find . -name "shadow" |

En este archivo encontramos las contraseñas hasheadas de los usuarios del sistema. Ahora vamos a identificar el tipo de hash para intentar crackearlas.
Identificamos el tipo de hash
1 | hash-identifier |

Ahora procedemos a crackear ambos hashes con john usando un diccionario especial de Seclist el cual descubrí que la botnet Mirai uso con las contraseñas predeterminadas comunes de los dispositivos IoT, que se encuentra en la siguiente ruta en mi sistema: /usr/share/seclists/Passwords/Malware/mirai-botnet.txt
En este caso el diccionario tiene un formato de user:pass y a nosotros solo nos interesa la contraseña, así que vamos a usar awk para filtrar únicamente por la contraseña
1 | cat /usr/share/seclists/Passwords/Malware/mirai-botnet.txt |

1 | cat /usr/share/seclists/Passwords/Malware/mirai-botnet.txt | awk '{print $2}' > mirai-botnet-pass.txt |

Ahora tenemos el diccionario listo, para proceder necesitamos 2 archivos a los cuales tenemos acceso: /etc/passwd y /etc/shadow. Debemos guardar ambos en archivos de texto.
1 | cat ./_IoTGoat-x86.img.extracted/squashfs-root/etc/passwd > passwd.txt |


Una vez guardados vamos a usar una herramienta propia de John llamada unshadow para unir ambos archivos, este debe llevar un orden especifico, de lo contrario nos guardara mal el archivo. Primero va el passwd y luego el shadow.
1 | sudo unshadow passwd.txt shadow.txt > unshadow.txt |

Una vez listo el archivo debe quedarnos así:

Ahora si procedemos a craquearlo con John usando la lista personalizada de contraseñas que creamos
1 | sudo john -w=mirai-botnet-pass.txt unshadow.txt |

Obtenemos la contraseña para el usuario iotgoatuser.
Descifrando la contraseña root
El diccionario utilizado para descifrar las contraseñas no fue suficiente para la contraseña de root , así que descargué una herramienta llamada princeprocessor para generar contraseñas con diferentes palabras y utilicé el diccionario rockyou con la adición de la palabra iotgoat . Pero tarda bastante en generarlo y luego en crackearla la pass. Guía detallada que explica el uso de princeprocessor.
Para generar el diccionario empleamos la herramienta princeprocessor con el siguiente comando:
1 | **./pp64.bin "rockyou.txt" --pw-min 8 --pw-max 24 > iot_list.txt** |

Con la lista generada procedemos a obtener la clave del usuario root haciendo uso de John
1 | sudo john -w=iot_list.txt ../unshadow.txt --format=md5crypt-long |

Obtenemos la contraseña para el usuario root.
Para fines prácticos y ya que esto lo usare en una demo una vez obtenida la pass decidí crear un diccionario con las palabras que contiene la contraseña y generar un diccionario mas pequeño con princeprocessor para ahorrar tiempo.
1 | ./pp64.bin mini-dic.txt --pw-min 8 --pw-max 24 > iot_list.txt |


2. Servicios de Red Inseguros (Insecure Network Services)
Servicios de red innecesarios o inseguros que se ejecutan en el propio dispositivo, especialmente aquellos expuestos a Internet, que comprometen la confidencialidad, integridad/autenticidad o disponibilidad de la información, o que permiten el control remoto no autorizado.
Primero, ejecutamos nmap para descubrir los diferentes puertos TCP abiertos. En esta ocasión no hacemos uso del típico escaneo rápidonmap -p- --open -sS --min-rate 5000 -vvv -n -Pn IP_Victim -oG scanP Ya que genera perdida de paquetes y no encuentra 3 puertos, el 5000, 5515 y el 65534
1 | nmap -p- -sT 192.168.172.129 -vvv -oG scanP |

Empleamos una utilidad llamada extractPorts, que nos permite sacar la información mas relevante de la captura Grep de nmap y copiar los puertos directamente a la clipboard, por eso guardamos en ese formato, para poder aprovechar esta utilidad y agilizar nuestro trabajo. Fue hecha por s4vitar, Para usarla la deben incorporar en su .zshrc o .bashrc y instalar xclip.
1 | # Instalar xclip |

Ahora hacemos un escaneo detallado para esos puertos encontrados
1 | nmap -sCV -p22,53,80,443,5515,65534 192.168.172.129 -oN scanS |


Encontramos varios servicios interesantes.
Como el servicio SSH esta abierto, probamos entrar con las credenciales obtenidas
1 | ssh iotgoatuser@192.168.172.129 |

Nos conectamos con éxito.
Como dato extra en la carpeta SSHde nuestro usuario debemos crear un archivo de configuración llamado config que contenga las siguientes líneas:
1 | Host 192.168.172.129 |
De esta manera podremos ingresar por SSHal IoTGoat, de lo contrario nos dará un error debido a que ese protocolo es considerado inseguro.
El puerto 53 suele estar vinculado a servicios DNS. En este caso, el análisis del puerto 53 arrojó el servicio utilizado: dnsmasq 2.73 He encontrado con searchsploity en internet que este servicio presenta múltiples vulnerabilidades críticas relacionadas con el envenenamiento de DNS y ataques DoS
1 | searchsploit dnsmasq 2.73 |


Encontramos en el puerto80 HTTP una redirección al puerto 443 HTTPS , en el cual nos muestra una web

Al parecer solo podemos ingresar con el usuario root, del cual ya tenemos credenciales, pero esto lo dejaremos para mas adelante, continuemos analizando los otros puertos.
Servicio desconocido (puerto 5515) parece haber una backdoor debido a la info que nos mostro nmap. Usaremos netcatpara tratar de conectarnos
1 | nc nc 192.168.172.129 5515 |

Obtenemos una shell como root
Telnetd (puerto 65534) Siguiendo el mismo procedimiento, Usamosnetcat para conectarnos al último puerto.
1 | nc 192.168.172.129 65534 |

Obtenemos una conexión. Este servicio es considerado obsoleto e inseguro debido a que toda la información que se transmite viaja en texto plano, incluyendo credenciales de acceso. Las cuales pueden ser interceptadas con un ataque MITM (Man In The Middle).
Vamos a interceptar el trafico con wireshark para ver las credenciales de acceso. Seleccionamos la interfaz de red y procedemos a capturar todo el trafico de red.


Vemos que ahi entabla la conexión nuestra maquina con el IoTGoat en el cual nos iremos al ultimo paquete donde termina el 3-way handshake y analizar esa conexión.
Identificado ese paquete hacemos un seguimiento a la conexión que se establece por TCP y nos mostrara las credenciales en texto plano. Es por eso que no se debe usar Telnet.

3. Interfaces de ecosistema inseguras (Insecure Ecosystem Interfaces)
Interfaces web, API backend, nube o móviles inseguras, que permiten comprometer el dispositivo o sus componentes. Entre los problemas más comunes se incluyen la falta de autenticación/autorización, la falta o debilidad del cifrado y la falta de filtrado de entradas y salidas de texto.
Al revisar la estructura de datos, nos encontramos con un framework web MVC (Model-View-Controller) basado en Lua , el cual es usado para el portal web. Se revisaron manualmente varios archivos de configuración y no parecía haber mucha info interesante. decidí buscar por extension de archivos .lua .
Nos encontramos un archivo interesante el cual tiene el nombre del firmware en la siguiente ruta: /usr/lib/lua/luci/controller/iotgoat/iotgoat.lua
1 | find . -name "*.lua" |

Vemos la esturtura de archivos y al parecer se sirven desde esta ruta: /usr/lib/lua/luci
Revisamos el archivo iotgoat.lua y dentro vemos varias entradas interesantes, la que me llama la atención es cmdinject.

Decido buscar el archivo cmdinject
1 | find . -name "cmd*" |

Revisamos el archivo
1 | cat ./usr/lib/lua/luci/view/iotgoat/cmd.htm |

Parece que nos da acceso a una “pagina secreta de diagnostico para desarrolladores”, la cual al observar su contenido, nos proporciona una webshell como el usuario root.
Nos dirigimos a esa ruta en la web para comprobar, recordemos que la ruta a la que se hace referencia en el iotgoat.lua es admin-iotgoat-cmdjinyect

Obtenemos una webshell como el usuario root.
Mientras navegaba por la web, encontré múltiples entradas de texto e intenté realizar ataques XSS. En la siguientes parte de la aplicación pude realizar ataque XSS:
https://IoTGoat_IP/cgi-bin/luci/admin/network/firewall/rules En el campo name .
1 | <script>alert("test");</script> |

Probe en otras entradas de texto pero no logre encontrar mas.
4. Actualizaciones Inseguras (Lack of Secure Update Mechanism)
Falta de capacidad para actualizar el dispositivo de forma segura. Esto incluye la falta de validación del firmware en el dispositivo, la falta de entrega segura (sin cifrar durante el tránsito), la falta de mecanismos anti-rollback y la falta de notificaciones de cambios de seguridad debidos a actualizaciones.
El firmware OpenWRT se puede actualizar o se le pueden instalar nuevos paquetes. En este paso, intenté encontrar diferentes CVE que afectaran a la seguridad del mecanismo de actualización. Durante la búsqueda, encontré múltiples vulnerabilidades críticas que afectan a OpenWRT.
La versión la podemos encontrar tanto en el github, también una vez ingresamos a la web nos muestra la versión y en la info del puerto 5000.



CVE’s encontrados en la siguiente pagina:
https://www.cvedetails.com/version/1306858/Openwrt-Openwrt-18.06.2.html

Vemos que el CVE-2020-28951 afecta al mecanismo de actualización, ya que un nombre malicioso proporcionado puede provocar una vulnerabilidad «after free» que posteriormente puede explotarse para cargar código arbitrario en la memoria. Además, el mecanismo de copia de seguridad no comprueba la integridad de los archivos.
5. Transferencia y almacenamiento de datos inseguros (Insecure Data Transfer and Storage)
Falta de cifrado o control de acceso a datos confidenciales en cualquier parte del ecosistema, incluidos los datos en reposo, en tránsito o durante su procesamiento.
Al revisar el sistema de archivos y filtrar por diferentes tipos de extensión de archivo, la que mostro resultados fue .db con la cual encontré un archivo llamado sensordata.db . La cual era un archivo de base de datos SQLite.
1 | find . -name "*db" |

Al revisar la base de datos vemos que los datos se almacenan sin cifrar y en texto plano.
1 | #Para abrir la base de datos |

6. Configuraciones por defecto inseguras (Insecure Default Settings)
Dispositivos o sistemas con configuraciones predeterminadas inseguras, como contraseñas por defecto fáciles de adivinar, servicios innecesarios habilitados, puertos abiertos o funciones administrativas expuestas. Muchas veces, los fabricantes no permiten al usuario cambiar o reforzar esas configuraciones, lo que deja al dispositivo vulnerable desde el primer momento en que se conecta a la red.
Conclusiones
La máquina IoTGoat no pretende ser el típico CTF para escalar privilegios hasta root, sino más bien un laboratorio didáctico que concentra múltiples fallos típicos en dispositivos IoT. Durante el análisis he podido corroborar vulnerabilidades sencillas y a la vez muy comunes de la lista OWASP Top 10 IoT facilitan desde exposición de información sensible hasta ejecución remota de código; esto la convierte en una herramienta excelente para practicar detección, explotación y evaluación de riesgos en dispositivos IoT. Más allá de explotar fallos puntuales, el valor real de IoTGoat está en mostrar patrones repetibles: configuraciones inseguras, gestión deficiente de actualizaciones y fallas en el diseño de autenticación/autorización que deben corregirse en cualquier despliegue real y que estan presentes en muchos dispositivos IoT de uso cotidiano.
Metodología de pruebas de seguridad del firmware de OWASP (OWASP Firmware Security Testing Methodology)
Se ejecutó la metodología de pruebas de seguridad de firmware de OWASP (OWASP Firmware Security Testing Methodology) hasta el enunciado 7. Para cada etapa se aplicaron las pruebas y procedimientos recomendados (identificación, extracción y análisis del firmware, revisión estática y dinámicas controladas).


¡Gracias por llegar hasta el final! Espero que este writeup te haya ayudado a comprender mejor las vulnerabilidades y técnicas que se emplean en dispositivos IoT, mediante este laboratorio de IoTGoat para que puedas aplicar lo aprendido en futuros escenarios.
Nos vemos en el próximo reto… ¡y recuerda, la mejor forma de aprender es practicando!
Happy Hacking!




