El XSS basado en DOM es una subsección de los ataques basados en DOM. Sin embargo, es la forma más potente de ataques basados en DOM, ya que permite inyectar código JavaScript y tomar control total del navegador. Como con todos los ataques basados en DOM, necesitamos una source y un sink para realizarlo.

La source más común para los ataques XSS basados en DOM es la URL, y más específicamente, fragmentos URL, los cuales son accedidos a través de la source window.location. Esto es porque tenemos la habilidad de construir links con fragmentos maliciosos para mandar a los usuarios. En la mayoría de casos, los fragmentos no son interpretados por el servidor sino reflejados en la respuesta, llevando a ataques XSS basados en DOM. Debe tenerse en cuenta que la mayoría de los navegadores modernos realizarán encoding URL de la información, lo que puede prevenir el ataque. Esto ha llevado a una pérdida de relevancia de este tipo de ataques a través de la source URL. Veamos un ejemplo de cómo un fragmento en la URL puede ser usado como source.


XSS Basado en DOM vía jQuery

Continuando con nuestro ejemplo de la localización de la página web, miremos el siguiente ejemplo de jQuery para navegar dicha página a la última localización vista:

javascript
$(window).on('hashchange', function() {
	var element = $(location.hash);
	element[0].scrollIntoView();
});

Como el valor del hash es una source a la que tenemos acceso, podemos inyectar un payload XSS en el selector link $() de la jQuery.. Por ejemplo:

https://realwebsite.com#<img src=1 onerror=alert(1)</img>

Sin embargo, esto sólo nos permitiría hacernos XSS a nosotros mismos. Para realizar XSS en otros usuarios, necesitamos encontrar una manera de disparar la función hashchange automáticamente. La opción más simple sería aprovechar un iFrame para depositar nuestro payload:

<iframe src="https://realwebsite.com#" onload="this.src+='<img src=1 onerror=alert(1)>'

Una vez se cargue la página web, el valor src se actualiza para incluir nuestro payload, disparando la función hashchange y por tanto nuestro payload XSS.

Este es un ejemplo de cómo se puede realizar XSS. Sin embargo, otros varios sinks podrían usarse. Esto incluye sinks JavaScript normales y específicos de frameworks como los de jQuery y Angular. Para una lista completa de los sinks disponibles visita esta página. Como se muestra, la parte complicada es la armamentización de ataques XSS basados en DOM. Sin la armamentización correcta, estamos únicamente haciéndonos XSS a nosotros mismos. Por suerte la armamentización puede realizarse mediante los canales XSS convencionales.


XSS Basado en DOM vs XSS Convencional

Cuando buscas XSS, aunque pueda parecer ser XSS normal, stored, o reflejado, en algunos casos puede serlo. La diferencia clave está en dónde reside el sink. Si el input del usuario se inyecta en el sink del lado del servidor y la respuesta contiene el payload, se convierte en XSS convencional. Sin embargo, si el DOM está completamente cargado y recibe input del usuario sin validación a través de JavaScript, es basado en DOM. Aunque no hay diferencia en cómo se explota, hay diferencia en cómo debe remediarse.