Les moteurs de modèles sont largement utilisés dans les applications web pour combiner HTML et données afin de générer des affichages. Par exemple, les moteurs de modèles sont utilisés en back-end pour intégrer des noms d'utilisateur, des contenus de publication, etc. au code HTML.
les valeurs saisies par l'utilisateur sont directement incluses dans le traitement de ce modèle , la syntaxe entière du modèle peut être évaluée. Il s'agit d'une vulnérabilité appelée « SSTI (Server-Side Template Injection) ».
Si une SSTI se produit, selon le type de moteur de template, elle risque d'entraîner un accès à des variables internes ou, dans le pire des cas, l'exécution arbitraire de commandes du système d'exploitation (RCE). En particulier, dans les systèmes basés sur Python, Jinja2
et Mako
présentent une implémentation vulnérable, ils peuvent devenir une porte d'entrée pratique pour les attaquants.
Mako
l'objet de cette vérification , est l'un des moteurs de modèles couramment utilisés en Python, mais il est également susceptible d' intégrer accidentellement la saisie utilisateur directement
Nous allons regarder un exemple concret pour voir comment cette vulnérabilité peut être exploitée dans une application réelle.
📹 : Vous pouvez également voir comment cela se fait en pratique sur YouTube !
- La sensation de frappe nette unique au système capacitif sans contact !
- Premier appareil compatible sans fil de REALFORCE ! Connexion filaire également disponible !
- Contrairement au HHKB, la disposition du clavier japonais n'a aucune particularité et est facile à utiliser pour tout le monde !
- Equipé d'une molette, le défilement horizontal est très facile !
- Il dispose également d'excellentes performances de réduction du bruit, ce qui le rend silencieux et confortable !
- Le défilement peut être commuté entre le mode haute vitesse et le mode cliquet !
À propos de HackTheBox
Cette fois, nous utilisons en fait HackTheBox (HTB) pour vérifier les vulnérabilités.
HackTheBox est une plateforme CTF pratique où les participants peuvent s'entraîner dans divers domaines de la sécurité, notamment les applications web, les serveurs et les réseaux.
Son principal atout est de permettre aux participants d'apprendre en accédant aux machines et applications qui seront attaquées et en se livrant à des expériences concrètes.
est l'une des catégories de défis qui étaient auparavant proposées sur HackTheBox , et n'est actuellement accessible qu'aux utilisateurs disposant d'un plan VIP ou supérieur
Il existe également des machines et des défis dans diverses catégories, notamment Web, Reversing, Pwn et Forensics, afin que vous puissiez les aborder à un niveau qui vous convient.
Si vous souhaitez sérieusement perfectionner vos compétences avec HackTheBox, assurez-vous au plan VIP et de profiter pleinement des machines et des défis passés.
👉 Visitez le site officiel de HackTheBox ici
👉 Pour des informations détaillées sur la façon de s'inscrire à HackTheBox et les différences entre les plans, veuillez cliquer ici.

Résumé du défi : Spookifier
Le défi que nous avons relevé cette fois, « Spookifier est classé dans la catégorie Web de HackTheBox est réglé sur TRÈS FACILE
À première vue, l'application est très simple : un service web qui convertit et affiche simplement du texte dans différents styles de police lors de sa saisie. À première vue, elle ne semble présenter aucune faille de sécurité.
Cependant, l'application le moteur de modèle Python « Mako » et la chaîne saisie par l'utilisateur était évaluée directement dans le modèle.
Ce défaut de conception peut conduire à une injection de modèle côté serveur (SSTI) et, en fin de compte, à une exécution de commande arbitraire (RCE)
👉 https://app.hackthebox.com/challenges/Spookifier
Points de défi
- Technologies utilisées : Python, Flask, Mako
- Comportement notable : l'entrée est affichée dans plusieurs polices
- Vecteur d'attaque : entrée non nettoyée dans le modèle → SSTI
- Cible : Récupérer les indicateurs de
/flag.txt
De cette façon, derrière la fonctionnalité qui semble sûre en surface une faiblesse dans le processus d'évaluation du modèle , et la structure vous permet de faire l'expérience d'un « modèle typique de SSTI à RCE ».
Le piratage informatique en pratique : du SSTI au RCE
À partir de là, nous allons tester l'application et rechercher des failles.
Une manipulation négligente du modèle pourrait constituer un point d'entrée pour une attaque.
Nous vérifierons la validité de SSTI et viserons finalement l'exécution de code à distance.
Scouting 1 : Tout d'abord, essayez l'application
Tout d’abord, accédez à l’application cible et vérifiez quelles fonctions elle possède et quelles entrées elle accepte
L'écran présente un formulaire de saisie simple, et semble n'avoir pour seule fonction que de « saisir du texte, le convertir en une police décorée et l'afficher ».
Son apparence et sa structure sont très simples, sans fonctions d'authentification ni routage complexe.

Il est important de noter ici la chaîne saisie par l'utilisateur est traitée d'une manière ou d'une autre, puis affichée comme modèle .
Il semble qu'à un moment donné, lors du processus d'affichage dans plusieurs polices, la chaîne soit manipulée par un moteur de modèles.

J'ai vérifié les informations de la demande à l'aide de devtools, mais il ne semble pas y avoir d'informations significatives.

Reconnaissance 2 : Identifier le moteur de template à partir du code source
Lors de l'investigation des vulnérabilités des applications web, il est rare d'avoir accès au code source.
Les tests d'intrusion et les programmes de primes aux bugs reposent sur des tests en boîte noire (observation du comportement depuis l'extérieur).
Par conséquent, nous vérifions généralement la présence d’un moteur de modèle et s’il existe des vulnérabilités via le processus suivant.
- Dans le champ de texte, essayez une syntaxe de modèle courante telle que
${7*7}
,{{7*7}}
,<%= 7*7 %>
- le résultat affiche
49
ou7*7
- Toute erreur de modèle inhabituelle ou tout résultat d’évaluation peut fournir des indices au moteur de modèle.
- Déduire le moteur de modèle utilisé à partir de sa sortie et de son comportement (Mako, Jinja2, Twig, etc.)
Cette fois, le code source a été fourni comme un défi spécial visant à en apprendre davantage sur les vulnérabilités,
me permettant d'examiner directement la structure interne et de comprendre rapidement comment fonctionne le traitement des modèles.
Dans le code source fourni, vous pouvez trouver la description de rendu du modèle suivant :
depuis mako.template importer Template ... renvoyer Template(result).render()
Cette phrase montre clairement que
Mako est utilisé comme moteur de template Mako est un moteur de template Python, et la syntaxe ${...}
est évaluée directement comme une expression Python, ce qui présente un risque d' injection de template côté serveur (SSTI)
essaiera d'évaluer ${}
dans la saisie utilisateur
Maintenant que nous savons que Mako est utilisé comme moteur de modèle, la prochaine chose à vérifier est de
le ${}
dans la chaîne saisie par l'utilisateur est réellement évalué comme une expression de modèle , ce qui est la première étape pour déterminer si SSTI (Server-Side Template Injection) existe.
essayez donc d'abord de saisir la syntaxe de modèle de base de Mako, ${7*7},
${7*7}
Si le moteur de modèle évalue cette entrée comme une expression, il doit générer le nombre
49.
Inversement, s'il n'est pas évalué et traité comme une chaîne, il sera simplement affiché à l'écran sous la forme ${7*7}
Lorsque je l'ai envoyé, le message suivant s'est affiché à l'écran :

Le résultat 49
le ${7*7}
saisi par l'utilisateur a été évalué par le moteur de modèle (Mako).
En d’autres termes, Mako traite les entrées utilisateur comme un modèle , et il a été confirmé que SSTI était en vigueur.
Intrusion : vérifier la présence d'un RCE ⇒ Essayez de voir jusqu'où vous pouvez l'exécuter à partir de la formule du modèle
Avec SSTI confirmé, notre prochain objectif était clair :
voir si nous pouvions exploiter les expressions de modèle pour exécuter du code arbitraire côté serveur (RCE)
Confirmation de l'exécution de la commande
Commençons par tester si nous pouvons réellement exécuter une commande du système d'exploitation à partir d'une expression de modèle.
Pour le vérifier, nous utiliserons la commande whoami
${__import__('os').popen('whoami').read()}
Lorsque j'ai soumis cette formule, j'ai obtenu le résultat suivant :

Le résultat de l'exécution de whoami
montre root
ce qui confirme que toute commande du système d'exploitation peut être exécutée via une expression de modèle et que la commande est exécutée avec les privilèges root
À ce stade, il est clair qu’une vulnérabilité d’exécution de code à distance (RCE) existe, permettant à un attaquant d’exécuter des commandes avec des privilèges élevés
Vérification de la lecture du fichier
Maintenant que nous savons que nous pouvons exécuter des commandes, nous pouvons vérifier
si nous pouvons lire n'importe quel fichier Un exemple typique /etc/passwd
, familier aux environnements Linux.
${open('/etc/passwd').read()}
La sortie comprenait les informations utilisateur, telles que :

Ce résultat montre qu'il
est possible d'appeler open()
de Python , vous donnant un contrôle total sur les opérations de lecture sur le serveur.
Exécution : Rechercher et obtenir des drapeaux
Jusqu'à présent, grâce à l'injection de modèles
- Exécution de code Python
- Exécuter les commandes du système d'exploitation
- Lecture de fichiers arbitraires
Cela signifie qu'une exécution de code à distance complète (RCE) a été réalisée .
L'étape suivante à rechercher le fichier d'indicateur cible et à récupérer son contenu .
Trouver l'emplacement du fichier drapeau
Tout d’abord, regardons le contenu du répertoire racine /
et voyons quels répertoires et fichiers s’y trouvent.
${__import__('os').listdir('/')}

Comme vous pouvez le voir, c'est bien si vous pouvez trouver le fichier souhaité ( flag.txt
), mais si vous ne le trouvez pas, vous devrez creuser plus profondément dans home
ou root
Lire le drapeau
Si la recherche trouve un fichier tel que /flag.txt
open()
pour récupérer son contenu :
${open('/flag.txt').read()}
Lorsque j'ai exécuté cette expression, j'ai obtenu le résultat suivant :

Nous avons réussi à obtenir
le signalement, objectif final du défi HackTheBox Ce processus nous a permis de mieux comprendre dans quelle mesure la vulnérabilité SSTI peut être exploitée lors de tests réels.
Pourquoi cette vulnérabilité est-elle apparue ? Comment utiliser les modèles en toute sécurité ?
La cause principale de cette vulnérabilité (SSTI → RCE) l'utilisation inappropriée du moteur de modèle
En particulier, le côté Python construit dynamiquement des chaînes de modèles contenant des entrées utilisateur , conduisant à une injection de modèles (SSTI) et à une éventuelle exécution de code à distance (RCE).
Solution – Ne transmettez pas de chaînes dynamiques aux modèles
L’un des modèles typiques dans lesquels SSTI (Server-Side Template Injection) se produit
lorsqu’une chaîne est construite en Python puis évaluée comme un modèle .
Créer des chaînes de modèles à l'aide de str.format()
, comme dans le code ci-dessous,
def generate_render(converted_polices): résultat = '''<tr><td> {0}</td></tr><tr><td> {1}</td></tr><tr><td> {2}</td></tr><tr><td> {3}</td></tr> '''.format(*converted_polices) renvoie Template(résultat).render()
Par exemple, converted_fonts
contient l'entrée utilisateur suivante :
${__import__('os').popen('id').read()}
Le passage de ce modèle à Mako crée une vulnérabilité sérieuse Mako évaluera ${...}
Utilisation sécurisée : séparation de la structure du modèle et des données
Pour éviter ce problème, il est important
de séparer la structure du modèle des données saisies par l'utilisateur (variables) Vous pouvez gérer ce problème en toute sécurité en transmettant explicitement des variables à render()
, comme ceci :
def generate_render(converted_polices): template = '''<tr><td> ${font1}</td></tr><tr><td> ${font2}</td></tr><tr><td> ${font3}</td></tr><tr><td> ${font4}</td></tr> ''' renvoie Template(template).render( font1=converted_fonts[0], font2=converted_fonts[1], font3=converted_fonts[2], font4=converted_fonts[3] )
Avec cette méthode, font1
à font4
contiennent ${}
, Mako les traitera comme des chaînes ordinaires et ne les évaluera pas comme des expressions de modèle.

${...}
de Mako évalue les expressions dans les modèles,
et si la saisie de l'utilisateur est transmise textuellement, il existe un risque d'exécution de code.
En revanche, si vous transmettez explicitement des variables via
Template(...).render(var=value)
Dans ce cas, var }
peut être utilisé en toute sécurité comme espace réservé dans le modèle , mais ne sera pas exécuté comme code.
Résumé : Les SSTI sont des vulnérabilités causées par des « habitudes d'utilisation »
Dans ce défi « Spookifier », une mauvaise gestion des modèles Mako
nous a permis d'exploiter une vulnérabilité qui a conduit à une injection de modèle côté serveur (SSTI) et finalement à une exécution de code à distance (RCE).
Ces vulnérabilités sont dues à
des erreurs d'implémentation commises par les développeurs Elles sont particulièrement dangereuses lorsque les chaînes de modèles sont construites dynamiquement.
Pour utiliser les moteurs de modèles en toute sécurité :
- Toujours séparer les modèles et les données (variables)
- Transmettez les variables comme espaces réservés et n'évaluez pas les expressions
- Ne transmettez pas d'entrées non fiables directement aux modèles
En suivant simplement ces principes de base, de nombreuses infections sexuellement transmissibles (IST) peuvent être évitées.
👉 Pour des informations détaillées sur la façon de s'inscrire à HackTheBox et les différences entre les plans, veuillez cliquer ici.
