# Iframes в XSS, CSP та SOP {{#include ../../banners/hacktricks-training.md}} ## Iframes в XSS Є 3 способи вказати вміст сторінки в iframe: - Через `src`, вказуючи URL (URL може бути крос-доменним або того ж домену) - Через `src`, вказуючи вміст за допомогою протоколу `data:` - Через `srcdoc`, вказуючи вміст **Доступ до змінних батьківського та дочірнього контексту** ```html ``` ```html ``` Якщо ви отримуєте доступ до попереднього html через http сервер (наприклад, `python3 -m http.server`), ви помітите, що всі скрипти будуть виконані (оскільки немає CSP, що цьому перешкоджає). **батьківський контекст не зможе отримати доступ до змінної `secret` всередині жодного iframe** і **тільки iframes if2 та if3 (які вважаються такими, що належать до одного сайту) можуть отримати доступ до секрету** в оригінальному вікні.\ Зверніть увагу, що if4 вважається таким, що має `null` походження. ### Iframes з CSP > [!TIP] > Будь ласка, зверніть увагу, що в наступних обходах відповідь на iframe-сторінку не містить жодного заголовка CSP, який заважає виконанню JS. Значення `self` для `script-src` не дозволить виконання JS коду, використовуючи протокол `data:` або атрибут `srcdoc`.\ Однак навіть значення `none` для CSP дозволить виконання iframe, які вказують URL (повний або лише шлях) в атрибуті `src`.\ Отже, можливо обійти CSP сторінки за допомогою: ```html ``` Зверніть увагу, що **попередній CSP дозволяє виконання лише вбудованого скрипту**.\ Однак, **будуть виконані лише скрипти `if1` та `if2`, але лише `if1` зможе отримати доступ до батьківського секрету**. ![](<../../images/image (372).png>) Отже, можливо **обійти CSP, якщо ви можете завантажити JS файл на сервер і завантажити його через iframe, навіть з `script-src 'none'`**. Це **можливо також зробити, зловживаючи кінцевою точкою JSONP того ж сайту**. Ви можете протестувати це з наступним сценарієм, де куки викрадаються навіть з `script-src 'none'`. Просто запустіть додаток і отримайте до нього доступ через ваш браузер: ```python import flask from flask import Flask app = Flask(__name__) @app.route("/") def index(): resp = flask.Response('') resp.headers['Content-Security-Policy'] = "script-src 'self'" resp.headers['Set-Cookie'] = 'secret=THISISMYSECRET' return resp @app.route("/cookie_s.html") def cookie_s(): return "" if __name__ == "__main__": app.run() ``` ### Інші Payloads, знайдені в дикій природі ```html ``` ### Iframe sandbox Вміст в iframe може підлягати додатковим обмеженням за допомогою атрибута `sandbox`. За замовчуванням цей атрибут не застосовується, що означає, що обмеження не діють. Коли використовується, атрибут `sandbox` накладає кілька обмежень: - Вміст розглядається так, ніби він походить з унікального джерела. - Будь-яка спроба надсилання форм блокується. - Виконання скриптів заборонено. - Доступ до певних API вимкнено. - Запобігає взаємодії посилань з іншими контекстами перегляду. - Використання плагінів через ``, ``, `` або подібні теги заборонено. - Навігація верхнього рівня контексту перегляду вмістом сама по собі заборонена. - Функції, які запускаються автоматично, такі як відтворення відео або автоматичне фокусування елементів форм, блокуються. Значення атрибута можна залишити порожнім (`sandbox=""`), щоб застосувати всі вищезазначені обмеження. Альтернативно, його можна встановити на список специфічних значень, розділених пробілами, які звільняють iframe від певних обмежень. ```html ``` ### Credentialless iframes Як пояснено в [this article](https://blog.slonser.info/posts/make-self-xss-great-again/), прапорець `credentialless` в iframe використовується для завантаження сторінки всередині iframe без відправки облікових даних у запиті, зберігаючи при цьому політику одного походження (SOP) завантаженої сторінки в iframe. Це дозволяє iframe отримувати чутливу інформацію з іншого iframe в тому ж SOP, завантаженому на батьківській сторінці: ```javascript window.top[1].document.body.innerHTML = 'Hi from credentialless'; alert(window.top[1].document.cookie); ``` - Приклад експлуатації: Self-XSS + CSRF У цій атаці зловмисник готує шкідливу веб-сторінку з 2 iframe: - Iframe, який завантажує сторінку жертви з прапором `credentialless` з CSRF, що викликає XSS (Уявіть собі Self-XSS у імені користувача): ```html
``` - Інший iframe, в якому насправді користувач увійшов в систему (без прапора `credentialless`). Тоді, з XSS, можливо отримати доступ до іншого iframe, оскільки вони мають одну і ту ж SOP, і вкрасти кукі, наприклад, виконавши: ```javascript alert(window.top[1].document.cookie); ``` ### fetchLater Attack Як зазначено в [this article](https://blog.slonser.info/posts/make-self-xss-great-again/), API `fetchLater` дозволяє налаштувати запит, який буде виконано пізніше (після певного часу). Тому це можна зловживати, наприклад, для входу жертви в сесію атакуючого (з Self-XSS), налаштувати запит `fetchLater` (щоб змінити пароль поточного користувача, наприклад) і вийти з сесії атакуючого. Потім жертва входить у свою власну сесію, і запит `fetchLater` буде виконано, змінюючи пароль жертви на той, що встановлений атакуючим. Таким чином, навіть якщо URL жертви не може бути завантажено в iframe (через CSP або інші обмеження), атакуючий все ще може виконати запит у сесії жертви. ```javascript var req = new Request("/change_rights",{method:"POST",body:JSON.stringify({username:"victim", rights: "admin"}),credentials:"include"}) const minute = 60000 let arr = [minute, minute * 60, minute * 60 * 24, ...] for (let timeout of arr) fetchLater(req,{activateAfter: timeout}) ``` ## Iframes в SOP Перевірте наступні сторінки: {{#ref}} ../postmessage-vulnerabilities/bypassing-sop-with-iframes-1.md {{#endref}} {{#ref}} ../postmessage-vulnerabilities/bypassing-sop-with-iframes-2.md {{#endref}} {{#ref}} ../postmessage-vulnerabilities/blocking-main-page-to-steal-postmessage.md {{#endref}} {{#ref}} ../postmessage-vulnerabilities/steal-postmessage-modifying-iframe-location.md {{#endref}} {{#include ../../banners/hacktricks-training.md}}