Como lo mencionamos en el anterior post , este hacia parte de una serie de retos que jugamos con el equipo el pasado fin e semana, sin embargo hasta ahora era autorizado poner writeups.
Este evento es su séptima edición y es organizado por el equipo NYUSEC
Baby Rev — CSAW CTF
Descripción:
El reto Baby Rev planteaba la siguiente premisa:
“I stashed the flag under a rock. Still don’t get all the grumbling about ‘Security Through Obscurity!’”
La pista sugería que la flag estaba escondida bajo algún tipo de protección ligera, probablemente mediante algún tipo de codificación simple.
Proceso de Resolución:
1. Análisis Estático
El binario proporcionado fue identificado como un archivo ELF de 64 bits, lo que significa que debíamos trabajar en un entorno de Linux.
personalmente primera vez que lo hacia con un binario de este tipo :
Para comenzar, realizamos un análisis estático del binario utilizando objdump
para desensamblar las secciones del binario:
objdump -d baby_rev > babyrev.txt
En el desensamblado, encontramos una sección de código en la función init
que cargaba una serie de valores que parecían ser partes de la flag. Estos valores estaban en formato Base64 y se almacenaban en diferentes direcciones de memoria.
2. Análisis Dinámico con GDB
Para analizar la ejecución en tiempo real, cargamos el binario en GDB:
gdb baby_rev
Colocamos un punto de interrupción en la función main
para detener el programa al inicio:
break main run
Identificamos la dirección base del binario utilizando info proc mappings
. Con esta dirección, calculamos la dirección real de la función check_message
, la cual estaba encargada de validar la flag.
Colocamos un punto de interrupción en check_message
:
break *0x5555555554ba continue
Una vez detenido en esta función, examinamos el contenido de la memoria donde se almacenaban los fragmentos de la flag:
x/s 0x555555558040
allí podemos observa la posible flag en base 64 y confirmar la hipótesis del inicio del reto que posiblemente estaba en una codificación simple
dejando un lado los de reversing, puesto que mi cabeza iba a explotar por la complejidad de muchos de estos, opte por explorar los de la categoria web!
Playing on the Backcourts
Categoría: Web
Puntos: 484
Descripción:
- yadayada playing tennis like pong yadayada someone’s cheating yadayada at least the leaderboard is safe!
Al ingresar al sitio web se nos da un tablero y unas posibles tablas de posiciones.
Una vez lo diligenciabas y enviabas , empezaba un juego de ping pong
para el reto los organizadores nos entregaron un archivo Python con el código del servidor web (app_public.py
), que revela algunas rutas interesantes:
- Autenticación mediante cookies: El código verifica si una cookie de sesión coincide con un hash SHA256 específico. en este punto pensé que quizá había que robar la cookie del admin para obtener la flag
- Función
deep_eval()
: La ruta/get_eval
permite a los usuarios enviar expresiones en formato JSON que se evalúan con la funcióneval()
de Python. Esto es potencialmente peligroso ya que eval puede ejecutar código arbitrario en el servidor.
En este punto ya sabia que el juego de pingpong usaba flask y además en el código se logra observar la mención de el archivo de texto de tabla de lideres
Dado que el código usa eval()
para ejecutar expresiones arbitrarias, decidí probar si podemos aprovechar esta función para leer archivos del servidor.
Utilizamos Burp Suite para interceptar y modificar una petición POST y poner que se enviaba a la ruta /get_eval
, con la intención de leer el archivo leaderboard.txt.
ya teniendo presente que era flask, y necesitábamos leer un archivo , es decir el servidor posiblemente sea vulnerable a un SSTI , fui a uno de mis repositorios favoritos y busque payloads para SSTI que pudieran leer archivos https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinja2
una vez encontré el payload, arme la siguiente petición , la cual me facilito leer el archivo de tabla de lideres
payload enviado:
{
“expr”: “__import__(‘os’).popen(‘cat leaderboard.txt’).read()”
}
en uno de los datos del archivo que se logro leer aparecía la flag csawctf{5H1774K3_Mu5Hr00M5_1_fuX0R3d_Up_50n_0F_4_81207CH}
Este reto nos permitió confirmar la importancia de evitar el uso de eval()
con entradas de usuarios y si se hace siempre realizar una correcta sanitización de las entradas en aplicaciones web
Sigamos….
Mire un rato el reto de pwn Diving Into Null , no es mi categoría mas fuerte pero lo quise intentar un buen rato
El reto nos otorgó acceso a una shell restringida en un entorno similar a Docker/Kubernetes, con muchos comandos comunes como ls
, cat
, y cd
deshabilitados. Nuestro objetivo era explorar el sistema en busca de la flag usando métodos alternativos.
Lo que me funcionó:
- Explorar directorios con
echo
:
- Aunque los comandos tradicionales como
ls
no funcionaban, se pudo usarecho *
para listar directorios clave como/bin
,/dev
,/proc
,/run
, y/srv
.
Acceso a archivos del sistema:
- Se logró leer el contenido de archivos importantes como
/etc/passwd
, que confirmó la estructura básica de usuarios del sistema, pero no reveló nada relevante para encontrar la flag.
Explorar /run/secrets
:
Se detectó la existencia del directorio /run/secrets
, que suele contener información sensible en entornos restringidos, lo que sugirió que la flag podría estar oculta en este directorio.
Listar dispositivos en /dev
:
- Se identificaron varios dispositivos importantes, como
/dev/null
,/dev/stdout
,/dev/tty
, y otros dispositivos relacionados con flujos de entrada/salida.
Aunque no encontré la flag, el reto me permitió explorar un entorno restringido de manera creativa, usando comandos como echo
para listar archivos y leer contenido. El directorio /run/secrets
parecía ser la clave, pero podría requerir permisos especiales o técnicas avanzadas para acceder a la flag. entonces, hice lo que cualquiera hubiera hecho :
después de esto, quise nuevamente sentirme útil , así que me fui a ver la categoría de intro, el reto OSIRIS trivia
El reto nos planteaba una pregunta sobre el antiguo nombre de dominio del laboratorio OSIRIS de la NYU (Offensive Security, Incident Response, and Internet Security Lab). debíamos encontrar el dominio antiguo del laboratorio, excluyendo el protocolo de red, y poner la respuesta en el formato csawctf{}
.
parecía un reto de OSINT , y después de googlear unos minutos , y comprender la historia de los organizadores encontré el siguiente repositorio , en el cual se podía ver la siguiente url:
https://ctf.isis.poly.edu/
En este punto , la deducción fue fácil, el antiguo dominio era isis.poly.edu y esto nos permitió capturar 50 puntos mas
era temprano y quizá explorar otras categorías, por lo que el siguiente reto tenia que ser o cripto o forense, así que me fui por Trapdoor (daba 310 puntos)
Trapdoor
Categoría: Criptografía
Autor: gummiebear
Descripción:
You’ll need more than 2700 core-years to break this encryption!
Además nos daban 4 archivos:
msg1.enc
msg2.enc
public_key1
public_key2
El reto proporcionaba dos mensajes cifrados (msg1.enc
y msg2.enc
) junto con dos claves públicas (public_key1
y public_key2
). Desde el principio, noté que ambas claves RSA utilizaban el exponente e=65537e = 65537e=65537, un valor estándar en muchos sistemas RSA.
Al revisar los módulos n1n_1n1 y n2n_2n2, mi intuición fue que podrían compartir un factor común, dado el nombre del reto “Trapdoor” y las pistas sobre la dificultad para romper la encriptación por fuerza bruta.
Al calcular el máximo común divisor (GCD) de los módulos n1n_1n1 y n2n_2n2, encontré que compartían un factor primo. Esto es una debilidad clásica de RSA, donde si dos claves comparten uno de sus factores, es posible derivar las claves privadas de ambos sistemas. Este fue el caso en la primera versión del reto.
gcd_n1_n2 = math.gcd(n1, n2)
Derivación de las claves privadas
Con el GCD ppp, pude calcular los otros factores q1q_1q1 y q2q_2q2 para ambos módulos y finalmente, utilizando el algoritmo extendido de Euclides, derivé las claves privadas d1d_1d1 y d2d_2d2. (en esta parte me ayudo GPT)
# Cálculo de las claves privadas d1 y d2
d1 = modinv(e, (p - 1) * (q1 - 1))
d2 = modinv(e, (p - 1) * (q2 - 1))
Finalmente utilizando las claves privadas, fue posible descifrar los mensajes cifrados. En la primera versión del reto, los mensajes descifrados fueron:
- msg1.enc:
The Euclidean algorithm is the granddaddy of all algorithms, because it is the oldest nontrivial algorithm that has survived to the present day.
- msg2.enc:
csawctf{n0_p0lyn0m1al_t1m3_f4ct0r1ng_n33d3d_t0_0p3n_th1s_tr4pd00r!}
Pero aqui paso algo y es que al parecer durante el evento se presento una fuga de la flag y los administradores decidieron resetear los puntos y subir nuevamente el reto
finalmente el proceso resultó ser muy similar. Al revisar los nuevos archivos, encontré que los módulos n1n_1n1 y n2n_2n2 seguían compartiendo un factor común. Esto permitió aplicar la misma técnica de factorización y descifrado.
Los mensajes descifrados en la nueva versión del reto fueron:
- msg1.enc:
The Euclidean algorithm is the granddaddy of all algorithms, because it is the oldest nontrivial algorithm that has survived to the present day
- msg2.enc:
csawctf{sowwy_W3_b0u9ht_a_l34ky_tr4pd00r!}
Este reto involucraba la vulnerabilidad clásica de RSA cuando dos claves comparten uno de sus factores primos. El autor del reto actualizó los archivos tras la primera resolución, pero la vulnerabilidad persistió, lo que permitió resolverlo nuevamente de la misma forma.
Las flags encontradas fueron:
- Primera versión:
csawctf{n0_p0lyn0m1al_t1m3_f4ct0r1ng_n33d3d_t0_0p3n_th1s_tr4pd00r!}
- Segunda versión:
csawctf{sowwy_W3_b0u9ht_a_l34ky_tr4pd00r!}
Fue una experiencia interesante resolver el mismo reto dos veces…
Ahora bien , después de haber hecho estos retos, era momento de ir a una categoría mas cómoda y conocida, OSINT, mi precioso OSINT
el reto se llama Authentic Chinese Food
Nos daba la siguiente descripción :
I visited this gourmet restaurant a while back, but I’m worried about the health and safety rating of it. Could you check it for me? Oh, and before I forget, could you tell me when the BUILDING was built, as well as the name of the LLC that owns the building?
Flag Format: csawctf{HealthGrade_YearBuilt_LLCName} (Name does not include LLC, replace all spaces with _ )
Grade is the MOST RECENT grade, and does not have to be a letter or a number.
y esta imagen:
El formato de la flag esperada es: csawctf{HealthGrade_YearBuilt_LLCName} , en otras palabras la flag era la clasificación de salubridad, el año de construcción del edificio y el nombre de la compañía que posee o es dueña del mismo.
Lo primero fue realizar búsquedas inversa para poder identificar el lugar, el cual estaba en las siguientes coordenadas
40.69195456316901, -73.988100891722
https://www.google.com/maps/place/Panda+Express/@40.6920118,-73.98807,21z/data=!4m14[…]1dxdds976?entry=ttu&g_ep=EgoyMDI0MDkwNC4wIKXMDSoASAFQAw%3D%3D
Para determinar el campo de “healthGrade” después de investigar un poco encontré el sitio de https://a816-health.nyc.gov/ABCEatsRestaurants/ en donde con la dirección y nombre del restaurante podemos conocer los antecedentes de calificación de establecimientos de comidas, y el grado actual.
allí puse la dirección de nuestro objetivo y podemos observar varias violaciones según las inspecciones que tuvo y los puntos de calificación, sin embargo el grado actual es pendiente.
Ahora ya solo nos resta el año de construido y el owner del edificio, por alguna razón pensé que era mas fácil obtener el dueño que el año de construcción, por esto me enfoque en buscar primero el dueño
Despues de googlear , encontré la solución en el segundo resultado
https://www.compass.com/building/423-fulton-st-brooklyn-ny-11201/293532309167074133/
Lo primero y mas gratificante fue ver que allí también estaba el año de construcción
y mas abajo estaba el owner
despues de esto y organizar que significaba la O (owner) la flag correcta fue
csawctf{Grade_pending_1920_Bnn_Fulton_Flushing_Owner}
El siguiente reto que desarrolle fue
Rickshaw
Al inicio la verdad perdí mucho tiempo haciendo reverse a la imagen, hasta que caí en cuenta que la esquina inferior derecha se veía mucha información relevante, como :
Color de la placa
2 números
2 letras
Además en el enunciado del reto nos decían que era de india y que el vehículo era un rickshaw , entonces googlie de la siguiente forma para conocer rápidamente que puede significar esto:
- La placa tiene el número 77 CD. En la India, las placas diplomáticas o consulares a menudo tienen el formato “CD” seguido de un número. Esto indica que es un vehículo diplomático.
- El color azul de la placa también confirma que este vehículo probablemente esté registrado bajo la categoría de vehículos diplomáticos o consulares.
Según los anteriores resultados, la placa 77 CD pertenece a un vehículo diplomático asociado con la misión de los Estados Unidos en la India. El código “77” indica que este vehículo es propiedad o está vinculado a la embajada o consulado de los Estados Unidos.
Entonces el siguiente paso aquí fue buscar el teléfono de Embajada de los Estados Unidos en la india .
y de esta forma arme la flag y la capture csawctf{+91-11-2419-8000}
Personalmente fue el CTF del fin de semana que mas disfrute ! nos vemos hasta un siguiente juego !