CSAW’24 Qualification round — solución de algunos retos

1v0t
11 min readSep 9, 2024

--

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:

  1. 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
  2. Función deep_eval(): La ruta /get_eval permite a los usuarios enviar expresiones en formato JSON que se evalúan con la función eval() 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ó:

  1. Explorar directorios con echo:
  • Aunque los comandos tradicionales como ls no funcionaban, se pudo usar echo * 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 !

--

--

1v0t
1v0t

Written by 1v0t

OSINT, threat hunting, CTF, forensic analysis, hunting down bad guys to complete the puzzle.

No responses yet