
Corrige la vulnerabilidad de contaminación de prototipos (CVE-2023-26136) para el paquete tough-cookie
La contaminación de prototipos es una vulnerabilidad de JavaScript que permite a un atacante agregar propiedades arbitrarias a los prototipos de objetos globales, que luego pueden ser heredadas por objetos definidos por el usuario. Una fuente de contaminación de prototipos es cualquier entrada controlable por el usuario que permita agregar propiedades arbitrarias a objetos prototipo. Las fuentes más comunes son las siguientes: URL JSON Mensajes web
Para el paquete tough-cookies (v2.5.0) la más relevante es la primera, a través de URL. Ocurre de la siguiente manera:
Aquí una solicitud:
https://vulnerable-website.com/?__proto__[badProperty]=payload
Al descomponer la cadena de consulta en pares clave:valor, un analizador de URL puede interpretar __proto__ como una cadena arbitraria.
En algún momento, la operación de fusión recursiva puede asignar el valor de evilProperty usando una declaración equivalente a la siguiente:
targetObject.__proto__.badProperty = 'payload';
__proto__ tiene un uso especial en JavaScript. Como sabemos, si para algún objeto una propiedad P1 no se encuentra, se buscará en el prototipo de ese objeto.
Ejemplo
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
Después de cambiar __proto__, todas las instancias creadas de myClass tendrán la propiedad P2.
Para el paquete tough-cookies (v2.5.0), esta vulnerabilidad de contaminación de prototipos se puede ver en el fragmento de código:
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);
}
}
);
});
Se descubrió que la clase CookieJar utiliza MemoryCookieStore como almacenamiento predeterminado. Y en varios métodos de MemoryCookieStore, los objetos se inicializan de la siguiente manera:
this.idx = {};
Esto significa que para this.idx se pueden agregar propiedades con valores (que pueden ser valores problemáticos) a través de __proto__. Para evitar esto, en varios lugares se cambió la inicialización de la siguiente manera:
this.idx = Object.create(null);
Esto crea un objeto vacío sin prototipo. Se agregó una prueba, memstore_vulnerability_fix_test.js, que verifica la corrección.