PostMessage Vulnerabilities
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
PostMessage uses the following function to send a message:
Zauważ, że targetOrigin może być '*' lub adresem URL, takim jak https://company.com. W drugim scenariuszu wiadomość może być wysyłana tylko do tej domeny (nawet jeśli pochodzenie obiektu okna jest inne). Jeśli użyto znaku wieloznacznego, wiadomości mogą być wysyłane do dowolnej domeny i będą wysyłane do pochodzenia obiektu Window.
Jak wyjaśniono w tym raporcie, jeśli znajdziesz stronę, która może być iframed (brak ochrony X-Frame-Header
) i która wysyła wrażliwe wiadomości za pomocą postMessage używając znaku wieloznacznego (*), możesz zmodyfikować pochodzenie iframe i wyciek wrażliwej wiadomości do domeny kontrolowanej przez Ciebie.
Zauważ, że jeśli strona może być iframed, ale targetOrigin jest ustawiony na adres URL, a nie na znak wieloznaczny, ten sztuczek nie zadziała.
addEventListener
to funkcja używana przez JS do deklarowania funkcji, która oczekuje postMessages
.
Zostanie użyty kod podobny do poniższego:
Zauważ w tym przypadku, jak pierwszą rzeczą, którą kod robi, jest sprawdzanie pochodzenia. To jest strasznie ważne, szczególnie jeśli strona ma zamiar zrobić cokolwiek wrażliwego z otrzymanymi informacjami (jak zmiana hasła). Jeśli nie sprawdzi pochodzenia, atakujący mogą zmusić ofiary do wysyłania dowolnych danych do tych punktów końcowych i zmieniać hasła ofiar (w tym przykładzie).
Aby znaleźć nasłuchiwacze zdarzeń na bieżącej stronie, możesz:
Przeszukać kod JS w poszukiwaniu window.addEventListener
i $(window).on
(wersja JQuery)
Wykonać w konsoli narzędzi deweloperskich: getEventListeners(window)
Przejść do Elements --> Event Listeners w narzędziach deweloperskich przeglądarki
Użyć rozszerzenia przeglądarki takiego jak https://github.com/benso-io/posta lub https://github.com/fransr/postMessage-tracker. Te rozszerzenia przeglądarki przechwycą wszystkie wiadomości i pokażą je Tobie.
Atrybut event.isTrusted
jest uważany za bezpieczny, ponieważ zwraca True
tylko dla zdarzeń generowanych przez prawdziwe działania użytkownika. Choć trudno go obejść, jeśli jest poprawnie zaimplementowany, jego znaczenie w kontrolach bezpieczeństwa jest zauważalne.
Użycie indexOf()
do walidacji pochodzenia w zdarzeniach PostMessage może być podatne na ominięcie. Przykład ilustrujący tę podatność to:
Metoda search()
z String.prototype.search()
jest przeznaczona do wyrażeń regularnych, a nie do ciągów. Przekazanie czegokolwiek innego niż regexp prowadzi do niejawnej konwersji na regex, co czyni tę metodę potencjalnie niebezpieczną. Dzieje się tak, ponieważ w regexie kropka (.) działa jako znak wieloznaczny, co pozwala na ominięcie walidacji za pomocą specjalnie skonstruowanych domen. Na przykład:
Funkcja match()
, podobnie jak search()
, przetwarza regex. Jeśli regex jest źle skonstruowany, może być podatny na ominięcie.
Funkcja escapeHtml
ma na celu sanitację danych wejściowych poprzez ucieczkę znaków. Jednak nie tworzy nowego obiektu z ucieczką, lecz nadpisuje właściwości istniejącego obiektu. To zachowanie może być wykorzystane. Szczególnie, jeśli obiekt można manipulować w taki sposób, że jego kontrolowana właściwość nie uznaje hasOwnProperty
, escapeHtml
nie zadziała zgodnie z oczekiwaniami. To jest pokazane w poniższych przykładach:
Oczekiwana awaria:
Ominięcie ucieczki:
W kontekście tej podatności, obiekt File
jest szczególnie podatny na wykorzystanie z powodu swojej właściwości name
tylko do odczytu. Ta właściwość, gdy jest używana w szablonach, nie jest sanitizowana przez funkcję escapeHtml
, co prowadzi do potencjalnych zagrożeń bezpieczeństwa.
Właściwość document.domain
w JavaScript może być ustawiana przez skrypt w celu skrócenia domeny, co pozwala na bardziej luźne egzekwowanie polityki tego samego pochodzenia w obrębie tej samej domeny nadrzędnej.
Podczas osadzania strony internetowej w sandboxed iframe przy użyciu %%%%%%, ważne jest, aby zrozumieć, że pochodzenie iframe będzie ustawione na null. To jest szczególnie ważne w przypadku atrybutów sandbox i ich implikacji na bezpieczeństwo i funkcjonalność.
Poprzez określenie allow-popups
w atrybucie sandbox, każde okno popup otwarte z wnętrza iframe dziedziczy ograniczenia sandboxu swojego rodzica. Oznacza to, że chyba że atrybut allow-popups-to-escape-sandbox
jest również uwzględniony, pochodzenie okna popup jest również ustawione na null
, co odpowiada pochodzeniu iframe.
W konsekwencji, gdy popup jest otwierany w tych warunkach i wiadomość jest wysyłana z iframe do popupu za pomocą postMessage
, zarówno nadawca, jak i odbiorca mają swoje pochodzenia ustawione na null
. Ta sytuacja prowadzi do scenariusza, w którym e.origin == window.origin
ocenia się jako prawda (null == null
), ponieważ zarówno iframe, jak i popup dzielą tę samą wartość pochodzenia null
.
Aby uzyskać więcej informacji przeczytaj:
Bypassing SOP with Iframes - 1Możliwe jest sprawdzenie, czy wiadomość pochodzi z tego samego okna, w którym skrypt nasłuchuje (szczególnie interesujące dla Content Scripts z rozszerzeń przeglądarki, aby sprawdzić, czy wiadomość została wysłana z tej samej strony):
Możesz wymusić, aby e.source
wiadomości było równe null, tworząc iframe, który wysyła postMessage i jest natychmiast usuwany.
Aby uzyskać więcej informacji przeczytaj:
Bypassing SOP with Iframes - 2Aby przeprowadzić te ataki, najlepiej będzie, jeśli będziesz mógł umieścić stronę internetową ofiary w iframe
. Jednak niektóre nagłówki, takie jak X-Frame-Header
, mogą zapobiegać temu zachowaniu.
W takich scenariuszach możesz nadal użyć mniej dyskretnego ataku. Możesz otworzyć nową kartę do podatnej aplikacji internetowej i komunikować się z nią:
Na poniższej stronie możesz zobaczyć, jak można ukraść wrażliwe dane postmessage wysłane do dziecięcego iframe przez zablokowanie strony głównej przed wysłaniem danych i wykorzystanie XSS w dziecku do ujawnienia danych przed ich odebraniem:
Blocking main page to steal postmessageJeśli możesz iframe'ować stronę internetową bez X-Frame-Header, która zawiera inny iframe, możesz zmienić lokalizację tego dziecięcego iframe, więc jeśli odbiera postmessage wysłane za pomocą wildcard, atakujący mógłby zmienić ten iframe origin na stronę kontrolowaną przez niego i ukraść wiadomość:
Steal postmessage modifying iframe locationW scenariuszach, w których dane wysyłane przez postMessage
są wykonywane przez JS, możesz iframe'ować stronę i wykorzystać zanieczyszczenie prototypu/XSS, wysyłając exploit za pomocą postMessage
.
Kilka bardzo dobrze wyjaśnionych XSS przez postMessage
można znaleźć w https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
Przykład exploita do wykorzystania zanieczyszczenia prototypu, a następnie XSS przez postMessage
do iframe
:
For więcej informacji:
Link do strony o zanieczyszczeniu prototypu
Link do strony o XSS
Link do strony o zanieczyszczeniu prototypu po stronie klienta do XSS
Aby ćwiczyć: https://github.com/yavolo/eventlistener-xss-recon
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)