Diventa Autore per CoreTech | Scopri di più
20/07/20 CoreTech Blog
Uno dei modi più comodi per creare pagine Web consiste nell'utilizzare modelli lato server. Tali modelli consentono di creare pagine HTML che includono elementi speciali che è possibile riempire e modificare in modo dinamico. Sono facili da capire per i progettisti e facili da mantenere per gli sviluppatori. Esistono molti motori di modelli lato server per diverse lingue e ambienti lato server. Uno di questi è Thymeleaf , che funziona con Java.
Le iniezioni di modelli lato server (SSTI) sono vulnerabilità che consentono all'attaccante di immettere codice in tali modelli lato server. In termini semplici, l'utente malintenzionato può introdurre il codice che viene effettivamente elaborato dal modello lato server. Ciò può comportare l'esecuzione di codice in modalità remota (RCE) , che rappresenta una vulnerabilità molto grave. In molti casi, tale RCE si verifica in un ambiente sandbox fornito dal motore modello, ma molte volte è possibile sfuggire a questo sandbox, il che può consentire all'attaccante di assumere il pieno controllo del web server.
Inizialmente SSTI fu studiato da James Kettle e successivamente da Emilio Pinna . Tuttavia, nessuno di questi autori ha incluso Thymeleaf nella sua ricerca SSTI. Vediamo quali opportunità RCE esistono in questo motore di template.
Thymeleaf è un moderno motore di template lato server per Java, basato sulla sintassi XML / XHTML / HTML5. Uno dei principali vantaggi di questo motore è il modello naturale . Ciò significa che un modello HTML Thymeleaf ha l'aspetto e il funzionamento esattamente come HTML. Ciò si ottiene principalmente utilizzando attributi aggiuntivi nei tag HTML. Ecco un esempio ufficiale:
<table>
<thead>
<tr>
<th th:text="#{msgs.headers.name}">Name</th>
<th th:text="#{msgs.headers.price}">Price</th>
</tr>
</thead>
<tbody>
<tr th:each="prod: ${allProducts}">
<td th:text="${prod.name}">Oranges</td>
<td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td>
</tr>
</tbody>
</table>
Se apri una pagina con questo codice usando un browser, vedrai una tabella riempita e tutti gli attributi specifici di Thymeleaf verranno semplicemente ignorati. Tuttavia, quando Thymeleaf elabora questo modello, sostituisce il testo del tag con i valori passati al modello.
Per tentare un SSTI in Thymeleaf, dobbiamo prima comprendere le espressioni che compaiono negli attributi di Thymeleaf. Le espressioni di thymeleaf possono avere i seguenti tipi:
${...}
: Espressioni variabili: in pratica si tratta di espressioni OGNL o Spring EL.*{...}
: Espressioni di selezione - simili alle espressioni variabili ma utilizzate per scopi specifici.#{...}
: Espressioni di messaggi (i18n) - utilizzate per l'internazionalizzazione.@{...}
: Espressioni di link (URL): utilizzate per impostare URL / percorsi corretti nell'applicazione.~{...}
: Espressioni di frammenti: ti consentono di riutilizzare parti di modelli.Il tipo di espressione più importante per un tentativo di SSTI è il primo: espressioni variabili. Se l'applicazione Web si basa su Spring, Thymeleaf utilizza Spring EL. In caso contrario, Thymeleaf utilizza OGNL.
L'espressione di test tipica per SSTI è ${7*7}
. Questa espressione funziona anche in Thymeleaf. Se si desidera ottenere l'esecuzione di codice in modalità remota, è possibile utilizzare una delle seguenti espressioni di test:
${T(java.lang.Runtime).getRuntime().exec('calc')}
${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}
Tuttavia, come accennato in precedenza, le espressioni funzionano solo con attributi speciali di Thymeleaf. Se è necessario utilizzare un'espressione in una posizione diversa nel modello, Thymeleaf supporta l' inserimento di espressioni . Per utilizzare questa funzione, è necessario inserire un'espressione all'interno di [[...]]
o [(...)]
(selezionare l'una o l'altra a seconda se è necessario uscire da simboli speciali). Pertanto, sarebbe un semplice payload di rilevamento SSTI per Thymeleaf [[${7*7}]]
.
Le probabilità che il payload di rilevamento di cui sopra funzioni, tuttavia, sono molto basse. Le vulnerabilità SSTI si verificano in genere quando un modello viene generato dinamicamente nel codice. Thymeleaf, per impostazione predefinita, non consente tali modelli generati dinamicamente e tutti i modelli devono essere creati in precedenza. Pertanto, se uno sviluppatore desidera creare un modello da una stringa al volo , dovrà creare il proprio TemplateResolver. Questo è possibile ma accade molto raramente.
Se esaminiamo più a fondo la documentazione del motore di template di Thymeleaf, troveremo un'interessante funzione chiamata pre-elaborazione delle espressioni . Le espressioni inserite tra i trattini bassi ( __...__)
sono preelaborate e il risultato della preelaborazione viene utilizzato come parte dell'espressione durante l'elaborazione regolare. Ecco un esempio ufficiale dalla documentazione di Thymeleaf:
#{selection.__${sel.code}__}
Primi preprocessi di Thymelead ${sel.code}
. Quindi, utilizza il risultato (in questo esempio è un valore memorizzato TUTTO ) come parte di un'espressione reale valutata in seguito ( #{selection.ALL})
.
Questa funzionalità introduce un grande potenziale per una vulnerabilità SSTI. Se l'attaccante può controllare il contenuto del valore preelaborato, può eseguire un'espressione arbitraria. Più precisamente, si tratta di una vulnerabilità a doppia valutazione, ma questo è difficile da riconoscere usando un approccio black-box.
PetClinic è un'applicazione demo ufficiale basata sul framework Spring. Utilizza Thymeleaf come motore modello.
La maggior parte dei modelli in questa applicazione riutilizza parti del modello layout.html , che include una barra di navigazione. Ha un frammento speciale (funzione), che genera il menu .
<li th:fragment="menuItem (path,active,title,glyph,text)" class="active" th:class="${active==menu ? 'active' : ''}">
<a th:href="@{__${path}__}" th:title="${title}">
Come puoi vedere, l'applicazione preelabora ${path}
, che viene quindi utilizzata per impostare un collegamento corretto ( @{}
). Tuttavia, questo valore proviene da altre parti del modello:
<li th:replace="::menuItem ('/owners/find','owners','find owners','search','Find owners')">
Sfortunatamente, tutti i parametri sono statici e incontrollabili dall'attaccante.
Tuttavia, se proviamo ad accedere a una route che non esiste, l'applicazione restituisce il modello error.html , che riutilizza anche questa parte di layout.html . Nel caso di un'eccezione (e l'accesso a una route che non esiste è un'eccezione), Spring aggiunge automaticamente variabili al contesto corrente (attributi del modello). Una di queste variabili è di percorso (altri includono timestamp , traccia , un messaggio , e altro ancora).
La variabile path è una parte del percorso (senza decodifica URL) dell'URL della richiesta corrente. Ancora più importante, questo percorso viene utilizzato all'interno del menuItemframmento. Pertanto, __${path}
__preelabora il percorso dalla richiesta. E l'attaccante può controllare questo percorso per raggiungere SSTI e, di conseguenza, RCE.
Come semplice test, possiamo inviare una richiesta a http: // petclinic / (7 * 7) e ottenere 49 come risposta.
Tuttavia, nonostante questo effetto, non siamo riusciti a trovare un modo per ottenere RCE in questa situazione quando l'applicazione viene eseguita su Tomcat. Questo perché è necessario utilizzare Spring EL, quindi è necessario utilizzare ${}
. Tuttavia, Tomcat non consente i caratteri { e } nel percorso senza codifica URL. E non possiamo usare la codifica, perché ${path}
restituisce il percorso senza decodifica. Per provare questi presupposti, abbiamo eseguito PetClinic su Jetty anziché Tomcat e ottenuto RCE perché Jetty non limita l'uso di { e } caratteri nel percorso:
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
Abbiamo dovuto usare i caratteri ( e ) perché dopo la preelaborazione l'@{}
espressione riceve una stringa che inizia con / (ad esempio, /${7*7}), quindi l'espressione non viene trattata come espressione. L' @{}
espressione consente di aggiungere parametri all'URL inserendoli tra parentesi. Possiamo usare questa funzione in modo improprio per cancellare il contesto e ottenere la nostra espressione eseguita.
L'iniezione di modelli sul lato server è molto più problematica di quanto sembri perché i modelli sul lato server vengono utilizzati sempre più spesso. Esistono molti di questi motori di template e molti di essi rimangono non sfruttati ma possono introdurre vulnerabilità SSTI se utilizzati in modo improprio. C'è molto da fare ${7*7}
per raggiungere l'RCE, ma in molti casi, come puoi vedere, è possibile.
Come ricercatori di sicurezza, troviamo sempre interessante vedere come le tecnologie complesse si scontrano e si influenzano a vicenda e quanto rimane ancora inesplorato.