Skip to main content

In this article

Correction d’une vulnérabilité permettant de contourner la protection contre la modification du prototype dans qs

Écrit par
Headshot of Tim Kadlec

Tim Kadlec

14 mars 2017

0 minutes de lecture

Le mois dernier, nous avons ajouté à notre base de données une vulnérabilité de gravité élevée permettant de contourner la protection contre la modification du prototype dans le package qs. Le correctif a été publié dans des versions mises à jour de la bibliothèque il y a environ une semaine. Cet article présente la vulnérabilité et explique comment y remédier.

qs est un package npm très populaire — un peu moins de 40 millions de téléchargements au cours du mois dernier — qui sert à convertir des paramètres de chaîne de requête en objets. Par exemple :

qs.parse('a=b&c=d');
// {a:'b', c: 'd'}

Cette fonctionnalité est certainement utile, mais qs se distingue surtout par les possibilités avancées qu’il offre. Avec qs, vous pouvez même créer des objets imbriqués dans vos chaînes de requête en utilisant des crochets ([ ou ]).

qs.parse('a[b]=c');
// {
//   a: {
//     b: "c"
//   }
// }

La possibilité de créer des objets imbriqués dans les paramètres de vos chaînes de requête comporte certains risques. Si vous ne les vérifiez pas correctement, vous pourriez écraser des propriétés du prototype de l’objet. Par exemple, vous pourriez tenter d’écraser la méthode hasOwnProperty de l’objet :

qs.parse('a[hasOwnProperty]=b');

Heureusement, l’exemple ci-dessus ne fonctionnerait pas. Par défaut, qs ignore tous les paramètres (comme hasOwnProperty) susceptibles d’écraser des propriétés du prototype de l’objet. Pour ce faire, il vérifie la présence de crochets ouvrants et fermants dans le paramètre, récupère le contenu entre les deux, puis le compare au prototype de l’objet pour déterminer s’il s’agit d’une propriété native. Une option permet d’autoriser la modification du prototype, mais qs le déconseille fortement.

Malheureusement, une faille dans la validation permettait tout de même d’écraser une propriété du prototype de l’objet en faisant précéder le paramètre d’un caractère [ ou ] sans crochet correspondant.

Par exemple, le code suivant écraserait la méthode hasOwnProperty de l’objet, même si nous avons explicitement indiqué à qs de ne pas autoriser la modification du prototype :

var paramData = qs.parse("]=hasOwnProperty", { allowPrototypes: false });
// {hasOwnProperty = true}

paramData.hasOwnProperty('toString');
// Results in Type Error: paramData.hasOwnProperty is not a function

Le résultat le plus probable serait un dysfonctionnement de votre application et un comportement imprévisible, mais selon sa logique, les conséquences pourraient être bien plus graves : dans certains cas, des attaquants pourraient même modifier le flux d’exécution de votre application.

Le correctif

Notre équipe de recherche en sécurité a découvert le problème le 13 février et l’a signalé au responsable du package. Celui-ci a rapidement publié un correctif, trois jours plus tard, dans les versions 6.0.3, 6.1.1, 6.2.2 et 6.3.1.

Le correctif résolvait le problème lorsque le paramètre commençait par ]=, mais cela ne suffisait pas : il s’est avéré que qs restait vulnérable si l’attaquant utilisait [=. Le responsable du package a donc mis à jour la logique et publié un correctif plus robuste dans les versions 6.4.0, 6.3.2, 6.2.3, 6.1.2 et 6.0.4.

Pour résoudre le problème, vous devez mettre à jour le package vers l’une de ces versions. Si vous utilisez Snyk pour surveiller votre projet, vous avez probablement déjà été invité à effectuer la mise à jour, soit au moyen d’une demande de tirage générée automatiquement, soit en exécutant snyk wizard à l’aide de l’interface CLI.

Sinon, vérifiez si votre application utilise le package qs, que ce soit comme dépendance directe répertoriée dans votre fichier package.json ou comme dépendance non répertoriée incluse par l’une de vos dépendances directes, puis mettez-le à jour vers la dernière version.