Podstawy protokołu HTTP

Niezależnie od tego czy pracujemy jako specjaliści od bezpieczeństwa, developerzy czy testerzy, z protokołem HTTP i komunikacją w aplikacji mamy do czynienia na co dzień. Niniejszy artykuł został poświęcony podstawowym zagadnieniom związanym z protokołem HTTP. Elementy powiązane z jego szyfrowaną wersją zostały pominięte.

Żądania i odpowiedzi

Komunikację miedzy klientem a serwerem zaczyna klient, który przesyła do serwera żądanie (request). Następnie serwer wysyła do klienta odpowiedź (response). Requesty przesyłane za pośrednictwem przeglądarki możemy podglądnąć w zakładce network za pomocą narzędzi developerskich.

Szablon zarówno responsu jak i requesta jest z góry narzucony przez specyfikację protokołu. W związku z tym każdy z nich będzie wyglądał w podobny sposób. Przeanalizujmy główne części żądania poniżej.

GET /omowienie-ldap-oraz-ataku-ldap-injection/ HTTP/2
Host: bugspace.pl

Pierwsza z linijek żądania składa się z trzech części. Jest to kolejno:

  • GET – wykorzystywana przez żądanie metoda,
  • /omowienie-ldap-oraz-ataku-ldap-injection/ – w naszym przypadku względny adres URL. Warto pamiętać, że możemy w tym miejscu zdefiniować pełny adres URL,
  • HTTP/2 – wersja używanego protokołu.

W drugiej linii znajduje się nagłówek Host, który przyjmuje wartość adresu URL. Kolejne części są nagłówkami dołączanymi przez przeglądarkę, które nie grają znaczenia w niniejszym artykule. Warto dodać, że w naszym przypadku żądanie powinno kończyć się dwoma pustymi liniami – pierwsza po nagłówku Host i druga po wszystkich nagłówkach. Koniec bieżącej linii nazywany jest CRLF i o podatności, która jest z nią związana będziecie mogli dowiedzieć się więcej z artykułów w przyszłości.

Jako odpowiedź otrzymaliśmy od serwera:

HTTP/2 200 OK

Ponownie możemy wyróżnić dwie części:

  • HTTP/2 – wersja używanego protokołu,
  • 200 OK – status odpowiedzi serwera. O nim samym dowiecie się więcej z kolejnej sekcji.

Statusy odpowiedzi

W poprzedniej sekcji wspomnieliśmy o tym, że serwer zwraca status. Status jest niczym innym jak skróconą odpowiedzią serwera. Istnieje pięć typów odpowiedzi: informujące, potwierdzające, przekierowujące, informujące o błędzie po stronie serwera i informujące o błędzie po stronie klienta. Przeanalizujmy część dostępnych statusów.

  • 201 Created – Żądanie powiodło się, a w jego wyniku został utworzony nowy zasób. Jest to typowa odpowiedź wysyłana po żądaniach POST lub niektórych żądaniach PUT,
  • 301 Moved Permanently – Adres URL żądanego zasobu został zmieniony na stałe. Nowy adres URL jest podawany w odpowiedzi,
  • 400 Bad Request – Serwer nie może lub nie chce przetworzyć żądania z powodu czegoś, co jest postrzegane jako błąd klienta (np. nieprawidłowa składnia żądania, nieprawidłowe obramowanie wiadomości żądania lub zwodnicze kierowanie żądania),
  • 401 Unauthorized – Chociaż standard HTTP określa „nieautoryzowany”, semantycznie odpowiedź ta oznacza „nieuwierzytelniony”. Oznacza to, że klient musi się uwierzytelnić, aby uzyskać żądaną odpowiedź,
  • 409 Too Many Requests – Użytkownik wysłał zbyt wiele żądań w określonym czasie,
  • 500 Internal Server Error – Serwer napotkał sytuację, z którą nie wie, jak sobie poradzić.

Pełna lista statusów wraz z ich opisami znajduje się w dokumentacji mozilli.

Metody HTTP

W poprzednim przykładzie analizowaliśmy jedynie żądania z użyciem metody GET. W RFC7231 możemy wyróżnić osiem metod. Są to: OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE oraz CONNECT. Inną metodą opisaną dopiero w RFC5789 jest PATCH.

  1. GET – odpowiada za pobieranie zawartości na stronie. Mogą to być zarówno zdjęcia, jak i reprezentacje danych w formacie JSON,
  2. POST – przesyłanie danych na serwer,
  3. PUT – edycja lub dodanie danych na serwer,
  4. DELETE – usuwanie danych,
  5. HEAD – robi to samo, co metoda GET, z tą różnicą, że nie zwraca treści wiadomości, a jedynie nagłówki,
  6. OPTIONS – wskazuje obsługiwane przez serwer metody. Informacja ta nie zawsze musi być prawdziwa,
  7. TRACE – wykonuje test pętli zwrotnej komunikatów wzdłuż ścieżki do zasobu docelowego,
  8. CONNECT – tworzenie tunelu poprzez serwer proxy,
  9. PATCH – aktualizacja danych.

Przesyłanie danych

Istnieje kilka sposobów na przekazywanie parametrów za pośrednictwem protokołu HTTP. Jest to szczególnie ważne w kontekście bezpieczeństwa, ponieważ właśnie w ten sposób dochodzi do jednych z najbardziej znanych nadużyć takich jak infekcje.

Adres URL

Pierwszym ze sposobów jest przekazywanie danych za pośrednictwem parametrów w adresie URL. Aby lepiej to zrozumieć, przyjrzyjmy się poniższemu żądaniowi.

GET /?s=myValue/ HTTP/2
Host: bugspace.pl

Jest to request przesłany na naszego bloga za pośrednictwem wyszukiwarki. Parametr s odpowiedzialny jest za przefiltrowanie wszystkich postów blogowych, w których występuje fraza myValue. Gdyby istniało więcej parametrów, byłyby one oddzielone od siebie znakiem &. Jako przykład może posłużyć poniższy URL.

https://bugspace.pl?s=myValue&v2=myValue2

Istnieją znaki zastrzeżone, które nie mogą zostać bezpośrednio przesłane poprzez adres URL. Należy do nich np. @. Aby znak został przesłany, trzeba użyć kodowania URL. Zakodowany znak miałby postać %40.

Metoda POST

Jak wiemy, metoda POST służy do przesyłania informacji o danym typie treści żądania. Jest on określany przez nagłówek Content-Type, który może przyjąć wartość text/plain, multipart/form-data oraz application/x-www-form-urlencoded. Aby dane w metodzie POST zostały przesłane, należy je zdefiniować w specjalnym miejscu nazywanym ciałem żądania (body). Znajduje się ono po wszystkich nagłówkach i oddzielone jest od nich pustą linią.

multipart/form-data

Przeanalizujmy przykład żądania multipart/form-data.

POST /test HTTP/1.1
Host: foo.example
Content-Type: multipart/form-data;boundary="boundary"

--boundary
Content-Disposition: form-data; name="field1"

value1
--boundary
Content-Disposition: form-data; name="field2"; filename="example.txt"

value2
--boundary--

W żądaniach typu multipart/form-data wartość jest przesyłana jako blok danych (ang. body part), przy czym każda część jest oddzielona ogranicznikiem (boundary). Jest to najczęściej losowa wartość o danej długości. Parametry są podane w nagłówku Content-Disposition każdej z części.

application/x-www-form-urlencoded

W przypadku żądań application/x-www-form-urlencoded jest prościej. Przekazywane parametry w sekcji body są, podobnie jak w przypadku przekazywanych parametrów URL, oddzielone od siebie znakiem &. Przykład może stanowić poniższe żądanie.

POST /test HTTP/1.1
Host: foo.example
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

field1=value1&field2=value2

To, o czym nie wspomnieliśmy wcześniej, to dołączony nagłówek Content-Length, który wskazuje na długość ciała żądania.

Nagłówki HTTP

Istnieją dwa rodzaje nagłówków – odpowiedzi oraz żądań. Z drugim typem spotkaliśmy się na początku artykułu i był to nagłówek Host. Nagłówki mają cel informacyjny, kontrolny oraz konfiguracyjny. Są dodatkowymi (poza bezpośrednio przesyłanymi) danymi używanymi do komunikacji między klientem a serwerem.

Przeanalizujmy kolejno część z dostępnych nagłówków.

Nagłówki żądań

  • Cookie – wysyła ciasteczko na serwer,
  • Accept – rodzaje zasobów, które akceptuje klient w odpowiedzi od serwera,
  • User-Agent – identyfikacja użytej przez klienta przeglądarki,
  • Accept-Language – klient przesyła informację w jakim języku preferuje odczyt strony.

Nagłówki odpowiedzi

  • Set-Cookie – serwer przesyła żądanie ustawienia ciasteczka,
  • Location – przekierowuje klienta na inny adres,
  • Content-Type – serwer informuje klienta, w jakim formacie i stronie kodowej wysyłany jest dokument.

Źródła

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
https://datatracker.ietf.org/doc/html/rfc2616#section-5.1.1
https://datatracker.ietf.org/doc/html/rfc5789#section-2
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.