NodeJS - __proto__ & prototype Pollution
Objetos en JavaScript
Los objetos en JavaScript son esencialmente colecciones de pares clave-valor, conocidos como propiedades. Un objeto puede crearse utilizando Object.create
con null
como argumento para producir un objeto vacío. Este método permite la creación de un objeto sin ninguna propiedad heredada.
Un objeto vacío es similar a un diccionario vacío, representado como {}
.
Funciones y Clases en JavaScript
En JavaScript, las clases y las funciones están estrechamente vinculadas, con las funciones a menudo sirviendo como constructores para las clases. A pesar de la falta de soporte nativo de clases en JavaScript, los constructores pueden emular el comportamiento de una clase.
Prototipos en JavaScript
JavaScript permite la modificación, adición o eliminación de atributos de prototipo en tiempo de ejecución. Esta flexibilidad permite la extensión dinámica de las funcionalidades de una clase.
Funciones como toString
y valueOf
pueden ser alteradas para cambiar su comportamiento, demostrando la naturaleza adaptable del sistema de prototipos de JavaScript.
Herencia
En la programación basada en prototipos, las propiedades/métodos son heredados por objetos de clases. Estas clases se crean añadiendo propiedades/métodos a una instancia de otra clase o a un objeto vacío.
Cabe destacar que cuando se añade una propiedad a un objeto que sirve como prototipo para otros objetos (como myPersonObj
), los objetos que heredan obtienen acceso a esta nueva propiedad. Sin embargo, esta propiedad no se muestra automáticamente a menos que se invoque explícitamente.
Contaminación de __proto__
Explorando la Contaminación de Prototipos en JavaScript
Los objetos de JavaScript están definidos por pares clave-valor y heredan del prototipo de objeto de JavaScript. Esto significa que alterar el prototipo de Object puede influir en todos los objetos en el entorno.
Vamos a usar un ejemplo diferente para ilustrar:
El acceso al prototipo de Object es posible a través de:
Al agregar propiedades al prototipo Object, todos los objetos de JavaScript heredarán estas nuevas propiedades:
contaminación de prototipos
Para un escenario donde el uso de __proto__
está restringido, modificar el prototipo de una función es una alternativa:
Esto afecta solo a los objetos creados a partir del constructor Vehicle
, dándoles las propiedades beep
, hasWheels
, honk
e isElectric
.
Dos métodos para afectar globalmente a los objetos JavaScript a través de la contaminación del prototipo incluyen:
Contaminando directamente el
Object.prototype
:
Contaminando el prototipo de un constructor para una estructura comúnmente utilizada:
Después de estas operaciones, cada objeto JavaScript puede ejecutar los métodos goodbye
y greet
.
Contaminando otros objetos
De una clase a Object.prototype
En un escenario donde puedes contaminar un objeto específico y necesitas llegar a Object.prototype
puedes buscarlo con algo similar al siguiente código:
Contaminación de elementos de un array
Tenga en cuenta que al igual que puede contaminar atributos de objetos en JS, si tiene acceso para contaminar un array, también puede contaminar los valores del array accesibles por índices (tenga en cuenta que no puede sobrescribir valores, por lo que necesita contaminar índices que de alguna manera se utilicen pero no se escriban).
Contaminación de elementos Html
Al generar un elemento HTML a través de JS, es posible sobrescribir el atributo innerHTML
para hacer que escriba código HTML arbitrario. Idea y ejemplo de este informe.
Ejemplos
Ejemplo Básico
Una contaminación de prototipo ocurre debido a una falla en la aplicación que permite sobrescribir propiedades en Object.prototype
. Esto significa que dado que la mayoría de los objetos derivan sus propiedades de Object.prototype
El ejemplo más sencillo es agregar un valor a un atributo no definido de un objeto que va a ser verificado, como:
Si el atributo admin
está sin definir, es posible abusar de una PP y establecerlo en Verdadero con algo como:
El mecanismo detrás de esto implica manipular propiedades de tal manera que si un atacante tiene control sobre ciertas entradas, pueden modificar el prototipo de todos los objetos en la aplicación. Esta manipulación típicamente implica establecer la propiedad __proto__
, que, en JavaScript, es sinónimo de modificar directamente el prototipo de un objeto.
Las condiciones bajo las cuales este ataque puede ejecutarse con éxito, como se describe en un estudio específico, incluyen:
Realizar una fusión recursiva.
Definir propiedades basadas en una ruta.
Clonar objetos.
Función de anulación
Contaminación de Prototipos a RCE
pagePrototype Pollution to RCEOtros payloads:
Contaminación de prototipos del lado del cliente a XSS
pageClient Side Prototype PollutionCVE-2019–11358: Ataque de contaminación de prototipos a través de jQuery $ .extend
Para más detalles, consulta este artículo En jQuery, la función $ .extend
puede llevar a la contaminación de prototipos si se utiliza incorrectamente la función de copia profunda. Esta función se usa comúnmente para clonar objetos o fusionar propiedades de un objeto predeterminado. Sin embargo, cuando está mal configurada, las propiedades destinadas a un nuevo objeto pueden asignarse al prototipo en su lugar. Por ejemplo:
Esta vulnerabilidad, identificada como CVE-2019–11358, ilustra cómo una copia profunda puede modificar inadvertidamente el prototipo, lo que lleva a posibles riesgos de seguridad, como acceso de administrador no autorizado si propiedades como isAdmin
se verifican sin una verificación de existencia adecuada.
CVE-2018–3721, CVE-2019–10744: Ataque de polución de prototipos a través de lodash
Para más detalles consulta este artículo
Lodash encontró vulnerabilidades similares de polución de prototipos (CVE-2018–3721, CVE-2019–10744). Estos problemas se abordaron en la versión 4.17.11.
Otro tutorial con CVEs
Herramientas para detectar la Polución de Prototipos
Server-Side-Prototype-Pollution-Gadgets-Scanner: Extensión de Burp Suite diseñada para detectar y analizar vulnerabilidades de polución de prototipos en el lado del servidor en aplicaciones web. Esta herramienta automatiza el proceso de escaneo de solicitudes para identificar posibles problemas de polución de prototipos. Explota gadgets conocidos, métodos para aprovechar la polución de prototipos para ejecutar acciones dañinas, centrándose particularmente en las bibliotecas de Node.js.
server-side-prototype-pollution: Esta extensión identifica vulnerabilidades de polución de prototipos en el lado del servidor. Utiliza técnicas descritas en la polución de prototipos en el lado del servidor.
Polución de Prototipos AST en NodeJS
NodeJS utiliza extensamente Árboles de Sintaxis Abstracta (AST) en JavaScript para funcionalidades como motores de plantillas y TypeScript. Esta sección explora las vulnerabilidades relacionadas con la polución de prototipos en motores de plantillas, específicamente Handlebars y Pug.
Análisis de Vulnerabilidad de Handlebars
El motor de plantillas Handlebars es susceptible a un ataque de polución de prototipos. Esta vulnerabilidad surge de funciones específicas dentro del archivo javascript-compiler.js
. La función appendContent
, por ejemplo, concatena pendingContent
si está presente, mientras que la función pushSource
restablece pendingContent
a undefined
después de agregar la fuente.
Proceso de Explotación
La explotación aprovecha el AST (Árbol de Sintaxis Abstracta) producido por Handlebars, siguiendo estos pasos:
Manipulación del Analizador: Inicialmente, el analizador, a través del nodo
NumberLiteral
, obliga a que los valores sean numéricos. La polución de prototipos puede eludir esto, permitiendo la inserción de cadenas no numéricas.Manejo por el Compilador: El compilador puede procesar un Objeto AST o una plantilla de cadena. Si
input.type
es igual aProgram
, la entrada se trata como preanalizada, lo que puede ser explotado.Inyección de Código: A través de la manipulación de
Object.prototype
, se puede inyectar código arbitrario en la función de plantilla, lo que puede llevar a la ejecución remota de código.
Un ejemplo que demuestra la explotación de la vulnerabilidad de Handlebars:
Este código muestra cómo un atacante podría inyectar código arbitrario en una plantilla de Handlebars.
Referencia Externa: Se encontró un problema relacionado con la contaminación de prototipos en la biblioteca 'flat', como se detalla aquí: Issue on GitHub.
Referencia Externa: Problema relacionado con la contaminación de prototipos en la biblioteca 'flat'
Ejemplo de explotación de contaminación de prototipos en Python:
Vulnerabilidad de Pug
Pug, otro motor de plantillas, enfrenta un riesgo similar de contaminación de prototipos. La información detallada está disponible en la discusión sobre Inyección AST en Pug.
Ejemplo de contaminación de prototipos en Pug:
Medidas Preventivas
Para reducir el riesgo de la contaminación del prototipo, se pueden emplear las estrategias enumeradas a continuación:
Inmutabilidad de Objetos: El
Object.prototype
puede hacerse inmutable aplicandoObject.freeze
.Validación de Entradas: Las entradas JSON deben ser rigurosamente validadas contra el esquema de la aplicación.
Funciones de Fusión Seguras: Se debe evitar el uso inseguro de funciones de fusión recursivas.
Objetos sin Prototipo: Se pueden crear objetos sin propiedades de prototipo utilizando
Object.create(null)
.Uso de Mapas: En lugar de
Object
, se debe usarMap
para almacenar pares clave-valor.Actualizaciones de Bibliotecas: Se pueden incorporar parches de seguridad actualizando regularmente las bibliotecas.
Herramientas de Linter y Análisis Estático: Utilice herramientas como ESLint con complementos apropiados para detectar y prevenir vulnerabilidades de contaminación del prototipo.
Revisiones de Código: Implemente revisiones de código exhaustivas para identificar y remediar posibles riesgos relacionados con la contaminación del prototipo.
Formación en Seguridad: Eduque a los desarrolladores sobre los riesgos de la contaminación del prototipo y las mejores prácticas para escribir código seguro.
Uso Cauteloso de Bibliotecas: Sea cauteloso al usar bibliotecas de terceros. Evalúe su postura de seguridad y revise su código, especialmente aquellos que manipulan objetos.
Protección en Tiempo de Ejecución: Emplee mecanismos de protección en tiempo de ejecución, como el uso de paquetes npm centrados en la seguridad que pueden detectar y prevenir ataques de contaminación del prototipo.
Referencias
Última actualización