PostMessage Vulnerabilities
PostMessage Вразливості
Надіслати PostMessage
PostMessage використовує наступну функцію для надсилання повідомлення:
Зверніть увагу, що targetOrigin може бути '*' або URL, наприклад, https://company.com. У другому сценарії повідомлення можна надсилати лише на цей домен (навіть якщо походження об'єкта вікна інше). Якщо використовується дев'ятка, повідомлення можуть бути надіслані на будь-який домен і будуть надіслані на походження об'єкта Window.
Атака на iframe та дев'ятка в targetOrigin
Як пояснено в цьому звіті, якщо ви знайдете сторінку, яку можна вставити в iframe (без захисту X-Frame-Header
) і яка надсилає чутливе повідомлення через postMessage, використовуючи дев'ятку (*), ви можете змінити походження iframe і викрити чутливе повідомлення на домен, контрольований вами.
Зверніть увагу, що якщо сторінка може бути вставлена в iframe, але targetOrigin встановлено на URL, а не на дев'ятку, цей трюк не спрацює.
експлуатація addEventListener
addEventListener
- це функція, яку використовує JS для оголошення функції, яка очікує postMessages
.
Будуть використані коди, подібні до наведеного нижче:
Зверніть увагу, що перше, що робить код, це перевіряє походження. Це надзвичайно важливо, особливо якщо сторінка збирається робити щось чутливе з отриманою інформацією (наприклад, змінювати пароль). Якщо не перевіряти походження, зловмисники можуть змусити жертв надсилати довільні дані на ці кінцеві точки і змінювати паролі жертв (в цьому прикладі).
Перерахування
Щоб знайти обробники подій на поточній сторінці, ви можете:
Шукати JS код для
window.addEventListener
та$(window).on
(версія JQuery)Виконати в консолі інструментів розробника:
getEventListeners(window)
Перейти до Elements --> Event Listeners в інструментах розробника браузера
Використати розширення браузера як https://github.com/benso-io/posta або https://github.com/fransr/postMessage-tracker. Ці розширення браузера перехоплюватимуть всі повідомлення і показуватим їх вам.
Обхід перевірки походження
Атрибут
event.isTrusted
вважається безпечним, оскільки повертаєTrue
лише для подій, які генеруються справжніми діями користувача. Хоча його важко обійти, якщо він реалізований правильно, його значення в перевірках безпеки є помітним.Використання
indexOf()
для перевірки походження в подіях PostMessage може бути вразливим до обходу. Приклад, що ілюструє цю вразливість:
Метод
search()
зString.prototype.search()
призначений для регулярних виразів, а не рядків. Передача чого-небудь, крім регулярного виразу, призводить до неявного перетворення в regex, що робить метод потенційно небезпечним. Це пов'язано з тим, що в regex крапка (.) діє як підстановочний знак, що дозволяє обійти перевірку з особливо створеними доменами. Наприклад:
Функція
match()
, подібно доsearch()
, обробляє regex. Якщо regex неправильно структурований, він може бути вразливим до обходу.Функція
escapeHtml
призначена для санітарної обробки введень шляхом екранування символів. Однак вона не створює нового екранованого об'єкта, а перезаписує властивості існуючого об'єкта. Цю поведінку можна експлуатувати. Зокрема, якщо об'єкт можна маніпулювати так, що його контрольована властивість не визнаєhasOwnProperty
,escapeHtml
не працюватиме, як очікувалося. Це продемонстровано в наведених нижче прикладах:Очікуване невдача:
Обхід екранування:
У контексті цієї вразливості об'єкт File
особливо вразливий через його тільки для читання властивість name
. Ця властивість, коли використовується в шаблонах, не санітарно обробляється функцією escapeHtml
, що призводить до потенційних ризиків безпеки.
Властивість
document.domain
в JavaScript може бути встановлена скриптом для скорочення домену, що дозволяє більш м'яке виконання політики однакового походження в межах одного батьківського домену.
e.origin == window.origin обхід
Коли ви вбудовуєте веб-сторінку в пісочницю iframe за допомогою %%%%%%, важливо розуміти, що походження iframe буде встановлено в null. Це особливо важливо при роботі з атрибутами пісочниці та їх наслідками для безпеки та функціональності.
Вказуючи allow-popups
в атрибуті пісочниці, будь-яке вікно спливаючого вікна, відкрите зсередини iframe, успадковує обмеження пісочниці свого батька. Це означає, що якщо атрибут allow-popups-to-escape-sandbox
також не включений, походження спливаючого вікна також встановлюється в null
, що відповідає походженню iframe.
Отже, коли спливаюче вікно відкривається за цих умов і повідомлення надсилається з iframe до спливаючого вікна за допомогою postMessage
, як відправник, так і отримувач мають свої походження, встановлені в null
. Ця ситуація призводить до сценарію, де e.origin == window.origin
оцінюється як істина (null == null
), оскільки як iframe, так і спливаюче вікно мають одне й те саме значення походження null
.
Для отримання додаткової інформації читайте:
Bypassing SOP with Iframes - 1Обхід e.source
Можливо перевірити, чи повідомлення надійшло з того ж вікна, в якому скрипт слухає (особливо цікаво для Content Scripts з розширень браузера, щоб перевірити, чи повідомлення було надіслано з тієї ж сторінки):
Ви можете примусити e.source
повідомлення бути null, створивши iframe, який надсилає postMessage і відразу видаляється.
Для отримання додаткової інформації читайте:
Bypassing SOP with Iframes - 2Обхід заголовка X-Frame
Щоб виконати ці атаки, ідеально, щоб ви могли вставити веб-сторінку жертви всередину iframe
. Але деякі заголовки, такі як X-Frame-Header
, можуть запобігти цій поведінці.
У таких сценаріях ви все ще можете використовувати менш приховану атаку. Ви можете відкрити нову вкладку для вразливого веб-додатку та спілкуватися з ним:
Вкрадення повідомлення, надісланого дитині, блокуючи основну сторінку
На наступній сторінці ви можете побачити, як ви могли б вкрасти чутливі дані postmessage, надіслані до дитячого iframe, блокуючи основну сторінку перед відправкою даних і зловживаючи XSS у дитині, щоб викрити дані до того, як вони будуть отримані:
Blocking main page to steal postmessageВкрадення повідомлення шляхом зміни місцезнаходження iframe
Якщо ви можете вставити веб-сторінку без X-Frame-Header, яка містить інший iframe, ви можете змінити місцезнаходження цього дитячого iframe, тому, якщо він отримує postmessage, надіслане з використанням wildcard, зловмисник може змінити цей iframe походження на сторінку, контрольовану ним, і вкрасти повідомлення:
Steal postmessage modifying iframe locationpostMessage до Prototype Pollution та/або XSS
У сценаріях, де дані, надіслані через postMessage
, виконуються JS, ви можете вставити сторінку і використати прототипне забруднення/XSS, надсилаючи експлойт через postMessage
.
Кілька дуже добре пояснених XSS через postMessage
можна знайти за посиланням https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
Приклад експлойту для зловживання Prototype Pollution, а потім XSS через postMessage
до iframe
:
Для додаткової інформації:
Посилання на сторінку про потенційне забруднення прототипу
Посилання на сторінку про XSS
Посилання на сторінку про забруднення прототипу на стороні клієнта до XSS
Посилання
Для практики: https://github.com/yavolo/eventlistener-xss-recon
Last updated