Vulnerabilidad Prototype pollution
www.onlinetis.com
La vulnerabilidad de Prototype pollution es un tipo de vulnerabilidad que afecta a lenguajes de programación basados en prototipos, principalmente JavaScript. Ocurre cuando un atacante puede inyectar propiedades en el prototipo base de un objeto (Object.prototype
), que es el objeto del que heredan todos los demás objetos. Esto puede llevar a la ejecución de código arbitrario, la modificación de la lógica de la aplicación, o la denegación de servicio. 😈
¿Cómo funciona?
En JavaScript, cada objeto tiene una propiedad interna __proto__
que apunta al prototipo del objeto del que hereda. A su vez, el objeto base de toda la jerarquía de herencia es Object.prototype
.
Un ataque de Prototype pollution explota la falta de validación o la mala implementación en funciones que combinan o manipulan objetos. Un atacante puede enviar datos maliciosos que contienen una clave __proto__
con una propiedad adicional.
Por ejemplo, si una aplicación tiene una función que combina dos objetos de forma recursiva:
function extend(target, source) {
for (let key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
if (typeof source[key] === 'object' && source[key] !== null) {
if (!target[key]) target[key] = {};
extend(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
}
Un atacante podría enviar una entrada como {"__proto__": {"isAdmin": true}}
. La función extend
combinaría esta entrada con el prototipo base, resultando en que Object.prototype
ahora tiene una propiedad isAdmin
con el valor true
.
A partir de ese momento, cualquier objeto creado o que se compruebe para la propiedad isAdmin
tendrá un valor verdadero, lo que podría permitirle al atacante escalar privilegios.
Impacto de la vulnerabilidad
El impacto de un ataque de Prototype pollution puede ser significativo y variar según el contexto de la aplicación:
Denegación de servicio (DoS): Un atacante puede inyectar una propiedad que cause un error fatal en una parte crítica de la aplicación. Por ejemplo, al sobreescribir una función nativa del lenguaje, se podría romper la funcionalidad del sitio para todos los usuarios.
Escalada de privilegios: Al inyectar una propiedad como
isAdmin: true
en el prototipo, un atacante podría engañar a la lógica de la aplicación para que le conceda permisos de administrador.Ejecución de código remoto (RCE): En algunos casos, un atacante podría inyectar una propiedad que modifique la configuración de un framework o biblioteca, permitiendo la ejecución de comandos del sistema.
Cómo prevenirla
La prevención de Prototype pollution se basa en el manejo cuidadoso de los objetos y la validación de la entrada del usuario.
Validar y limpiar la entrada del usuario: Es la medida más importante. Nunca confíes en los datos recibidos de una fuente externa. Asegúrate de que las claves de los objetos no incluyan nombres reservados como
__proto__
.Utilizar
Object.create(null)
: Al crear objetos que se van a manipular con datos del usuario, utilizaObject.create(null)
para crear un objeto que no tenga prototipo. Esto evita que los datos maliciosos se extiendan aObject.prototype
.Evitar la combinación recursiva de objetos: Las funciones que fusionan objetos de forma profunda son las que más riesgo tienen. Si es necesario, utiliza bibliotecas bien probadas o verifica que no se procesen propiedades como
__proto__
oconstructor
.Congelar el prototipo: Aunque no es una solución completa, puedes congelar
Object.prototype
conObject.freeze(Object.prototype)
para evitar la adición o modificación de propiedades. Sin embargo, esto puede causar efectos secundarios en otras bibliotecas.