
Corriger la vulnérabilité de pollution de prototype (CVE-2023-26136) pour le package tough-cookie
La pollution des prototypes est une vulnérabilité JavaScript qui permet à un attaquant d'ajouter des propriétés arbitraires aux prototypes d'objets globaux, lesquelles peuvent ensuite être héritées par des objets définis par l'utilisateur. Une source de pollution des prototypes est toute entrée contrôlable par l'utilisateur qui permet d'ajouter des propriétés arbitraires aux objets prototypes. Les sources les plus courantes sont les suivantes : URL JSON Messages Web
Pour le paquet tough-cookies (v2.5.0), la première via l'URL est plus pertinente. Cela se produit comme suit :
Voici une requête :
https://vulnerable-website.com/?__proto__[badProperty]=payload
Lors de la décomposition de la chaîne de requête en paires clé:valeur, un analyseur d'URL peut interpréter proto comme une chaîne arbitraire.
À un moment donné, l'opération de fusion récursive peut assigner la valeur d'evilProperty à l'aide d'une instruction équivalente à la suivante :
targetObject.__proto__.badProperty = 'payload';
__proto__ a un usage spécial en JavaScript. Comme nous le savons, si pour un objet une propriété P1 n'est pas trouvée, elle sera recherchée dans le prototype de cet objet.
Exemple
function myClass() {
this.P1 = 'value';
}
let mc = new myClass();
console.log(mc.P1); //Value
console.log(mc.P2); //Undefined
mc.__proto__.P2 = 'value2';
let mc2 = new myClass();
console.log(mc.P2); //value2
Après avoir modifié __proto__, toutes les instances créées de myClass auront la propriété P2.
Pour le paquet tough-cookies (v2.5.0), cette vulnérabilité de pollution des prototypes peut être observée à partir de l'extrait de code suivant :
await new Promise((resolve, reject) => {
cookiejar.setCookie(
"Slonser=polluted; Domain=__proto__; Path=/notauth",
"https://__proto__/admin",
{ loose: true },
(err, cookie) => {
if (err) {
reject(err);
} else {
resolve(cookie);
}
}
);
});
Il a été constaté que la classe CookieJar utilise MemoryCookieStore comme magasin par défaut. Et dans plusieurs méthodes de MemoryCookieStore, les objets sont initialisés comme suit :
this.idx = {};
Cela signifie que des propriétés avec des valeurs (qui peuvent être problématiques) peuvent être ajoutées au prototype de this.idx via __proto__. Pour éviter cela, l'initialisation a été modifiée à plusieurs endroits comme suit :
this.idx = Object.create(null);
Cela crée un objet vide sans prototype. Un test a été ajouté memstore_vulnerability_fix_test.js vérifiant le correctif.