Utrudnianie działania pośrednikom o złych zamiarach za pomocą protokołów HTTPS i HTTP Strict Transport Security

Biorąc pod uwagę ilość danych osobowych, które przepływają przez internet, czyli przez długą serię rurek, szyfrowanie nie jest czymś, co możemy lub powinniśmy lekceważyć. Nowoczesne przeglądarki oferują kilka mechanizmów, które można wykorzystać, aby zapewnić bezpieczeństwo danych użytkowników podczas przesyłania: zabezpieczone pliki cookieścisłe bezpieczeństwo transportu to 2 najważniejsze z nich. Umożliwiają one bezproblemową ochronę użytkowników, ulepszając ich połączenia do HTTPS i gwarantując, że dane użytkowników nigdy nie są przesyłane w postaci zwykłego tekstu.

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

Przesyłanie strony internetowej przez niezaszyfrowane połączenie HTTP jest mniej więcej tak samo niebezpieczne jak wręczenie nieopatrzonej koperty pierwszej napotkanej na ulicy osobie, która zmierza w kierunku urzędu pocztowego. Jeśli masz szczęście, może sama dowieźć paczkę do miejsca przeznaczenia lub przekazać ją następnej osobie, którą zobaczy i która podąża we właściwym kierunku. Ta osoba może zrobić to samo, i tak dalej.

Większość obcych osób w tym improwizowanym łańcuchu jest godna zaufania i nigdy nie zajrzy do otwartego listu ani go nie zmieni. Im więcej razy list zmienia właściciela, tym więcej osób ma do niego pełny dostęp. W końcu jest bardzo prawdopodobne, że odbiorca listu otrzyma coś, ale nie wiadomo, czy będzie to to samo, co zostało przekazane na początku. Może jednak należało zapieczętować kopertę…

Pośrednicy

Niezależnie od tego, czy jest to dobre, czy złe, ogromne obszary internetu polegają na wiarygodności obcych osób. Serwery nie są połączone bezpośrednio, ale przekazują żądania i odpowiedzi z routera na router, jak w grze w telefon.

Możesz zobaczyć te przeskoki za pomocą narzędzia 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 tak dużo. Jeśli jednak wysyłam żądania przez HTTP, każdy z tych pośrednich routerów ma pełny dostęp do moich żądań i odpowiedzi serwerów. Wszystkie dane są przesyłane w postaci niezaszyfrowanego tekstu, a każdy z tych pośredników może działać jako człowiek pośrodku, czytając nasze dane lub nawet manipulując nimi w trakcie przesyłania.

Co gorsza, tego typu 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 umożliwiłby Ci sprawdzenie, czy otrzymane dane są _dokładnie_ takimi samymi danymi, które zostały wysłane. Jeśli ktoś zdecyduje się zamienić mój internet na głowę, to nie mam zbyt wielu możliwości.

Czy to jest połączenie zabezpieczone?

Przejście z niezaszyfrowanego połączenia HTTP na szyfrowane połączenie HTTPS to najlepsza obrona przed pośrednikami. Połączenia HTTPS szyfrują cały kanał od końca do końca przed wysłaniem jakichkolwiek danych, co uniemożliwia maszynom znajdującym się między Tobą a miejscem docelowym odczytanie lub zmodyfikowanie danych w trakcie przesyłania.

Omnibox w Chrome zawiera sporo informacji o stanie połączenia.
Womniboks w Chrome zawiera sporo szczegółowych informacji o stanie połączenia.

Bezpieczeństwo zapewniane przez HTTPS opiera się na koncepcji kluczy kryptograficznych publicznych i prywatnych. Szczegóły (na szczęście) wykraczają poza zakres tego artykułu, ale główna zasada jest dość prosta: dane zaszyfrowane za pomocą danego klucza publicznego można tylko odszyfrować za pomocą odpowiedniego klucza prywatnego. Gdy przeglądarka inicjuje protokół HTTPS w celu utworzenia bezpiecznego kanału, serwer udostępnia certyfikat, który przekazuje przeglądarce wszystkie informacje potrzebne do zweryfikowania tożsamości, sprawdzając, czy serwer ma odpowiedni klucz prywatny. Od tego momentu cała komunikacja jest szyfrowana w taki sposób, aby potwierdzać, że żądania są dostarczane do i odpowiedzi odbierane od uwierzytelnionego serwera.

HTTPS zapewnia więc pewną gwarancję, że komunikujesz się z serwerem, z którym chcesz, oraz że nikt inny nie podsłuchuje ani nie zmienia danych przesyłanych przez sieć. Takie szyfrowanie jest absolutnym warunkiem bezpieczeństwa w internecie. Jeśli aplikacja nie jest obecnie dostarczana za pomocą protokołu HTTPS, jest podatna na ataki. Rozwiąż problem Ars Technica udostępnia świetny przewodnik po uzyskiwaniu i instalowaniu certyfikatów (bezpłatnie), który zawiera szczegółowe informacje techniczne. Konfiguracja różni się w zależności od dostawcy i serwera, ale proces żądania certyfikatu jest wszędzie taki sam.

Bezpieczeństwo w standardzie

Po przesłaniu prośby o instalację certyfikatu i jego zainstalowaniu upewnij się, że użytkownicy skorzystają z Twojej ciężkiej pracy: przejdź do przejrzystej migracji obecnych użytkowników na połączenia HTTPS za pomocą magicznego przekierowania HTTP i zapewnij, że pliki cookie są tylko dostarczane za pomocą bezpiecznych połączeń.

Proszę tędy

Gdy użytkownik wejdzie na 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 typu przekierowania można łatwo skonfigurować na serwerach takich jak Apache czy Nginx. Na przykład konfiguracja Nginx, która przekierowuje z http://example.com/ do 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 się w ramach bezstanowego protokołu HTTP. Dane przechowywane w plikach cookie, w tym informacje poufne, takie jak identyfikatory sesji, są wysyłane wraz z każdą prośbą, co pozwala serwerowi określić, któremu użytkownikowi ma w danym momencie odpowiadać. Gdy już upewnisz się, że użytkownicy otwierają Twoją witrynę przez HTTPS, musisz 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 jawnej postaci.

Ustawienie pliku cookie zwykle wiąże się z użyciem nagłówka 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 z wykorzystaniem śledzenia pojedynczego słowa kluczowego:

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

Pliki cookie ustawione za pomocą parametru secure nigdy nie zostaną wysłane przez HTTP.

Zamknij otwarte okno

Przekierowanie przezroczyste do HTTPS oznacza, że przez większość czasu, gdy użytkownicy są w Twojej witrynie, będą korzystać z bezpiecznego połączenia. Pozostawia jednak niewielkie okno na atak: początkowe połączenie HTTP jest całkowicie otwarte i niechronione przed odczytywaniem danych z protokołu SSL i powiązanymi z nim atakami. Ponieważ 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 niepewne połączenie HTTP niezależnie od intencji serwera.

Ryzyko tego rodzaju ataków możesz ograniczyć, prosząc przeglądarkę o wdrożenie mechanizmu HTTP Strict Transport Security (HSTS). Wysłanie nagłówka HTTP Strict-Transport-Security instruuje przeglądarkę, aby przekierowała z HTTP na HTTPS po stronie klienta, bez jakiegokolwiek kontaktu z siecią (co również pozytywnie wpływa na wydajność – 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: więcej informacji znajdziesz na stronie caniuse), odnotują, że ta konkretna witryna poprosiła o dostęp tylko przez HTTPS, co oznacza, że niezależnie od tego, jak użytkownik do niej dotrze, będzie ona otwierana przez HTTPS. Nawet jeśli wpisze w przeglądarce http://example.com/, połączy się z HTTPS, nie nawiązując połączenia HTTP. Co więcej, jeśli przeglądarka wykryje nieprawidłowy certyfikat (np. próbę podszywania się pod tożsamość serwera), użytkownicy nie będą mogli kontynuować przez HTTP. To świetne rozwiązanie.

Przeglądarka wygaśnie stan HSTS serwera po max-age sekundach (w tym przykładzie około miesiąca); ustaw tę wartość na odpowiednio wysoką.

Możesz też zadbać o to, aby wszystkie subdomeny źródła były chronione, 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 podróżowanie

HTTPS to jedyny sposób na pewność, że wysyłane dane dotrą do właściwego odbiorcy w całości. Już dziś skonfiguruj bezpieczne połączenia dla swoich witryn i aplikacji. To dość prosty proces, który pomoże Ci chronić dane klientów. Gdy już utworzysz kanał szyfrowany, przekieruj użytkowników na to bezpieczne połączenie, niezależnie od tego, w jaki sposób docierają do Twojej witryny, wysyłając odpowiedź HTTP 301. Następnie upewnij się, że wszystkie informacje o sesji z danymi wrażliwymi użytkowników korzystają tylko z tego bezpiecznego połączenia. Aby to zrobić, podczas konfigurowania plików cookie dodaj słowo kluczowe secure. Gdy to zrobisz, zadbaj o to, aby użytkownicy nigdy nie wypadli z autobusu: chroń ich, zapewniając, że ich przeglądarka będzie działać prawidłowo, wysyłając nagłówek Strict-Transport-Security.

Skonfigurowanie protokołu HTTPS nie wymaga wiele pracy, a przynosi ogromne korzyści dla witryny i jej użytkowników. Naprawdę warto.

Zasoby

  • StartSSL oferuje bezpłatne certyfikaty zweryfikowane przez domenę. Nie ma nic lepszego niż bezpłatne. Przejście na wyższy poziom weryfikacji jest oczywiście możliwe i niedrogie.
  • Test serwera SSL: gdy skonfigurujesz HTTPS na serwerach, sprawdź, czy wszystko działa prawidłowo, wykonując test serwera SSL Labs. Otrzymasz szczegółowy raport, który pokaże, czy wszystko działa prawidłowo.
  • Warto przeczytać najnowszy artykuł Ars Technica „Securing your Web Server with SSL/TLS” (zabezpieczanie serwera WWW za pomocą SSL/TLS), aby dowiedzieć się więcej o szczegółach konfigurowania serwera.
  • Warto zapoznać się ze specyfikacją HTTP Strict Transport Security (RFC6797), aby uzyskać wszystkie informacje techniczne o nagłówku Strict-Transport-Security, które mogą Ci być potrzebne.
  • Gdy już dokładnie wiesz, co robisz, możesz podać w reklamie, że Twoja witryna powinna być dostępna tylko z użyciem określonego zestawu certyfikatów. W IETF trwają prace nad rozwiązaniami, które umożliwią Ci to za pomocą nagłówka Public-Key-Pins. Jest to wciąż nowy temat, ale warto go śledzić.