De SSTI a RCE en Tornado Web Framework

Por Gustavo H. Reyes @0n1r1k0

La solución al reto titulado And Now For Something Completely Different que presento a continuación fue parte de los retos en la categoría web y se realizó durante el TUCTF 2019, una competición tipo Capture The Flag dirigida a principiantes.

Descripción:

Descripción del reto al terminar la competición.

En la URL proporcionada se encuentra una aplicación de tienda en línea, al comenzar a probar la funcionalidad se identifica que muchas de las funciones  -como ver la información de la cuenta o registrarse-  conducen a un error que es devuelto al usuario, con esta información -divulgada innecesariamente-, se reconoce que la aplicación utiliza Tornado, un framework web escrito en Python.

Al continuar con el reconocimiento, se encuentra un comentario interesante dentro del HTML:

Comentario sospechoso que invita a revisar /welcome/test

Al visitar la dirección http://chal.tuctf.com:30007/welcome/test se observa que se muestra el mensaje "Welcome test", después de algunos otros intentos se identifica que al modificar la URL y cambiar "test" por alguna otra palabra ésta se ve reflejada en el sitio a continuación del "Welcome". Lo primero que se probó fue ver si era vulnerable a XSS pero el resultado fue otro mensaje de error relacionado a Tornado, una vez descartada esa posibilidad se intuye que podría tratarse de una vulnerabilidad de tipo Server-Side Template Injection (SSTI).

Para verificar la existencia de la vulnerabilidad uno de los payloads más básicos y comunes es {{7*7}}, al ingresarlo, el servidor responde "Welcome 49", lo que indica que no está saneando el input que recibe y ejecuta el código, es decir, que es vulnerable.

Con esta información se procede a investigar sobre la combinación de SSTI y Tornado, lo que me llevó a  un blog bastante interesante y que recomiendo consultar si se desea saber más sobre esta vulnerabilidad.

En el blog recién mencionado se haya un payload que permite importar módulos de Python 
Una vez obtenida esta información es momento de intentar importar el módulo os de Python para ejecutar comandos en el sistema, por lo que se crea el siguiente payload:

{% import os %}{{ os.popen("ls").read() }}
Al ingresarlo es ejecutado el comando ls (usado para listar archivos  y directorios en Linux) y se obtiene lo siguiente:


Donde destaca la existencia del archivo flag.txt, por lo que se modifica el payload anterior para mostrar el contenido de dicho archivo, quedando de la siguiente forma:

{% import os %}{{ os.popen("cat flag.txt").read() }}
Con lo cual, finalmente, se obtiene la bandera.



TUCTF{4lw4y5_60_5h0pp1n6_f0r_fl465}


Go Mayas!



Recursos:

Comentarios