Aller au contenu
Retour à la recherche en sécurité

Recherche en sécurité

Injection de gabarit côté serveur: de la détection au shell distant

Parlons aujourd’hui des moteurs de gabarits et des vulnérabilités qui en découlent: les attaques par injection de gabarit côté serveur. Dans ce billet, nous abordons quelques enjeux de sécurité liés à l’utilisation des moteurs de gabarits dans les applications Web modernes.

1 – Qu’est-ce qu’un moteur de gabarits?

Les moteurs de gabarits sont de plus en plus répandus dans les applications Web modernes.

Utilisé pour insérer des données dynamiques dans les pages Web, un moteur de gabarits sépare la logique de traitement des données et le code de présentation en deux parties distinctes.

Cette séparation rend le code plus facile à modifier et à maintenir, et permet aux développeurs de produire les types de contenu voulus. Le gabarit est créé une seule fois par les développeurs, puis traité par un moteur de gabarits qui insère l’information désirée dans les blocs de balises prévus à cette fin.

Les usages sont variés: afficher de l’information sur des utilisateurs ou des produits, ou encore composer des envois massifs de courriels pour des applications de marketing. On les retrouve couramment dans les wikis, les CMS et les plateformes de blogue.

Java (freemarker, Velocity), PHP (smarty, twig), python (Jinja, tornado) et ruby (Liquid) disposent d’un moteur de gabarits, et beaucoup d’autres langages recourent à des bibliothèques pour faire ce travail [1].

2 – Qu’est-ce qu’une injection de gabarit?

James Kettle (portSwigger) a présenté cette vulnérabilité pour la première fois lors de la Blackhat 2015. Si ce n’est pas déjà fait, je vous invite à lire son excellent billet à ce sujet [2].

Une injection de gabarit peut survenir lorsqu’une entrée non fiable est concaténée à un fichier de gabarit sans être transmise comme contexte à une méthode de rendu. Que ce soit intentionnellement ou par erreur, les développeurs peuvent introduire ce type de vulnérabilité dans leurs applications Web.

Les attaques par injection de gabarit côté serveur sont souvent confondues avec les vulnérabilités XSS. Du point de vue d’un testeur d’intrusion, l’attaque XSS est bien connue et souvent simple à exploiter, alors que l’injection de gabarit peut passer inaperçue. Le risque est d’autant plus grand qu’elle peut mener à l’exécution de code arbitraire à distance.

3 – La mission:

Assez de théorie, passons à la pratique. Nous allons utiliser la preuve de concept suivante, écrite en python, pour illustrer cette vulnérabilité [3].

import tornado.ioloop
import tornado.web
import tornado.template

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        TEMPLATE = '''
<html>
  <head>
    <title>SSTI POC</title>
  </head>
  <body>

<h2>
      Hello %s !
    </h2>

  </body>
</html>
''' % (self.get_argument('param', ''))
        t = tornado.template.Template(TEMPLATE)
        self.write(t.generate())

if __name__ == "__main__":
    application = tornado.web.Application([(r"/", MainHandler),],debug=True)
    application.listen(8888)
    tornado.ioloop.IOLoop.current().start()

Suivons la méthodologie de James en démarrant l’application tornado, et voyons ce que cela donne: L’application de test Tornado au premier chargement.

Nous avons donc un paramètre d’entrée dont le résultat est affiché dans le gabarit.

La première chose à faire est de déterminer si le moteur de gabarits est vulnérable ou non.

Une simple opération mathématique suffit à le vérifier:

Une simple opération arithmétique évaluée par le moteur de gabarits, confirmant l’injection.

L’opération est évaluée et le résultat est renvoyé au client. Voilà qui est intéressant. Poursuivons notre investigation.

La documentation de tornado [4] nous apprend que les expressions sont encadrées par des accolades doubles, sous la forme {{expression python}}: elles sont évaluées et le résultat est renvoyé au client. N’importe quelle expression python peut y être placée. En poussant la lecture de la documentation, nous apprenons aussi qu’il est possible d’importer des modules python au moyen de la directive de gabarit {% import module %}.

Nous savons maintenant exactement à quoi nous avons accès. Fort de ces constats, l’étape suivante consiste à fabriquer un exploit. Sans trop de difficulté, nous obtenons une exécution de code à distance.

Énumération de ce que le contexte du gabarit expose.

Dès lors, prendre le contrôle du service n’est plus qu’une question de temps. Complétons la compromission totale avec un shell distant:

Un shell distant obtenu sur le service.

N’oubliez pas de démarrer un écouteur netcat sur votre machine locale:

gdieu:~ admin$ ncat -v -l -p 4444

Ncat: Version 7.00 ( https://nmap.org/ncat )

Ncat: Listening on:::4444

Ncat: Listening on 0.0.0.0:4444

Ncat: Connection from 192.168.0.107.

Ncat: Connection from 192.168.0.107:39342.

$ id

uid=1000(gdieu) gid=1000(gdieu) groups=1000(gdieu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),114(lpadmin),115(sambashare)

Mission accomplie: nous avons obtenu un shell distant sur le serveur vulnérable. C’est tout pour cette fois!

Gérôme Dieu, OSCP

Consultant en sécurité informatique

___________________________________________________

[1] https://en.wikipedia.org/wiki/Comparison\_of\_web\_template\_engines

[2] http://blog.portswigger.net/2015/08/server-side-template-injection.html

[3] https://opsecx.com/index.php/2016/07/03/server-side-template-injection-in-tornado/

[4] http://www.tornadoweb.org/en/stable/template.html?highlight=templating#syntax-reference

Envoyez-nous un message

Seul votre courriel est requis. Choisissez un sujet, ajoutez une note, puis envoyez.

Incident en cours? Appelez la ligne 24/7 plutôt que d’attendre une réponse: +1 450 681-1681, poste 277