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.

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
.

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
.

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.

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.

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?

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.

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

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