
Behebt die Prototype-Pollution-Schwachstelle (CVE-2023-26136) für das tough-cookie-Paket
Prototype Pollution ist eine JavaScript-Sicherheitslücke, die es einem Angreifer ermöglicht, beliebige Eigenschaften zu globalen Objektprototypen hinzuzufügen, die dann von benutzerdefinierten Objekten geerbt werden können. Eine Prototype-Pollution-Quelle ist jede benutzerkontrollierbare Eingabe, die es ermöglicht, beliebige Eigenschaften zu Prototypobjekten hinzuzufügen. Die häufigsten Quellen sind: URL JSON Web Messages
Für das tough-cookies-Paket (v2.5.0) ist die erste Quelle per URL relevanter. Es geschieht wie folgt:
Hier eine Beispielanfrage:
https://vulnerable-website.com/?__proto__[badProperty]=payload
Beim Zerlegen der Abfragezeichenfolge in Schlüssel-Wert-Paare kann ein URL-Parser __proto__ als beliebige Zeichenkette interpretieren.
Irgendwann kann die rekursive Merge-Operation den Wert von evilProperty mit einer Anweisung zuweisen, die der folgenden entspricht:
targetObject.__proto__.badProperty = 'payload';
__proto__ hat eine spezielle Verwendung in JavaScript. Wie wir wissen, wird, wenn für ein Objekt eine Eigenschaft P1 nicht gefunden wurde, im Prototyp dieses Objekts danach gesucht.
Beispiel
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
Nach Änderung von __proto__ haben alle erstellten Instanzen von myClass die Eigenschaft P2.
Für das tough-cookies-Paket (v2.5.0) ist diese Prototype-Pollution-Sicherheitslücke aus dem folgenden Code-Ausschnitt ersichtlich:
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);
}
}
);
});
Es wurde festgestellt, dass die CookieJar-Klasse standardmäßig MemoryCookieStore als Speicher verwendet. Und in mehreren Methoden von MemoryCookieStore werden Objekte wie folgt initialisiert:
this.idx = {};
Das bedeutet, dass für this.idx über __proto__ Eigenschaften mit Werten (die problematisch sein können) zum Prototyp hinzugefügt werden können. Um dies zu verhindern, wurde an mehreren Stellen die Initialisierung wie folgt geändert:
this.idx = Object.create(null);
Dies erstellt ein leeres Objekt ohne Prototyp. Es wurde ein Test memstore_vulnerability_fix_test.js hinzugefügt, der die Korrektur überprüft.