07-12-2018 / Od 0 do pentestera

postMessage

Załóżmy, że jesteśmy właścicielami dwóch różnych domen i chcemy aby mogły się one ze sobą komunikować przy użyciu JavaScript.

Komunikacja pomiędzy domenami

Standardowo, strony mogą się ze sobą komunikować jedynie jeżeli zgadza się ich nazwa hosta, numer portu i protokół - jest to tak zwany mechanizm same origin policy.

Aby go obejść mamy kilka możliwości. Jedną z nich jest postMessage.

Zobaczmy na kod domena1.

Kod domeny pierwsze

Nasłuchujemy w nim na wiadomości a jeśli takowe wystąpią wyświetlamy je przy pomocy alert.

Teraz popatrzmy na drugą domenę.

Tutaj otwieramy tą pierwszą używając iframe a następnie (po tym jak się załaduje) wysyłamy do niej wiadomość przy użyciu funkcji postMessage.

Kod domeny drugiej

Wyświetlił się nasz komunikat - więc wszystko działa.

Gdzie jest zatem dzisiejszy błąd?

Wprowadźmy trzecią domenę, która robi dokładnie to samo co druga - czyli wysyła wiadomość do domeny pierwszej.

Tym razem jednak nie jest to nasza domena a domena atakującego.

Jak widać ta wiadomość również została wyświetlona.

Kod trzeciej domeny

Stało się tak ponieważ nie zawarliśmy żadnego mechanizmu zabezpieczającego - nasza strona otrzymuje i wyświetla wiadomości od wszystkich.

Może to rodzić różne konsekwencje. Zależy od tego co dana strona robi z otrzymanymi danymi.

W zależności od przypadku może zatem dojść do ataku XSS - kiedy wysyłamy niebezpieczny kod HTML, który jest przez stronę wyświetlany bez żadnej weryfikacji.

Czasami możemy ukraść ciasteczka czy też opublikować jakiś wpis na koncie zalogowanego użytkownika bez jego wiedzy.

W najgorszym możliwym scenariuszu (gdy strona traktowała by wysłaną wiadomość jako kod JavaScript) - możemy na podanej stronie zrobić praktycznie wszystko.

No dobrze, ale jak się przed tym zabezpieczyć?

Musimy w funkcji obsługującej przychodzące wiadomości sprawdzić origin - czyli skąd dana wiadomość do nas trafiła.

Przeglądarka automatycznie wysyła taką informację razem z treścią wiadomości.

Nagłówek origin
https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent

Ale i tutaj można się pomylić.

Załóżmy, że użyliśmy wyrażenia regularnego, aby sprawdzić czy domena, która wysłała do nas wiadomość należy do nas.

Czy jesteś w stanie zauważyć błąd?

Wyrażenie regularne

W wyrażeniach regularnych kropka oznacza dokładnie jeden, dowolny znak.

Aby kropka była traktowana jako kropka, musi zostać poprzedzona backslashem.

Takie sprawdzenie będzie zatem działało w domenie www.domena2.local ale także w wwwXdomena2.local, gdzie kropkę zastąpiliśmy znakiem x.

Wyrażenie regularne

Inną nieprawidłową formą może być użycie funkcji indexOf, czyli sprawdzenie czy gdziekolwiek w nazwie origin znajduje się nasza domena.

Funkcja indexOf

To zabezpieczenie możemy obejść tworząc subdomene, która będzie się zaczynać od danego przedrostka, czyli: www.domena2.local.cokolwiek.local.

Ta domena nie należy do nas a do atakującego ponieważ jest to domena cokolwiek.local, w której to stworzona została subdomena www.domena2.local.

IndexOf natomiast sprawdza czy podany ciąg znaków znajduje się gdziekolwiek.

Icon made by Freepik, Maxim Basinski Premium, pictogramer from www.flaticon.com