Читать книгу Na tropie błędów. Przewodnik hakerski - Peter Yaworski - Страница 9
1.
PODSTAWY BUG BOUNTY
Co się dzieje, kiedy odwiedzasz stronę
ОглавлениеPonieważ w tej książce skupiamy się na żądaniach HTTP, ta sekcja dostarczy Ci wysokopoziomowy wgląd na cały proces, który następuje po wpisaniu adresu URL w przeglądarce.
Krok 1: Identyfikacja domeny internetowej
Kiedy wpiszesz http://www.google.com/, Twoja przeglądarka ustala domenę z adresu URL. Domena identyfikuje stronę, którą próbujesz odwiedzić, i musi przy tym przestrzegać określonych zasad zdefiniowanych przez RFC. Na przykład domena może zawierać tylko znaki alfanumeryczne i podkreślenia. Jedyny wyjątek stanowią zinternacjonalizowane domeny, które wychodzą poza zakres tej książki. Jeśli chcesz dowiedzieć się więcej na ten temat, sprawdź dokument RFC 3490, który definiuje ich użycie. W tym przypadku domeną jest www.google.com. Domena służy jako jedna z dróg do znalezienia adresu serwera.
Krok 2: Ustalenie adresu IP
Po ustaleniu domeny, Twoja przeglądarka używa IP do sprawdzenia adresu IP powiązanego z tą stroną. Ten proces jest określany jako ustalanie adresu IP i każda domena w internecie musi zostać przetłumaczona na adres IP, aby działała.
Istnieją dwa rodzaje adresów IP, definiowane przez protokół internetowy w wersji 4 (IPv4) i w wersji 6 (IPv6). Adresy IPv4 są skonstruowane z czterech liczb połączonych kropkami, gdzie każdy numer jest z przedziału od 0 do 255. IPv6 jest najnowszą wersją protokołu internetowego. Został stworzony po to, by rozwiązać problem kończących się adresów IPv4. Adresy IPv6 są stworzone z ośmiu grup czterocyfrowych liczb dziesiętnych, oddzielonych dwukropkami, lecz istnieją metody na ich skrócenie. Na przykład 8.8.8.8 jest adresem IPv4, a 2001:4860:4860::8888 jest skróconym adresem IPv6.
Aby znaleźć adres IP, używając domeny, Twój komputer wysyła żądanie do serwerów DNS (Domain Name System) składających się ze specjalnych serwerów w internecie, które mają rejestr wszystkich domen i odpowiadających im adresów IP. Powyższe adresy IPv4 i IPv6 są serwerami DNS Google.
W tym przypadku serwer DNS, do którego się łączysz, dopasowałby www.google.com do adresu IPv4 216.58.201.228 i wysłałby go z powrotem do Twojego komputera. By dowiedzieć się więcej na temat adresu IP konkretnej strony, możesz użyć komendy dig A site.com w swoim terminalu i zamienić site.com na stronę, którą chcesz sprawdzić.
Krok 3: Nawiązanie połączenia TCP
Następnie komputer próbuje nawiązać połączenie TCP (Transmission Control Protocol – protokół kontroli transmisji) z adresem IP przez port 80, ponieważ odwiedziłeś stronę, używając http://. Szczegóły na temat TCP nie są istotne oprócz tego, że jest to kolejny protokół, który definiuje sposób, w jaki komputery komunikują się ze sobą. TCP zapewnia dwukierunkową komunikację, dzięki czemu odbiorcy wiadomości mogą zweryfikować kompletność przesyłanej informacji podczas transmisji.
Serwer, do którego wysyłasz żądanie, może być w trakcie obsługi wielu usług (traktuj usługę jako program komputerowy), więc używa portów do identyfikacji konkretnych usług, aby odbierać żądania. Możesz je sobie wyobrazić jako drzwi serwera do internetu. Bez portów usługi musiałyby konkurować ze sobą o to, która informacja zostanie wysłana. Oznacza to, że potrzebujemy kolejnego standardu do zdefiniowania tego, jak usługi współpracują ze sobą i upewnić się, że dane dla jednej usługi nie są kradzione przez inne. Na przykład port 80 jest standardowym portem do wysyłania i odbierania żądań HTTP. Innym powszechnym portem jest 443, który jest używany do zaszyfrowanych żądań HTTPS. Mimo że port 80 jest standardem dla HTTP i 443 jest standardem dla HTTPS, komunikacja TCP może następować na dowolnym porcie, zależnie od konfiguracji aplikacji przez administratora.
Możesz nawiązać swoje własne połączenie TCP do strony internetowej przez port 80 przy użyciu terminala, wpisując komendę nc <ADRES IP> 80. Komenda nc używa narzędzia Netcat do utworzenia połączenia sieciowego do odczytywania i pisania wiadomości.
Krok 4: Wysyłanie zapytania HTTP
Kontynuując przykład ze stroną http://www.google.com/, jeśli połączenie w kroku 3 zostało nawiązane pomyślnie, Twoja przeglądarka powinna przygotować i wysłać żądanie HTTP, tak jak w listingu 1.1:
GET / HTTP/1.1
Host: www.google.com
Connection: keep-alive
Accept: application/html, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36
Listing 1.1. Wysyłanie żądania HTTP
Przeglądarka przygotowuje żądanie GET do ścieżki / , która jest główną ścieżką dostępu strony. Zawartość strony jest organizowana ścieżkami, dokładnie tak samo jak foldery i pliki na Twoim komputerze. Gdy wchodzisz w kolejne foldery, ścieżka, którą podążasz, jest oznaczona przez zapisywanie nazw kolejnych folderów i dopisywanie / na ich końcu. Kiedy odwiedzasz pierwszą stronę na witrynie internetowej, dostajesz się do głównej ścieżki dostępu, którą jest po prostu /. Przeglądarka również sygnalizuje, że używa wersji 1.1 protokołu HTTP. Żądanie GET jedynie otrzymuje informacje. Dowiesz się o tym więcej później.
Nagłówek host zawiera dodatkowe informacje, które są wysłane jako część zapytania. HTTP 1.1 potrzebuje ich, by określić, gdzie serwer dla danego adresu IP powinien przesłać żądanie, ponieważ adresy IP mogą hostować kilka domen na raz. Nagłówek connection informuje, żeby utrzymać połączenie otwarte, aby uniknąć potrzeby ciągłego otwierania i zamykania połączeń.
Możesz zobaczyć oczekiwany format odpowiedzi w . W tym przypadku oczekujemy application/html, lecz zaakceptujemy każdy format, co zostało oznaczone symbolem (*/*). Istnieją tysiące możliwych rodzajów zawartości, ale dla naszych potrzeb najczęściej będziesz wykorzystywał: application/html, application/json, application/octet-stream oraz text/plain. W końcu User-Agent określa oprogramowanie odpowiedzialne za wysyłanie żądań.
Krok 5: Odpowiedź serwera
W odpowiedzi na nasze żądanie serwer powinien odpowiedzieć czymś w rodzaju listingu 1.2:
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<head>
<title>Google.com</title>
</head>
<body>
--cięcie–
</body>
</html>
Listing 1.2. Odpowiedź serwera
Tutaj otrzymaliśmy odpowiedź HTTP z kodem statusu 200 . Kod statusu jest istotny, ponieważ mówi o rezultacie odpowiedzi. Co również jest opisane przez RFC, kody te zazwyczaj mają trzycyfrowy numer, który zaczyna się 2, 3, 4 lub 5. Mimo że nie ma wyznaczonych standardów do używania konkretnych kodów, 2xx najczęściej oznacza sukces.
Ponieważ nie istnieje żaden wymóg co do tego, jak serwer implementuje użycie własnych kodów HTTP, możesz czasem zobaczyć odpowiedź z kodem 200, nawet jeśli dalsza odpowiedź HTTP opisuje błąd. Treść wiadomości HTTP jest tekstem powiązanym z żądaniem lub odpowiedzią . W tym przypadku usunęliśmy zawartość i zamieniliśmy ją na –cięcie– ze względu na wielkość treści wiadomości od Google. Zawartość odpowiedzi to zazwyczaj HTML dla strony internetowej, ale może być również tekstem JSON dla API, zawartością do pobrania i tak dalej.
Nagłówek Content-Type informuje przeglądarkę o rodzaju treści. Rodzaj treści określa, w jaki sposób przeglądarka będzie renderować zawartość. Przeglądarki nie zawsze jednak używają wartości zwróconej przez aplikację; zamiast tego przeglądarka wykonuje tzw. MIME sniffing przez czytanie pierwszych bitów treści wiadomości, aby wykryć jej rodzaj samemu. Aplikacje mogą wyłączyć tę funkcję przez dołączanie nagłówka X-Content-Type-Options:nosniff, który w obecnym przykładzie nie został dołączony.
Kolejny kod statusu, zaczynający się od 3 oznacza przekierowanie, co instruuje Twoją przeglądarkę do wykonania dodatkowego zapytania. Na przykład, jeśli Google chciałby odesłać Cię na stałe z jednego adresu URL na drugi, użyłby odpowiedzi 301. Dla odróżnienia 302 oznacza tymczasowe przekierowanie.
Gdy otrzymujesz odpowiedź 3xx, Twoja przeglądarka powinna wykonać nowe żądanie HTTP na adres URL wskazany w nagłówku Location:
HTTP/1.1 301 Found
Location: https://www.google.com/
Odpowiedzi zaczynające się od 4 najczęściej wskazują na błąd użytkownika, tak jak kod 403, kiedy żądanie nie będzie zawierało odpowiednich danych do wykonania uwierzytelnienia, mimo przesłania prawidłowego żądania HTTP. Odpowiedzi zaczynające się 5 oznaczają błąd po stronie serwera, przykładem może być kod 503, który oznacza, że serwer nie jest w stanie obsłużyć otrzymanego żądania.
Krok 6: Renderowanie odpowiedzi
Ponieważ serwer wysłał odpowiedź z kodem 200 i rodzajem text/html, nasza przeglądarka rozpocznie renderowanie wiadomości, którą otrzymała. Treść odpowiedzi mówi przeglądarce, co powinno zostać wyświetlone użytkownikowi.
Dla naszego przykładu byłby to HTML do budowy strony; kaskadowe arkusze stylów (CSS) do stylizacji i układu; JavaScript do dodatkowej funkcjonalności i mediów, takich jak zdjęć lub filmów. Serwer może również odpowiedzieć inną zawartością, taką jak XML, lecz dla tego przykładu zostaniemy przy podstawach. Rozdział 11 omawia XML w szczegółach.
W przypadku gdy strona internetowa ma zewnętrzną zawartość, taką jak CSS, JavaScript czy media, przeglądarka będzie musiała wykonać dodatkowe żądania HTTP dla wszystkich wymaganych plików przez daną witrynę. W trakcie gdy przeglądarka wysyła wymagane żądania, wciąż będzie analizować odpowiedź i wyświetlać zawartość jako stronę. W tym przypadku wyrenderuje główną stronę Google, www.google.com.
Zauważ, że JavaScript jest językiem skryptowym wspieranym przez każdą przeglądarkę. JavaScript pozwala stronom na posiadanie dynamicznej funkcjonalności, włączając w to możliwość aktualizacji elementów na stronie bez potrzeby odświeżania całej strony, sprawdzanie siły Twojego hasła (w przypadku niektórych stron) i wiele innych. Tak jak inne języki programowania, JavaScript ma wbudowane funkcje, może przechowywać wartości w zmiennych i potrafi uruchamiać kod w odpowiedzi na interakcje na stronie. Ma również dostęp do zróżnicowanych interfejsów programowania (API). Interfejsy te pozwalają językowi JavaScript na interakcję z innymi systemami, z czego jednym z najważniejszych jest obiektowy model dokumentu (DOM – Document Object Model).
DOM umożliwia językowi JavaScript dostęp i manipulację kodem HTML i CSS należącymi do strony. Jest to bardzo istotne, ponieważ jeśli intruz jest w stanie uruchomić własny kod JavaScript, będzie on mógł uzyskać dostęp do DOM-u i wykonać akcje na stronie w imieniu ofiary. Rozdział 7 rozwija to zagadnienie dokładniej.