Zabezpieczanie przed szkodliwymi pośrednikami za pomocą protokołu HTTPS i mechanizmu HTTP Strict Transport Security

Biorąc pod uwagę ilość danych osobowych, które przepływają przez wielką sieć rur, jaką jest internet, szyfrowanie nie jest czymś, co możemy lub powinniśmy lekceważyć. Nowoczesne przeglądarki oferują kilka mechanizmów, których możesz użyć, aby zapewnić bezpieczeństwo danych użytkowników podczas przesyłania. Dwa najważniejsze z nich to bezpieczne pliki cookie i Strict Transport Security. Pozwalają one bezproblemowo chronić użytkowników, uaktualniając ich połączenia do HTTPS i gwarantując, że dane użytkowników nigdy nie są wysyłane w formie niezaszyfrowanej.

Dlaczego warto wziąć to pod uwagę? Zastanów się nad tymi kwestiami:

Przesyłanie strony internetowej przez niezaszyfrowane połączenie HTTP jest mniej więcej tym samym co przekazanie niezaklejonej koperty pierwszej osobie, którą zobaczysz na ulicy i która wygląda, jakby szła w kierunku poczty. Jeśli będziesz mieć szczęście, może sama dostarczy ją na miejsce albo przekaże kolejnej osobie, która idzie we właściwym kierunku. Ta osoba może zrobić to samo i tak dalej.

Większość nieznajomych w tym improwizowanym łańcuchu jest godna zaufania i nigdy nie zajrzałaby do otwartego listu ani nie zmieniła jego treści. Jednak im więcej razy list przechodzi z rąk do rąk, tym więcej osób ma pełny dostęp do wysyłanego listu. Ostatecznie jest bardzo prawdopodobne, że adresat listu otrzyma coś pocztą, ale to, czy to coś będzie tym samym, co zostało wysłane, jest kwestią otwartą. Może trzeba było zakleić kopertę…

Pośrednicy

Niezależnie od tego, czy nam się to podoba, czy nie, ogromne obszary internetu opierają się na zaufaniu do nieznajomych. Serwery nie są połączone bezpośrednio, ale przekazują żądania i odpowiedzi od routera do routera, jak w głuchym telefonie.

Możesz zobaczyć te przeskoki w działaniu za pomocą traceroute. Trasa z mojego komputera do HTML5Rocks wygląda mniej więcej tak:

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

13 przeskoków to nie jest zły wynik. Jeśli jednak wysyłam żądania przez HTTP, każdy z tych routerów pośrednich ma pełny dostęp do moich żądań i odpowiedzi serwerów. Wszystkie dane są przesyłane jako niezaszyfrowany zwykły tekst, a każdy z tych pośredników może działać jako atakujący typu „człowiek w środku”, odczytując moje dane, a nawet manipulując nimi podczas przesyłania.

Co gorsza, tego rodzaju przechwytywanie jest praktycznie niewykrywalne. Złośliwie zmodyfikowana odpowiedź HTTP wygląda dokładnie tak samo jak prawidłowa odpowiedź, ponieważ nie ma mechanizmu, który pozwoliłby upewnić się, że otrzymane dane są _dokładnie_ tymi samymi danymi, które zostały wysłane. Jeśli ktoś postanowi wywrócić mój internet do góry nogami dla żartu, to mam pecha.

Czy to bezpieczna linia?

Przejście z protokołu HTTP na bezpieczne połączenie HTTPS to najlepsza obrona przed pośrednikami. Połączenia HTTPS szyfrują cały kanał od początku do końca, zanim zostaną wysłane jakiekolwiek dane, co uniemożliwia maszynom znajdującym się między Tobą a miejscem docelowym odczytywanie lub modyfikowanie danych w ruchu.

Omniboks Chrome zawiera sporo szczegółowych informacji o stanie połączenia.
Omniboks Chrome zawiera sporo szczegółowych informacji o stanie połączenia.

Bezpieczeństwo, które zapewnia protokół HTTPS, opiera się na koncepcji publicznych i prywatnych kluczy kryptograficznych. Szczegółowe omówienie tego zagadnienia wykracza (na szczęście) poza zakres tego artykułu, ale podstawowe założenie jest dość proste: dane zaszyfrowane danym kluczem publicznym można odszyfrować tylko za pomocą odpowiadającego mu klucza prywatnego. Gdy przeglądarka rozpoczyna uzgadnianie HTTPS w celu utworzenia bezpiecznego kanału, serwer dostarcza certyfikat, który zawiera wszystkie informacje niezbędne do zweryfikowania tożsamości serwera przez sprawdzenie, czy ma on odpowiedni klucz prywatny. Od tego momentu cała komunikacja jest szyfrowana w sposób, który potwierdza, że żądania są dostarczane do serwera uwierzytelniania, a odpowiedzi są z niego odbierane.

HTTPS daje więc pewność, że komunikujesz się z serwerem, z którym chcesz się komunikować, i że nikt inny nie podsłuchuje ani nie modyfikuje przesyłanych danych. Ten rodzaj szyfrowania jest absolutnym warunkiem bezpieczeństwa w internecie. Jeśli Twoja aplikacja nie jest obecnie dostarczana przez HTTPS, jest podatna na ataki. Rozwiąż problem Ars Technica ma świetny przewodnik po uzyskiwaniu i instalowaniu certyfikatu (bezpłatnie), który polecam, jeśli chcesz poznać szczegóły techniczne. Konfiguracja będzie się różnić w zależności od dostawcy i serwera, ale proces żądania certyfikatu jest wszędzie taki sam.

Bezpieczeństwo w standardzie

Po uzyskaniu i zainstalowaniu certyfikatu zadbaj o to, aby użytkownicy mogli korzystać z efektów Twojej pracy: przenieś dotychczasowych użytkowników na połączenia HTTPS, korzystając z magii przekierowania HTTP, i upewnij się, że pliki cookie są dostarczane tylko przez bezpieczne połączenia.

Tędy, proszę.

Gdy użytkownik odwiedzi stronę http://example.com/, przekieruj go na stronę https://example.com/, wysyłając odpowiedź 301 Moved Permanently z odpowiednim nagłówkiem Location:

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

Tego rodzaju przekierowanie można łatwo skonfigurować na serwerach takich jak Apache czy Nginx. Na przykład konfiguracja Nginx, która przekierowuje z http://example.com/ na https://example.com/, wygląda tak:

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

Pliki cookie umożliwiają nam zapewnianie użytkownikom płynnego logowania w ramach bezstanowego protokołu HTTP. Dane przechowywane w plikach cookie, w tym informacje poufne, takie jak identyfikatory sesji, są wysyłane z każdym żądaniem, dzięki czemu serwer może określić, któremu użytkownikowi odpowiada w danym momencie. Gdy upewnimy się, że użytkownicy odwiedzają naszą witrynę przez HTTPS, powinniśmy też zadbać o to, aby dane wrażliwe przechowywane w plikach cookie były przesyłane tylko przez bezpieczne połączenie i nigdy nie były wysyłane w formie jawnego tekstu.

Ustawienie pliku cookie zwykle obejmuje nagłówek HTTP, który wygląda mniej więcej tak:

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

Możesz poinstruować przeglądarkę, aby ograniczyła użycie pliku cookie do bezpiecznych sesji, dodając jedno słowo kluczowe:

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

Pliki cookie ustawione za pomocą słowa kluczowego secure nigdy nie będą wysyłane przez HTTP.

Zamykanie otwartego okna

Przezroczyste przekierowanie do HTTPS oznacza, że przez większość czasu użytkownicy będą korzystać z Twojej witryny przez bezpieczne połączenie. Pozostawia jednak niewielką lukę, która może zostać wykorzystana do ataku: początkowe połączenie HTTP jest całkowicie otwarte i podatne na ataki typu SSL stripping i podobne. Ponieważ osoba przeprowadzająca atak typu „man in the middle” ma pełny dostęp do początkowego żądania HTTP, może działać jako serwer proxy między Tobą a serwerem, utrzymując niezabezpieczone połączenie HTTP niezależnie od intencji serwera.

Możesz ograniczyć ryzyko tego rodzaju ataku, prosząc przeglądarkę o wymuszenie mechanizmu HTTP Strict Transport Security (HSTS). Wysłanie nagłówka HTTP Strict-Transport-Security powoduje, że przeglądarka przekierowuje HTTP do HTTPS po stronie klienta, bez konieczności korzystania z sieci (jest to też świetne rozwiązanie pod względem wydajności – najlepsze żądanie to takie, którego nie trzeba wysyłać):

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

Przeglądarki, które obsługują ten nagłówek (obecnie Firefox, Chrome i Opera – szczegółowe informacje znajdziesz na stronie caniuse), odnotują, że ta witryna wymaga dostępu tylko przez HTTPS. Oznacza to, że niezależnie od tego, jak użytkownik trafi do witryny, będzie ją odwiedzać przez HTTPS. Nawet jeśli wpisze w przeglądarce http://example.com/, zostanie przekierowana na stronę HTTPS bez nawiązywania połączenia HTTP. Co więcej, jeśli przeglądarka wykryje nieprawidłowy certyfikat (potencjalnie próbujący podszyć się pod tożsamość serwera), użytkownicy nie będą mogli kontynuować przez HTTP. To świetne rozwiązanie, bo nie ma tu miejsca na półśrodki.

Przeglądarka wygasi stan HSTS serwera po max-age sekundach (w tym przykładzie to około miesiąca). Ustaw odpowiednio wysoką wartość.

Możesz też zapewnić ochronę wszystkich subdomen źródła, dodając do nagłówka dyrektywę includeSubDomains:

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

Bezpieczne korzystanie z usługi

HTTPS to jedyny sposób, aby mieć pewność, że wysyłane dane dotrą do zamierzonego odbiorcy w nienaruszonym stanie. Już dziś skonfiguruj bezpieczne połączenia dla swoich witryn i aplikacji. To dość prosty proces, który pomoże Ci chronić dane klientów. Po skonfigurowaniu zaszyfrowanego kanału należy w przejrzysty sposób przekierowywać użytkowników do tego bezpiecznego połączenia, niezależnie od tego, jak trafili na Twoją witrynę, wysyłając odpowiedź HTTP 301. Następnie upewnij się, że wszystkie poufne informacje o sesjach użytkowników korzystają wyłącznie z tego bezpiecznego połączenia, dodając słowo kluczowe secure podczas ustawiania plików cookie. Gdy to zrobisz, upewnij się, że użytkownicy nigdy przypadkowo nie wypadną z autobusu: chroń ich, dbając o to, aby ich przeglądarka działała prawidłowo, wysyłając nagłówek Strict-Transport-Security.

Konfiguracja HTTPS nie wymaga wiele wysiłku, a zapewnia ogromne korzyści dla witryny i jej użytkowników. Warto poświęcić na to trochę czasu.

Zasoby

  • StartSSL oferuje bezpłatne certyfikaty dla zweryfikowanych domen. Nie ma nic lepszego niż bezpłatne usługi. Przejście na wyższe poziomy weryfikacji jest oczywiście możliwe i ma rozsądną cenę.
  • SSL Server Test: po skonfigurowaniu protokołu HTTPS na serwerach sprawdź, czy wszystko działa prawidłowo, przeprowadzając test serwera SSL Labs. Otrzymasz szczegółowy raport, który pokaże, czy wszystko działa prawidłowo.
  • Warto przeczytać niedawny artykuł w Ars Technica „Securing your Web Server with SSL/TLS” (Zabezpieczanie serwera WWW za pomocą SSL/TLS), aby dowiedzieć się więcej o szczegółach konfiguracji serwera.
  • Warto przejrzeć specyfikację HTTP Strict Transport Security (RFC6797), aby poznać wszystkie informacje techniczne dotyczące nagłówka Strict-Transport-Security.
  • Gdy już będziesz wiedzieć, co robisz, możesz na przykład ogłosić, że Twoja witryna powinna być dostępna tylko za pomocą określonego zestawu certyfikatów. W IETF trwają prace nad rozwiązaniem, które pozwoliłoby na to za pomocą nagłówka Public-Key-Pins. To dopiero początek, ale warto śledzić postępy.