Skip to main content

In this article

Cómo corregir una vulnerabilidad que permite eludir la protección contra la sobrescritura de prototipos en qs

Escrito por
Headshot of Tim Kadlec

Tim Kadlec

14 de marzo de 2017

0 minutos de lectura

El mes pasado, agregamos a nuestra base de datos una vulnerabilidad de alta gravedad que permite eludir la protección contra la sobrescritura de prototipos en el paquete qs. La corrección se publicó hace aproximadamente una semana en versiones actualizadas de la biblioteca. En esta publicación explicamos la vulnerabilidad y cómo mitigarla.

qs es un popular paquete de npm —con poco menos de 40 millones de descargas durante el último mes— que se usa para convertir parámetros de cadenas de consulta en objetos. Por ejemplo:

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

Aunque esto es muy útil, donde qs realmente destaca es en las funciones avanzadas que ofrece. Con qs, incluso puedes crear objetos anidados dentro de tus cadenas de consulta usando corchetes ([ o ]).

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

La posibilidad de crear objetos anidados dentro de los parámetros de tus cadenas de consulta también implica ciertos riesgos. Si no se validan correctamente, podrías sobrescribir propiedades del prototipo del objeto. Por ejemplo, podrías intentar sobrescribir el método hasOwnProperty del objeto:

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

Por suerte, lo anterior no funcionaría. De forma predeterminada, qs ignora los parámetros (como hasOwnProperty) que sobrescribirían las propiedades del prototipo del objeto. Para hacerlo, comprueba si hay corchetes de apertura y cierre en el parámetro, extrae el fragmento que está dentro y luego lo compara con el prototipo del objeto para determinar si es una propiedad nativa. Existe una opción para permitir la sobrescritura de prototipos, pero qs recomienda encarecidamente no hacerlo.

Lamentablemente, una brecha en la validación permitía seguir sobrescribiendo una propiedad del prototipo del objeto si se anteponía al parámetro un carácter [ o ] sin pareja.

Por ejemplo, lo siguiente sobrescribiría el método hasOwnProperty del objeto, aunque le hayamos indicado explícitamente a qs que no permita la sobrescritura de prototipos:

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

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

Lo más probable es que esto cause errores y fragilidad inesperada en tu aplicación, pero, según la lógica de la aplicación, las consecuencias podrían ser mucho más graves: incluso podría permitir que los atacantes alteraran el flujo de ejecución de la aplicación.

La corrección

Nuestro equipo de investigación de seguridad descubrió el problema el 13 de febrero y se lo reportó al responsable del paquete. El responsable actuó rápidamente y publicó una corrección tres días después en las versiones 6.0.3, 6.1.1, 6.2.2 y 6.3.1.

La corrección resolvió el problema cuando el parámetro comenzaba con ]=, pero no fue suficiente: resultó que qs seguía siendo vulnerable si el atacante usaba [=. Por eso, el responsable del paquete actualizó la lógica y publicó una corrección más robusta en las versiones 6.4.0, 6.3.2, 6.2.3, 6.1.2 y 6.0.4.

Para resolver el problema, tendrás que actualizar el paquete a una de estas versiones. Si usas Snyk para monitorear tu proyecto, probablemente ya recibiste una indicación para realizar la actualización, ya sea mediante una solicitud de incorporación de cambios generada automáticamente o ejecutando snyk wizard desde la CLI.

De lo contrario, tendrás que revisar tu aplicación para verificar si usas el paquete qs, ya sea como dependencia directa indicada en el archivo package.json o como dependencia indirecta que incorpora alguna de tus dependencias directas, y actualizarlo a la versión más reciente.