Cómo mitigar los ataques de DOM clobbering en JavaScript
Keshav Malik
7 de agosto de 2023
0 minutos de lecturaEl modelo de objetos del documento (DOM) actúa como interfaz entre HTML y JavaScript, y conecta el contenido estático con la interactividad dinámica. Esta función hace que el DOM sea indispensable para los desarrolladores web modernos.
Sin embargo, el DOM tiene un inconveniente: el DOM clobbering. Este ocurre cuando los elementos HTML entran en conflicto con variables o funciones globales de JavaScript, lo que puede provocar un comportamiento inesperado y crear una posible vulnerabilidad de seguridad en tu aplicación web.
Para abordar este problema, se necesitan prácticas de programación rigurosas, conocimientos sólidos de JavaScript y una comprensión firme de la seguridad de las aplicaciones web. En este artículo se explora el concepto de DOM clobbering y se presentan estrategias para crear aplicaciones web más seguras y sólidas.
Cómo se produce el DOM clobbering
Cada elemento HTML puede tener un atributo ID o name único que permite hacer referencia fácilmente a elementos específicos en JavaScript. Por ejemplo, el siguiente botón HTML tiene un atributo ID con el valor "myButton":
Podemos usar este ID en nuestro código JavaScript para manipular el botón; por ejemplo, para cambiar el texto cuando se hace clic:
El DOM facilita esta interacción entre HTML y JavaScript. Pero ¿qué sucede si el atributo ID o name del elemento HTML entra en conflicto con una variable o función global de JavaScript?
Cuando un navegador carga una página HTML, crea automáticamente variables globales de JavaScript para cada atributo ID y name del DOM HTML. Si tenemos un elemento HTML llamado "myButton", el navegador crea la variable global de JavaScript myButton, que hace referencia a ese elemento HTML.
Ahora, pensemos en una situación en la que declaramos una función de JavaScript llamada myButton:
Pero también tenemos un elemento HTML con el ID o name "myButton". Cuando se carga la página, el proceso automático del navegador sobrescribe la función de JavaScript myButton con una referencia al elemento HTML:
Este proceso es el DOM clobbering y puede causar un comportamiento impredecible y vulnerabilidades de seguridad. Si un atacante puede controlar los atributos, podría inyectar código malicioso en la página web y provocar problemas de seguridad como cross-site scripting (XSS).
Veamos un ejemplo:
Un atacante podría escribir algo como <img id='alert' src=x onerror='alert(1)'>, para crear un nuevo componente HTML con un 'id' de 'alert'. Este componente reemplaza —o sobrescribe— la función alert normal de JavaScript. La próxima vez que el sitio web intente usar esta función, no funcionará correctamente e incluso podría ejecutar código malicioso.
Cómo identificar vulnerabilidades de DOM clobbering
Imagina una aplicación web básica con un formulario de comentarios. Los usuarios ingresan su nombre y un mensaje, y luego lo envían. La página muestra el comentario:
HTML:
JavaScript:
Este código toma el nombre y el comentario del usuario y los muestra en un elemento de párrafo dentro del div feedbackDisplay.
Un atacante podría aprovechar este código al enviar HTML en el formulario de comentarios. Por ejemplo, si ingresara el siguiente código en el campo name y enviara el formulario, la etiqueta de script reemplazaría el área donde se muestran los comentarios:
Cuando el formulario intente mostrar el siguiente comentario, ejecutará el script en su lugar y redirigirá al usuario a un sitio web malicioso.
Esta situación crea una vulnerabilidad porque la aplicación usa los datos ingresados por el usuario para crear HTML, lo que genera una etiqueta de script con el mismo ID que un elemento existente. Este es un ejemplo de DOM clobbering con consecuencias graves: el atacante puede tomar el control del navegador del usuario y robar datos confidenciales o instalar malware.
Prácticas de programación segura para prevenir el DOM clobbering
Ahora que comprendemos mejor estas vulnerabilidades, veamos algunas prácticas recomendadas para mitigar el riesgo de DOM clobbering.
Delimita correctamente el alcance de las variables y funciones
Una de las causas más comunes del DOM clobbering es el uso incorrecto del alcance global en JavaScript. Si definimos variables y funciones dentro de un alcance específico, podemos limitar las sobrescrituras a ese alcance o a cualquier alcance anidado y minimizar los posibles conflictos.
Apliquemos las reglas de alcance de JavaScript y refactoricemos el ejemplo anterior para ver cómo hacerlo:
Nota: Usamos DOMPurify para sanitizar el HTML en el bloque de código anterior. Puedes instalarlo en Node.js con npm install dompurify. Inclúyelo en tu HTML con <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.3.3/purify.min.js"></script>.
En esta versión del código, encerramos todo en una expresión de función invocada inmediatamente (IIFE), que crea un nuevo alcance. Las variables form y feedbackElement, así como la función asignada al controlador de eventos onsubmit, no están en el alcance global, por lo que no se pueden sobrescribir mediante DOM clobbering.
Usa identificadores únicos
Asegurarte de que cada elemento de tu página web tenga un ID único reduce el riesgo de sobrescribir por accidente una función o variable importante. Además, evita usar nombres comunes o que puedan entrar en conflicto con objetos o funciones globales de JavaScript.
Evita contaminar el espacio de nombres global
Mantener limpio el espacio de nombres global es fundamental para escribir JavaScript seguro. Cuantas más variables y funciones haya en el alcance global, mayor será el riesgo de DOM clobbering. Usa el alcance de función de JavaScript o el alcance de bloque de ES6 para mantener tus variables y funciones contenidas. Aquí tienes un ejemplo con este último:
En este código, usamos un bloque (delimitado por {}) para crear un nuevo alcance. Ahora, todas las variables y funciones quedan limitadas a este bloque y no están en el alcance global.
Nota: Los ejemplos de código de esta guía están simplificados con fines demostrativos y no están pensados para usarse en un sitio web o una aplicación en producción.
Usa las funciones de JavaScript para mitigar el DOM clobbering
JavaScript moderno ofrece varias funciones que ayudan a minimizar el riesgo de DOM clobbering. En particular, las palabras clave let y const, que se introdujeron en ES6, ofrecen más control al declarar variables.
Tradicionalmente, declaramos variables de JavaScript con la palabra clave var. Sin embargo, var tiene algunas peculiaridades: una de ellas es que no tiene alcance de bloque, sino solo alcance de función y global. Esto significa que se puede acceder a una variable declarada con var y sobrescribirla fuera del bloque en el que se declaró.
Por otro lado, let y const tienen alcance de bloque, lo que significa que solo se puede acceder a ellas dentro del bloque en el que se declararon. Esta característica suele convertirlas en una mejor opción para declarar variables, ya que limita la posibilidad de que se sobrescriban.
También podemos usar const para declarar constantes, es decir, valores que no podemos cambiar después de asignarlos. Son otra herramienta útil para evitar cambios no deseados en variables importantes.
Veamos cómo implementar estas funciones en el código de nuestro formulario de comentarios para prevenir el DOM clobbering:
En este código, reemplazamos todos los usos de var por const. Limitamos todas las variables al bloque en el que las declaramos y las constantes no se pueden sobrescribir.
Recuerda que usar let y const no elimina el riesgo de DOM clobbering, pero sigue siendo una parte fundamental de la programación segura. Comprender e implementar estas funciones de JavaScript puede hacer que tus aplicaciones web sean más seguras.
Cómo monitorear y detectar vulnerabilidades de DOM clobbering
Las prácticas de programación segura pueden ayudar a prevenir el DOM clobbering, pero detectar las vulnerabilidades cuando aparecen es igual de importante. Veamos algunas herramientas y técnicas que pueden ayudar.
Análisis estático de código
Las herramientas de pruebas estáticas de seguridad de aplicaciones (SAST), como Snyk Code, pueden detectar eficazmente posibles vulnerabilidades de seguridad, incluido el DOM clobbering. Estas herramientas analizan el código fuente sin ejecutarlo e identifican patrones que podrían causar problemas de seguridad. La amplia cobertura de JavaScript de Snyk lo convierte en una excelente opción para los desarrolladores web.
Herramientas para desarrolladores del navegador
Las herramientas para desarrolladores del navegador, como las disponibles en Chrome o Firefox, pueden ser grandes aliadas para detectar vulnerabilidades de DOM clobbering.
Veamos brevemente cómo usar estas herramientas para identificar un posible problema:
En tu página web, haz clic con el botón derecho en cualquier lugar y selecciona Inspeccionar para abrir las herramientas para desarrolladores. También puedes usar Ctrl+Shift+I en Windows o Cmd+Option+I en macOS.
Ve a la pestaña Consola, donde se muestran los errores o registros de JavaScript.
Escribe “window” en la consola y presiona Enter para examinar el alcance global, con todas las variables y funciones globales. Busca variables que parezcan fuera de lugar, especialmente las que tengan el mismo nombre que los ID o nombres de tus elementos HTML.
Usa la pestaña Elementos para editar el HTML de la página, manipular el DOM y probar si hay posibles vulnerabilidades. Por ejemplo, agrega un elemento con un ID que coincida con una variable o función global para ver si se sobrescribe.
Conclusión
En este artículo explicamos cómo ocurre el DOM clobbering, los peligros asociados y cómo protegerse. Delimitar correctamente el alcance de las variables, usar identificadores únicos y elegir adecuadamente las funciones de JavaScript let y const son medidas fundamentales para mitigar esta vulnerabilidad.
Para mantener la seguridad del código, es necesario equilibrar las medidas de prevención y detección. Aplicar prácticas de programación recomendadas, usar las herramientas para desarrolladores del navegador y recurrir a una solución SAST como Snyk puede ayudar a identificar problemas existentes y posibles.
Al incorporar estas técnicas en tus aplicaciones JavaScript y mantenerte al día con las tendencias en seguridad de aplicaciones web, puedes adoptar un enfoque proactivo para proteger tus prácticas de programación.
Snyk para la seguridad de JavaScript
Desde la primera línea de código hasta la última dependencia de npm, Snyk protege tus aplicaciones de JavaScript directamente desde tu IDE, CLI y flujos de trabajo de Git.


