Skip to main content

Corriger une vulnérabilité d’exécution de code à distance dans EJS

Écrit par
Headshot of Tim Kadlec

Tim Kadlec

30 novembre 2016

0 minutes de lecture

Cette semaine, nous avons ajouté une vulnérabilité d’exécution de code à distance dans le package EJS à notre base de données des vulnérabilités.

EJS (Embedded JavaScript Templates) est un moteur de templates JavaScript rapide, simple et très populaire. EJS propose plusieurs options pour effectuer le rendu d’un template. Deux d’entre elles, render et renderFile, sont assez similaires. La seule différence est que render attend une chaîne de caractères pour le template, tandis que renderFile attend le chemin d’accès à un fichier template. Les deux méthodes acceptent également des arguments pour les données et un ensemble facultatif d’options de configuration. La méthode renderFile accepte aussi une fonction de rappel.

ejs.render(str, data, options);

ejs.renderFile(filename, data, options, callback)

Les deux méthodes permettent également de regrouper les données et les options dans un seul objet.

ejs.render(str, dataAndOptions);

ejs.renderFile(filename, dataAndOptions, callback)

La vulnérabilité

La méthode raccourcie peut sembler plus simple, mais mélanger données et options peut finir par entraîner des erreurs. Et si cela ne suffit pas à vous convaincre de l’éviter, voici une meilleure raison : elle peut exposer votre application à une vulnérabilité d’exécution de code à distance.

Les templates EJS que vous compilez peuvent inclure d’autres fichiers à l’aide d’une directive include.

<%- include('path/to/include'); %>

Par défaut, ces inclusions sont relatives au template. Si celui-ci se trouve dans le dossier templates, EJS cherchera le fichier à inclure dans templates/path/to/include.

L’option de configuration root vous permet notamment de modifier l’emplacement par défaut à partir duquel ces fichiers sont inclus.

Cela ne pose pas de problème lorsque les options sont transmises dans un argument distinct, mais cela en devient un si vous regroupez options et données dans un seul objet. Si la méthode transmet une liste de données fournies par l’utilisateur, un attaquant peut aussi intercepter la requête et injecter une option root .

ejs.renderFile('my-template', {root:'/bad/root/'}, callback);

En transmettant la directive root dans la ligne ci-dessus, toutes les inclusions proviendraient désormais de /bad/root au lieu du chemin prévu, ce qui entraînerait une exécution de code à distance.

La possibilité de configurer la racine peut être utile aux développeurs qui utilisent le moteur EJS, mais permettre de le faire dans un objet contenant également des données utilisateur présente un risque de sécurité important. Le développeur pourrait certes prendre des mesures pour assainir les entrées, mais le moteur resterait vulnérable par défaut.

Notre équipe de sécurité a découvert le problème et l’a signalé le 27 novembre. Le responsable du projet, Matthew Eernisse, a préparé un correctif simple qui interdit l’option root afin qu’elle ne puisse pas être incluse avec les données utilisateur.

Il arrive souvent que des vulnérabilités ne soient pas corrigées longtemps après leur signalement initial. Rappelez-vous la vulnérabilité XSS dans Marked : il a fallu plus d’un an pour la corriger. Heureusement, ce n’était pas le cas ici. Grâce à une publication remarquablement rapide de Matthew, la vulnérabilité a été corrigée un jour seulement après son signalement. La version 2.5.3 d’EJS, publiée le 28 novembre, inclut le correctif.

Comment corriger le problème

Si vous avez demandé à Snyk de surveiller votre projet et qu’il utilise EJS, vous avez probablement déjà reçu une alerte concernant ce problème. Vous pouvez corriger la vulnérabilité en utilisant l’intégration GitHub pour générer une pull request depuis votre tableau de bord, ou en exécutant snyk wizard depuis l’interface en ligne de commande. Dans les deux cas, Snyk détectera le problème et vous invitera à mettre à jour le package EJS vers la dernière version.

Vous n’utilisez pas Snyk ? Pas de souci, on vous aime quand même. Vous pouvez corriger le problème en mettant manuellement EJS à jour vers la dernière version. Pensez également à vérifier toutes vos dépendances. Si l’une d’elles inclut le package EJS, celui-ci n’apparaîtra pas dans votre fichier package.json et la mise à jour pourrait être bien plus complexe.

Lancez-vous dans les compétitions Capture The Flag

Apprenez à résoudre des défis Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.