17-02-2020 / Podcast

XS-leaks - Cross Site Leaks

Wprowadzenie

Większość odnajdowanych w oprogramowaniu błędów jest dobrze znana i opisana.

Wiemy dlaczego występują, jakie mogą być ich skutki a także jak się przed nimi ochronić.

Dalej jednak pojawiają się w różnych miejscach z różnych powodów.

Zazwyczaj jest to pośpiech, niewiedza bądź też błąd ludzki.

Ale branża nie śpi.

Różni badacze od czasu do czasu wpadają na nowe, rewolucyjne pomysły, które wywracają świat do góry nogami.

Dzisiaj o jednej z nowszych rodzajów podatności, tak zwanych Cross Site Leaks.

Uogólniając, błędy tego rodzaju w specyficznych okolicznościach pozwalają na odpowiedź tak/nie na zadane wcześniej pytanie.

Nie wydaje się to zatem niczym spektakularnym.

Nie ma wybuchów i wykonywania zdalnego kodu na serwerze.

Odpowiedź na pytanie tak/nie

 Odpowiedź tak/nie

Na pozór wydaje się zatem, że to nic nie znacząca klasa podatności.

Diabeł tkwi w szczegółach i wszystko zależy od systemu, z jakim mamy do czynienia.

Jeśli to serwer sądowy – można sprawdzić czy obywatel X był karany.

W przypadku szpitala – możliwe jest zweryfikowanie, czy Kowalski choruje na raka prostaty.

 Na co chorujesz?

Błąd w banku pozwoli dowiedzieć się, czy użytkownik posiada więcej niż milion złotych na koncie.

Możliwe jest także poznanie hasła użytkownika.

Każde pytanie można bowiem zamienić na serię pytań tak/nie.

Czy pierwszy znak hasła zawiera się pomiędzy cyfrą 0 a 9.

A może jest to litera Z?

Czy w skrzynce mailowej użytkownika znajduje się mail od pana Kowalskiego?

Dzisiaj opowiem o atakach Cross Site Leaks.

Dlaczego występują, co jest ich powodem i jak należy ich poszukiwać.

Jeżeli materiały tego rodzaju Ci się podobają, dołącz do grupy „od 0 do pentestera” na Facebooku gdzie dzielimy się swoją wiedzą z zakresu bezpieczeństwa.

Podcast ten jest dostępny na YouTube, Spotify oraz Google i Apple Podcast.

A jeżeli wolisz czytać – link do całego tekstu znajduje się w opisie pod tym materiałem.

Same origin policy

 Same origin policy

Ale zanim wyjaśnię tytułowy błąd, należy zrozumieć jak działają przeglądarki internetowe i co to jest Same Origin Policy.

Już na samym początku istnienia przeglądarek, powstały pewne zasady, które chronią bezpieczeństwo użytkowników.

Jedną z nich jest SOP – czyli Same Origin Policy.

Dzięki niemu, strona X nie może pobrać treści ze strony Y – o ile strona Y nie wyrazi na to zgody.

Ta na pozór prosta reguła jest podstawą bezpieczeństwa.

Dlaczego?

Wyobraźmy sobie, że jesteśmy zalogowani na stronie banku.

W tej samej przeglądarce, w innych kartach mamy uruchomione także inne strony należące do różnych firm.

Gdyby reguła ta nie istniała, każda dowolna strona mogła by wysłać zapytanie do witryny naszego banku i pobrać informacje na temat stanu naszego konta.

Przeglądarka automatycznie dołączyła by nasze ciasteczko – czyli informacje, która sprawia, że serwer wie, że my to my.

Przeglądanie Internetu było by znacząco utrudnione.

Musielibyśmy bowiem korzystać jedynie z jednej karty, logować się na jedną stronę a następnie po wykonaniu wszystkich koniecznych operacji się z niej wylogować.

I tak w kółko.

Z drugiej jednak strony przeglądarki pozwalają na wysyłanie żądań pod inne adresy.

Korzystamy z tego na co dzień, wypełniając formularze na różnych stronach czy też korzystając z API różnych serwisów.

Samo wysyłanie żądania pod inny adres to jeszcze nic złego.

Kluczowa jest natomiast możliwość dostępu do zwrócony przez serwer danych.

Protokół, port i domena

 SOP

Przeglądarka porównuje protokół port i domenę i jedynie w przypadku zgodności wszystkich tych elementów zezwala na dostęp do danych.

Oczywiście w między czasie pojawiły się dodatkowe mechanizmy, umożliwiające odczytywanie danych z zewnętrznych serwerów.

Przykład. Chcemy na swojej stronie umieścić prognozę pogody.

Sami nie zajmujemy się przewidywaniem opadów więc korzystamy z zewnętrznego narzędzia.

Z poziomu kodu JavaScript na naszej stronie kontaktujemy się z odpowiednim API.

W odpowiedzi zwraca ono interesujące nas dane, które po obróbce mogą być wyświetlone na naszej stronie.

Tylko, że z powodu różnych domen – przeglądarka na to nie pozwoli.

Chyba, że serwer zwrócił odpowiedni nagłówek CORS – wyrażając na to zgodę.

 CORS

Wiemy już jak działa ten mechanizm.

Wróćmy więc do błędów, o których wspominałem na samym początku materiału.

Teoretycznie każda strona internetowa może wysłać żądanie do Gmaila.

Jeżeli jesteśmy aktualnie zalogowani i nasza przeglądarka posiada odpowiednie ciasteczka – serwer zwróci treść naszej skrzynki mailowej.

Tylko, nie będą się zgadzały domeny więc zadziała mechanizm SOP.

Równocześnie, raczej nie ma co liczyć, ze Google będzie ustawiał odpowiednie nagłówki CORS, które pozwoliły by na odczytanie poufnych informacji.

Atakujący są więc w kropce.

Badacze po pewnym czasie zauważyli, że rzeczywiście, nie mogą odczytać treści zwracanych przez serwer informacji.

Tylko, że te informacje docierają do przeglądarki – czyli żądanie jest wysyłane do zewnętrznego serwera a jago odpowiedź trafia do przeglądarki.

I to ona decyduje, czy dana strona ma do nich dostęp.

Postanowili więc mierzyć czas trwania całego takiego żądania.

Jest to możliwe – w każdym bowiem momencie, z poziomu kodu JavaScript można wysłać dowolne żądanie do dowolnego serwera a następnie oczekiwać na komunikat błędu – równocześnie mierząc czas.

 Jak działa SOP

Ten atak nazywano XS-SEARCH, teraz jednak mówimy o szerszej grupie XS-leaks.

Rozpatrzmy to na przykładzie.

Chcemy sprawdzić, czy w skrzynce odbiorczej znajduje się wiadomość od Kowalskiego.

Jeżeli nie ma takiej odpowiedzi – serwer zwróci kod błędu lub pustą skrzynkę.

W przypadku pozytywnego wyniku – zwróci treść wiadomości.

Można więc założyć, że treść wiadomości jest większa niż kod błędu.

 XS-search

Co za tym idzie zwracana treść strony będzie większa, jeżeli odpowiedź na pytanie jest twierdząca.

Teoretycznie im więcej informacji przesyłamy przez Internet tym dłużej to trwa.

Pamiętajmy, że mówimy tu jednak o milisekundach.

Pojedyncza próba nie jest w stanie zwrócić nam poprawnego wyniku.

Musimy ją powtórzyć kilkaset lub nawet kilka tysięcy razy, równocześnie porównując wyniki z wartościami kontrolnymi.

Tak oto wyglądały początki tej klasy podatności.

Czas trwania żądania

Trzeba jednak przyznać, że całość opiera się na dość kruchych podwalinach.

Co więcej, tej klasy podatności zostały dość szybko załatane przez same przeglądarki.

Wystarczyło, że zaczęły one dorzucać losowe opóźnienia do zwracanych wyników i nagle czar prysł.

Co więcej, atak ten nie był praktyczny.

Każdy pytanie bowiem wymagało sporej ilości żądań.

Ale świetne pomysły rodzą się w trudach i pocie czoła.

Oprócz wysyłania żądań do innych serwerów możemy także umieszczać inne strony bezpośrednio na naszej witrynie.

Służy do tego tag iframe.

Okazuje się, że SOP nie pozwala na odczytywanie treści zwracanych danych, pozwala jednak sprawdzić ile ramek znajduje się w zwróconym żądaniu.

Czyli ile razy na stronie, o której dane prosiliśmy wykorzystano tag iframe.

Tag iframe

 Tag iframe

I ponownie – wydaje się to być nieistotną informacją.

Ale należy zastanowić się do jakich celów programiści używają tagów iframe.

Mogą być one używane chociażby do wyświetlania reklam.

A kiedy wyświetlamy reklamy? Dookoła treści dla użytkownika.

Jeżeli wiec coś na naszej stronie nie zadziałało – czyli szukana przez użytkownika treść nie istnieje w naszym serwisie – zazwyczaj zwracamy błąd 404 i nie wyświetlamy reklamy aby jeszcze bardziej nie irytować użytkownika.

I właśnie to jest przewaga atakującego.

Powiedziałem bowiem wcześniej, że może on odczytać ilość ramek.

Wysyła wiec żądanie do strony, które to w przypadku niepowodzenia zwraca błąd 404.

Przy prawidłowej odpowiedzi – użytkownik widzi pełną stronę z wynikiem wraz z załadowaną ramką.

Teraz wystarczy tylko porównać ilość załadowanych ramek.

Liczba 0 wskazuje, że odpowiedź na nasze pytanie jest przecząca – czyli dla przykładu użytkownik o danym imieniu nie istnieje w serwisie.

Jeżeli jest ona większa od 0 – wiemy, że serwer zwrócił jakiś wynik.

W taki oto sposób możemy zadawać pewne pytania.

Co więcej tym razem odpowiedzi są powtarzalne i deterministyczne.

Nie potrzebujemy wykonywać tysiąca żądań i mierzyć ich czasu ładowania.

XSS Auditor

 XSS Auditor

Okazuje się, że ta klasa podatności była jednym z powodów, dlaczego Chrome pozbył się XSS Auditora ze swojej przeglądarki.

XSS Auditor z założenia miał blokować strony podatne na atak XSS.

W jaki sposób?

Oprogramowanie sprawdzało wszystkie parametry przekazywane przez użytkownika w treści adresu URL bądź też parametrów POST.

Jeżeli któryś z tych parametrów zawierał potencjalnie złośliwy kod – czyli kod JavaScript i dokładnie ten sam kod był zwracany przez serwer, przeglądarka blokowała jego wykonanie.

Całość opierała się zatem na stwierdzeniu, że jeżeli użytkownik podawał kod JS który następnie znajdował się na stronie to strona jest podatna.

Przeglądarki nie interesowało równocześnie, że przecież ten sam kod JS mógł tam być wcześniej.

Istotne było tu i teraz.

W przypadku wykrycia potencjalnego ataku – przeglądarka nie pozwalała na wykonanie takiego kawałka kodu JS w obrębie danej strony.

I rzeczywiście mechanizm ten działał i blokował niektóre ataki.

Z czasem jednak zaczęto odnajdywać obejścia, czyli ciągi znaków, których mechanizm nie traktował za szkodliwe.

Równocześnie, zaczęto wykorzystywać go w atakach XS-Search.

Należy znaleźć odpowiednią podstronę, zachowującą się w specyficzny sposób.

W przypadku pozytywnej odpowiedzi na pytanie, powinna ona zawierać jakiś bliżej nie określony kawałek kodu JavaScript.

W przypadku negatywnej odpowiedzi – tego kawałka kodu nie powinno być.

Atakujący wykonując zapytanie do danej podstrony, oprócz pytania na które chce uzyskać odpowiedź, dokleja jeden, nadmiarowy parametr.

W nim to zawiera treść wykrytego wcześniej kawałka kodu JS.

Przeglądarka zapoznaje się ze wszystkimi parametrami i znajdzie ten, zawierający kod JS.

Ponieważ ten sam kod JS znajduje się na stronie – XSS audytor zablokuje jego wykonanie.

A taka blokada wykonania może zostać odczytana bez względu na SOP.

Event onload

 Event onload

Wykorzystuje się tutaj event onload – który wykonuje się, gdy strona załaduje się do ramki.

Następnie dynamicznie zmienia się adres takiej ramki, dokładając do niej ciąg po znaku #hasz.

Tak skonstruowany adres nie powoduje odświeżenia ramki – event onload nie wykona się zatem ponownie.

Jeżeli jednak strona została zablokowana przez XSS Auditor – zmiana adresu spowoduje ponowne wywołanie eventu.

Tym samym poznaliśmy kolejną metodę na uzyskanie odpowiedzi tak bądź nie.

Tym razem, licząc ile razy wykonał się event onload.

A może Twoja witryna pozwala na ściąganie jakiś plików?

Wyobraźmy sobie serwis medyczny, który pozwala na ściągniecie pliku PDF z danymi pacjenta bazując na jego numerze PESEL.

To też można wykryć.

Pobieranie plików

 Wielkość okna

W Chromium, panel pobierania plików jest zintegrowany z przeglądarką.

Jeżeli zatem strona rozpocznie ściąganie jakiegoś pliku – równocześnie zmieni się rozmiar okna, ponieważ teraz jego część będzie zajmowana przez pasek postępu.

Ponownie atakujący może więc spróbować pobrać interesujący go plik.

Oczywiście nie jest w stanie odczytać jego treści, będzie jednak mógł sprawdzić czy jego pobieranie zostało rozpoczęte.

Wystarczy monitorować wysokość okna.

Inne podejście to wykorzystanie kodu błędów.

Każda strona może wykorzystać kod JavaScript lub obrazek z dowolnej innej domeny.

Wystarczy użyć tagu script czy też img

Równocześnie przeglądarka udostępnia dwie funkcję: onload oraz onerror.

Ta pierwsza wykona się, jeżeli plik istnieje i został załadowany.

W innym przypadku, mamy do czynienia z drugą funkcją.

Jeżeli zatem znajdziemy jakiś zasób, który w odpowiedzi na nasze pytanie raz zwraca obrazek a raz nie – ponownie możemy to wykorzystać na naszą korzyść.

Wystarczy w tle, próbować załadować wiele tysięcy obrazków – i sprawdzać ich status.

Błędy tego rodzaju mają poważne konsekwencje z punktu widzenia prywatności.

Mogą bowiem doprowadzić do deanonimizacji użytkowników w Internecie.

Prywatność

 Deanonimizacja użytkowników

Przykład.

Sporo z nas korzysta z Facebooka i jest na nim ciągle zalogowanym.

Jeżeli znalazł by się tam błąd XS-Leaks, dowolna strona wysyłając odpowiednio spreparowane żądania mogła by sprawdzić nasz identyfikator – a co za tym idzie dokładnie stwierdzić kto obecnie przegląda daną stronę.

Równocześnie, błędy tego rodzaju są bardzo trudne do uniknięcia.

Wymagają bowiem innego spojrzenia na otaczającą nas rzeczywistość.

Oczywiście nie należy popadać w paranoję.

Ale problem jest realny i będzie coraz popularniejszy.

Więcej informacji znajdziesz na Githubie XS-Leaks1.

Są tam obecnie znane techniki a także przykłady realnych błędów znajdujących się w serwisach używanych przez miliony użytkowników.