Solución del CTF Fetch the Flag 2022: Not So Smart Fridge
Antonio Gomes
10 de noviembre de 2022
0 minutos de lectura¡Gracias por jugar Fetch con nosotros! Felicidades a los miles de jugadores que participaron en Fetch the Flag CTF. Y muchas gracias a los Snykers que crearon, probaron y documentaron los desafíos.
Este desafío de Fetch the Flag CTF comienza con una cálida bienvenida y toda la información necesaria sobre nuestro flamante Smart Fridge Ultra SFU-3000. Emocionante, ¿no?
Isaac Asimov predijo una vez: «Se pueden almacenar comidas completas o semipreparadas en el refrigerador, listas para comer. El equipo de cocina podrá preparar “comidas automáticas”, calentar agua y hacer café». Y aquí estamos, usando este refrigerador para pedir productos e incluso reproducir música. ¡Es increíble!

Bueno, era emocionante hasta que descubrí que la función Music no estaba disponible. Y la función Settings para actualizar el firmware del refrigerador estaba rota, así que no había forma de actualizarlo desde pistache/0.0.3.20220107 a la versión más reciente. Al menos conocemos la versión del firmware, lo que nos ayudará a identificar la bandera y resolver este desafío.

Guía paso a paso
Después de acceder a la página web de nuestro Smart Fridge Ultra SFU-3000 —y decepcionarnos con sus capacidades reales—, al ir a Settings descubrimos que el firmware es pistache/0.0.3.20220107. Para quienes no conocen pistache, es un framework HTTP y REST moderno para C++, lo cual es útil porque nos da pistas sobre el software detrás de la página web del desafío.
Con esta información, podemos usar Snyk Intel Vulnerability Database para buscar problemas de seguridad relacionados con pistache/0.0.3.20220107. Al buscar pistache, encontramos que Pistache tiene una vulnerabilidad de recorrido de rutas que afecta la versión del firmware de nuestro refrigerador: 0.0.3.20220107. Es una buena noticia, porque podemos intentar explotarla con el comando sugerido a continuación en la PoC de Snyk.

Al ejecutar curl --path-as-is, curl no eliminará las secuencias /../ de la ruta completa. Además, esto nos permitirá obtener los resultados que se muestran a continuación, que prueban que logramos recuperar la lista de usuarios con acceso al sistema para aprovechar la vulnerabilidad de recorrido de rutas y que tenemos una carpeta llamada doc.
Al acceder a la ruta de la carpeta doc, obtendremos un documento de la API de Swagger que nos permitirá identificar los endpoints disponibles de nuestra aplicación web (por ejemplo, v1/system/flag/{flag}). En este punto, ya sabemos que estamos ante una aplicación web que usa pistache como binario de C++.

¿Qué sigue? Aprovecharemos proc de Linux. Más específicamente, /proc/self/exe, que apunta literalmente al proceso que se está ejecutando, que en este caso es el binario de la aplicación web Pistache. Para hacerlo, ejecutamos el siguiente comando:
Esto nos permitirá descargar el binario de Pistache. Tendremos que hacer ingeniería inversa del binario para averiguar cuál es la bandera. Primero, tendremos que descargar una herramienta de ingeniería inversa de software; en este caso, usaré Ghidra (también disponible para usuarios de MacOS mediante brew).
Con Ghidra, crearé un proyecto nuevo e importaré el binario .exe que descargamos antes.

Por fin llegamos a la parte emocionante del desafío: ¡averiguar cómo es esta bandera! En Ghidra, filtraremos los resultados por «flag». Así descubriremos que hay un método llamado checkFlag, cuyo contenido podemos ver en la imagen de abajo, en la ventana Decompile: checkFlag - (exe).

Al revisar la ventana decompilada, podemos ver que la bandera debe tener 70 caracteres:
if lVar4 == 0x46. La condición definida en el código original indica que lVar4 contiene la longitud de la bandera ingresada, mientras que 0x46 equivale a 70 en decimal.

Si se cumple la condición anterior, length == 70, veremos que se llama a otro método llamado checkIndexes.

checkIndexes, como vemos en las imágenes de arriba y de abajo, espera una cadena de la bandera que proporciona el programa, un vector con varios índices y un carácter — '7' en la imagen de arriba.

¿Qué significa? Que cada llamada a checkIndexes valida un carácter en las posiciones de cada n índices para determinar si la cadena de la bandera es válida. La lógica consiste en llamar a todos los checkIndexes; si todos pasan, significa que identificamos correctamente la bandera. Para averiguar cuál es, podemos investigar el archivo desensamblado e intentar convertir cada variable local_* de hexadecimal a decimal para determinar la posición

{13, 22, 29, 39,40, 45, 59} corresponde a la lista de índices en los que aparece el carácter `5` en la bandera. Ahora construimos la bandera:
Otra forma de identificar todos los índices de cada vector asignado es mediante un script (consulta el código). Para hacerlo, exportaremos el programa como archivo C/C++, eliminaremos todo lo demás y tomaremos en cuenta únicamente el método checkFlag y agregaremos un script para analizarlo, convertir las variables local_* de hexadecimal a decimal y determinar los índices de cada carácter hasta reconstruir la bandera.

Más inteligente que un refrigerador
En este desafío, aprendimos a usar Snyk para identificar una vulnerabilidad de recorrido de rutas en una aplicación web de C++, acceder y descargar el binario del proceso en ejecución, analizarlo con ingeniería inversa usando Ghidra y averiguar la bandera al analizar el binario decompilado. ¡Divertido!
Eso es todo. Espero que hayas disfrutado nuestros desafíos y gracias por participar en Snyk CTF 2022. ¿Quieres saber cómo encontramos las demás banderas? Visita nuestra página de soluciones de Fetch the Flag para descubrir cómo lo hicimos.



