TetCTF 2021

Nuevo año, nuevos CTFs

Kike Fontan
6 min readJan 3, 2021

Con la llegada del 2021, y aprovechando un poco las vacaciones de Navidad, he decidido participar en el primer CTF de este año: TetCTF.

https://ctf.hackemall.live/

Algo que me ha hecho especial ilusión, ha sido el hecho de poder hacerlo en equipo junto a la maravillosa gente de flagHunters. Esto ha sido gracias a que recientemente han contactado con Suraei y conmigo para invitarnos a formar parte de su comunidad.

Para quien no lo sepa, Suraei es la persona con la que he participado en todos los CTFs hasta la fecha (y la mejor hacker que conozco, con diferencia)

A pesar de todo, el nivel de TetCTF era demasiado elevado y los integrantes del equipo apenas teníamos tiempo que dedicarle a la competición. Aún así, al final hemos conseguido quedar entre los 100 primeros -literalmente-, lo cual no está nada mal teniendo en cuenta que eran más de 500 equipos...

Los retos

Los 300 puntos que obtuvimos son fruto de haber resuelto 3 retos. Dos de ellos basados en PHP y un sanity check (que durante casi toda la competición fue nuestra única flag 😅).

Haciendo retrospectiva, los retos que hemos conseguido sacar no eran demasiado complicados, pero sí lo suficientemente específicos como para necesitar saber bien lo que se estaba haciendo.

HPNY

Info: Get some lucky word or number for your new year! (http://challenge/?roll=get_lucky_word)

La frustración hecha reto. Clickando en el link, solamente se puede ver un mensaje deseando Feliz Año Nuevo en algún idioma aleatorio, pero en el caso de acceder sin especificar ningún parámetro, se muestra el código fuente de la página:

Como se puede ver, hay dos funciones definidas: get_lucky_wordy get_lucky_number. No parece que haya nada realmente interesante en ninguna, así que las obviaremos. Por otro lado, el código comprueba la existencia del parámetro rolly si éste contiene solamente valores alfabéticos y algunos símbolos admitidos. Además, también valida que la longitud del valor sea menor o igual que 50 caracteres.

La parte interesante viene después:

Claramente aquí se encuentra la vulnerabilidad.

Vemos que lo que le pasemos como valor al parámetro roll se va a evaluar como una función. Es por eso que si escribimos get_lucky_wordnos devuelve una felicitación aleatoria.

Para probar si existe la vulnerabilidad, se puede escribir la función phpinfoy esperar que devuelva un resultado:

Voilà! Muestra exactamente lo que se esperaba. La idea ahora es buscar dónde puede estar la flag escondida…

El primer paso es listar el directorio en el que nos encontramos, pero no va a ser posible usar scandir("."), dado que las comillas no están permitidas. Aún así, la solución es simple: podemos usar variables globales como __DIR__o funciones como getcwdpara resolver el problema. Pero también sucede que scandirdevuelve un Array, y no es posible renderizarlo en el navegador, así que lo suyo será englobar todo dentro de funciones como var_dumpo print_r:

Contenido del directorio actual mostrado con el comando ?roll=print_r(scandir(__DIR__))

La frustración y los problemas comienzan al intentar leer el archivo. Para utilizar comandos como readfileo show_sourcees necesario especificar el nombre del fichero, pero habría que usar comillas y además éste contiene un número (caracter que no tenemos permitido).

Entonces, ¿cómo lo resolvemos?

Una solución, y posiblemente la más sencilla, es aprovechar el resultado del script anterior para concatenarlo con una lectura de archivos. Podemos darle la vuelta al array con array_reversey obtener al segundo índice con next.

¡La primera flag!

Para ser sinceros, esta no es la solución a la que yo llegué. Mi aproximación fue algo diferente.

Ya que existen funciones como getallheaders, pasé como cabecera el nombre del archivo y lo obtuve usando array_pop:

Distinta solución al mismo reto

Super Calc

Info: Let try on the next-generation, the superior Calculator that support many operations, made with love ❤ (http://challenge/?calc=(1.2–0.2)*5.1)

Este reto es similar al anterior, aunque el procedimiento para resolverlo no sea el mismo.

Al acceder a la web, se puede observar el siguiente texto:

Result: 5.1

Si recargamos la página sin parámetros, nos muestra su código fuente:

¿preg_match y eval? ¿De qué me suena?

Ya de primeras se aprecia que la estructura es muy similar a HPNY, pero en este caso sólo acepta números y operadores como argumentos. La cosa es… ¿cómo se pueden ejecutar comandos sin usar letras?

Antes de nada, hay que entender que PHP es bastante vago al analizar las variables y sus tipos. Esto nos permite hacer operaciones como tan curiosas como las siguientes:

¡Polimorfismo!

¿Y cuál es el tipo de operación más usada al ofuscar comandos?

La respuesta es XOR. ¿Te suena de algo?

XOR es un tipo de operación lógica con la que podemos, como con la mayoría de las operaciones, obtener un valor gracias a otros dos. Lo bueno es que es reversible. Es decir, sabiendo dos valores, podemos obtener el tercero fácilmente.

Por ejemplo: imaginemos que necesitásemos una U para resolver el reto, pero sólo podemos usar operadores y números. Pues bien, podemos hacer lo siguiente: '+' ^ '~' = 'U', que se puede deducir de hacer '+' ^ 'U' = '~' o '~' ^ 'U' = '+'.

Una vez entendido esto, vamos a resolver el reto. La aproximación más sencilla será leer todos los archivos de la carpeta con la esperanza de encontrar la flag. El comando más corto que he encontrado ha sido `cat *`, que es lo mismo que ejecutar shell_exec('cat *').

Intentar calcular la operación XOR a mano es un trabajo tedioso, para ello se puede usar el siguiente script de devploit o montarse un script propio:

En el caso de que con dos combinaciones no podamos obtener la letra deseada, habrá que concatenar varias operaciones. Después de realizar el proceso, el comando`cat *` quedaría como algo similar a esto:

('**'^'~~'^'47').('8'^'^'^'7'^'0').('^~'^'*^').('*'^'~'^'4')

Esta es una posible combinación, pero no es la única.

Ahora sólo queda ejecutarlo como parámetro. Como es posible que la flag esté en un comentario u oculto de alguna manera no visible, recomiendo inspeccionar el código fuente de la respuesta:

¡Funciona!

Y esto es todo por hoy. La verdad que han sido dos retos bastante interesantes.

Agradecer antes de finalizar a SrBleu, el cual me ha ayudado aportando su visión sobre los retos. Y a ti, por haber llegado hasta aquí.

Espero que nos volvamos a encontrar en otro post pronto, ¡un abrazo enorme y a seguir hackeando! 💕🦄

— Puma

Sign up to discover human stories that deepen your understanding of the world.

--

--

Kike Fontan
Kike Fontan

Written by Kike Fontan

Pentester, Profesor, Divulgador Científico y Estudiante

No responses yet

Write a response