NTS – Network Time Security
Napisał: Patryk Krawaczyński
Dzisiaj w Administracja, Bezpieczeństwo Brak komentarzy. (artykuł nr 942, ilość słów: 2107)
K
orzystając z protokołu NTP (ang. Network Time Protocol) możemy mieć pewność, że nasze serwery synchronizują swój czas z wyspecjalizowanymi serwerami czasu opartymi na zegarach atomowych (w zależności od poziomu stratum). Utrzymanie precyzyjnego i aktualnego czasu na serwerach (i ogólnie urządzeniach biorących udział w komunikacji) nie jest tylko kwestią możliwości odpowiedzi na pytanie: „- która godzina?”. Poprawny czas na różnego rodzaju urządzeniach to krytyczny element stabilności, bezpieczeństwa i spójności danych. Jeśli zegar serwera znacząco odbiega od rzeczywistości to wiele usług używających czasu w swoich mechanizmach może zacząć działać niepoprawnie. Na przykład duże różnice w postaci dni, miesięcy i lat mogą powodować uznawanie certyfikatów SSL/TLS za nieważne (wydane w przeszłości lub przyszłości). Mniejsze różnice mieszczące się w oknie od 2 do 5 minut mogą powodować problemy z kodami uwierzytelniającymi dla OTP, 2FA, czy Kerberos – bo różnica czasu między klientem, a serwerem spowoduje ich odrzucenie.
Tyczy się to również spójności logowania zdarzeń w dziennikach systemowych wielu serwerów, gdzie w przypadku włamania lub awarii ustalenie kolejności zajść jest kluczowe do podjęcia dalszych kroków. Nie wspominając już o poprawnym działaniu rozproszonych systemów (aplikacji, baz danych), mechanizmów blokad i transakcji, zaplanowanych zadań (crond) czy czyszczeniu (retencji) danych (sesji, plików tymczasowych). Wszystkie te operacje opierają się na znacznikach czasu, a ich „rozjazd” względem innych, powiązanych systemów może doprowadzić do wielu niechcianych anomalii.
Bardzo wiele protokołów stworzonych w początkowych latach działania internetu zyskało dzisiaj „opakowania” kryptograficzne (HTTPS, FTPS, DNSSEC, SMTPS itd.). Ten sam proces spotkał Network Time Protocol. W 2020 roku zatwierdzono standard (RFC 8915) Network Time Security (NTS), którego zadaniem jest zapewnienie bezpieczniejszej wersji wspomnianego protokołu NTP. Dzięki temu dodano kilka wbudowanych zabezpieczeń, które uodporniły go na ataki typu:
- Man-in-the-Middle (MITM) – osoba postronna może przechwycić i sfałszować pakiety NTP „okłamując” serwer, co do aktualnej godziny.
- Spoofing i replay – atakujący może wysyłać sfałszowane dane lub ponawiać przesyłanie starych, poprawnych pakietów, aby spowodować przesunięcie zegara systemowego.
- DDoS – niezabezpieczone serwery NTP są często wykorzystywane do wzmacniania (ang. Amplification) ataków DDoS (ang. Distributed Denial of Service) na inne sieci lub serwery.
Dodatkowo w celu rozwiązania problemu wprowadzenia kryptografii do systemu dystrybucji czasu bez zwiększenia opóźnień (a tym samym negatywnego wpływu na dokładność otrzymywanego czasu) oddzielono proces szyfrowania od procesu synchronizacji czasu. W procesie uwierzytelniania i dalszej komunikacji z klientami NTS wykorzystuje protokół TLS 1.3 (ang. Transport Layer Security) oraz AEAD (ang. Authenticated Encryption with Associated Data). W uproszczeniu proces ten wygląda następująco:
Wymiana danych kryptograficznych z NTS-KE:
Zanim nastąpi proces wymiany czasu między klientem NTS, a serwerem ten drugi musi „przedstawić się” i uzgodnić klucze szyfrujące. Ta faza zazwyczaj odbywa się poprzez port TCP o numerze 4460. Klient NTS łączy się z serwerem NTS-KE (KE – Key Establishment) za pomocą standardowego protokołu TLS (podobnie jak przy wchodzeniu na stronę za pomocą HTTPS). Dzięki przeprowadzeniu weryfikacji certyfikatu ma pewność, że rozmawia z właściwym serwerem. Następnie wewnątrz bezpiecznego tunelu TLS klient i serwer ustalają wspólne algorytmy kryptograficzne (obecnie standardem i niemal jedynym wyborem jest AEAD_AES_SIV_CMAC_256) do generowania sum kryptograficznych, czyli kodów MAC (ang. Message Authentication Code), którymi będą zabezpieczane pakiety UDP przesyłane między klientem i serwerem. Kolejnym krokiem jest użycie mechanizmu TLS Exported Key Material (RFC 5705), aby wygenerować dwa klucze sesyjne. Polega to na tym, że obie strony (klient i serwer) używają ustalonych parametrów sesji TLS, aby stworzyć te same klucze bez przesyłania ich sobie przez sieć. Jeden będzie służył do generowania kodów MAC w zapytaniach wysyłanych przez klienta, a drugi do generowania kodów MAC przy odpowiedziach wysyłanych przez serwer. Po tym kroku serwer generuje zaszyfrowany swoim głównym kluczem zestaw „ciasteczek” (ang. cookies), a każde z nich zawiera w sobie klucz sesji klienta. Pozostaje tylko przesłać klientowi adres IP i port serwera NTP oraz zestaw wspomnianych ciasteczek. Po tym fakcie połączenie TLS zostaje zamknięte. Odebrane dane od serwera klient przechowuje w swojej pamięci.
Synchronizacja czasu z NTS:
Po zakończeniu fazy ustalania algorytmów i kluczy sesyjnych, właściwa komunikacja odbywa się już przez szybki protokół UDP na standardowym porcie 123. Klient wysyła do serwera pakiet NTPv4, do którego za pomocą rozszerzonych pól (ang. extension fields) dołącza niepowtarzalny identyfikator (UID – Unique Identifier), jedno z otrzymanych ciasteczek oraz kod uwierzytelniający (MAC) wygenerowany za pomocą swojego klucza sesyjnego. Serwer otrzymuje pakiet. Ponieważ proces ten jest „bezstanowy” serwer nie musi pamiętać klienta, ani jego kluczy. Odszyfrowuje otrzymane ciasteczko (w którym ukryty jest klucz sesji klienta) swoim głównym kluczem i za pomocą pozyskanego klucza sesji klienta sprawdza poprawność kodu MAC w ten sposób potwierdzając, że zapytanie jest autentyczne. Serwer wysyła odpowiedź z precyzyjnym czasem, tym samym identyfikatorem UID i nowym ciasteczkiem, aby klient mógł wysłać kolejne zapytanie w przyszłości (zastępując to właśnie zużyte). Wszystko to jest podpisane kodem MAC wygenerowanym kluczem sesyjnym serwera. Klient posiadając klucz sesyjny serwera sprawdza poprawność jego kodu MAC i czy UID w pakiecie zwrotnym jest identyczny z tym, który wysłał ułamek sekundy wcześniej. Jeśli wszystko się zgadza, aktualizuje czas systemowy.
Jak widzimy dzięki zastosowaniu kontroli MAC i UID ataki typu MITM, spoofing i replay są bardzo mocno utrudnione, ponieważ klient akceptuje tylko odpowiedź z aktualnym, unikalnym UID, a cały pakiet musi się jeszcze zgadzać kryptograficznie (podpis MAC stworzony kluczami sesyjnymi). Natomiast, jeśli chodzi o ataki DDoS to serwer NTS zapobiega nim, dbając o to, aby rozmiar zapytania i odpowiedzi był zbliżony nie wykonując efektu wzmocnienia. Aktualny stan rozwoju NTS zyskuje wsparcie w wielu implementacjach klientów NTP, w tym Chrony, NTPsec i ntpd-rs. Liczba serwerów NTS również stale przyrasta. W dodatku jego implementacja jest bardzo prosta. Potrzebujemy jedynie zainstalować klienta wspierającego NTS i wskazać mu serwery, z jakich ma korzystać. Należy pamiętać, że jeśli systemd-timesyncd był wcześniej zainstalowany, zostanie on automatycznie odinstalowany. Zainstalowanie klienta Chrony automatycznie uruchomi jego usługę i włączy ją, aby była uruchamiana po ponownym uruchomieniu serwera:
apt install chrony
Teraz musimy edytować plik konfiguracyjny (/etc/chrony/chrony.conf) i zastąpić istniejące serwery NTP serwerami NTS. Wystarczy, że zakomentujemy wszystkie wiersze zaczynające się od słowa „pool” oraz „sourcedir”, dodając znak „#” na początku wiersza:
# pool ntp.ubuntu.com iburst maxsources 4 # pool 0.ubuntu.pool.ntp.org iburst maxsources 1 # pool 1.ubuntu.pool.ntp.org iburst maxsources 1 # pool 2.ubuntu.pool.ntp.org iburst maxsources 2 server 1.ntp.ubuntu.com nts iburst server 2.ntp.ubuntu.com nts iburst server 3.ntp.ubuntu.com nts iburst server 4.ntp.ubuntu.com nts iburst server sth1.nts.netnod.se nts iburst server sth2.nts.netnod.se nts iburst server time.cloudflare.com nts iburst server ntppool1.time.nl nts iburst server ntppool2.time.nl nts iburst # Use time sources from DHCP. # sourcedir /run/chrony-dhcp # Use NTP sources found in /etc/chrony/sources.d. # sourcedir /etc/chrony/sources.d
Po restarcie usługi możemy uruchomić następujące polecenie jako użytkownik root, aby sprawdzić, czy ustanowienie kluczy NTS powiodło się:
service chrony restart
root@darkstar:~# chronyc authdata Name/IP address Mode KeyID Type KLen Last Atmp NAK Cook CLen ========================================================================= ntp-nts-2.ps5.canonical.> NTS 1 30 128 727 0 0 8 64 ntp-nts-3.ps5.canonical.> NTS 1 30 128 726 0 0 8 64 ntp-nts-2.ps6.canonical.> NTS 1 30 128 727 0 0 8 64 ntp-nts-3.ps6.canonical.> NTS 1 30 128 725 0 0 8 64 sth1-ts.nts.netnod.se NTS 1 15 256 49m 0 0 8 100 sth2-ts.nts.netnod.se NTS 1 15 256 49m 0 0 8 100 time.cloudflare.com NTS 1 30 128 49m 0 0 8 64 ntppool1.time.nl NTS 1 30 128 48m 0 0 8 64 ntppool2.time.nl NTS 1 30 128 48m 0 0 8 64
Kolumny: KeyID, Type i KLen powinny mieć wartości różne od zera. Jeśli są równe zero, musimy sprawdzić logi pod kątem komunikatów o błędach z chronyd. Jeśli wszystkie wartości są dobrze, możemy uruchomić następujące polecenie, aby potwierdzić, że nasz klient wykonuje zapytania za pomocą NTS:
root@darkstar:~# chronyc sources MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^- ntp-nts-2.ps5.canonical.> 2 6 17 2 +1190us[+1190us] +/- 15ms ^- ntp-nts-3.ps5.canonical.> 2 6 17 0 +1078us[+1078us] +/- 15ms ^- ntp-nts-2.ps6.canonical.> 2 6 17 1 -5275us[-5275us] +/- 79ms ^- ntp-nts-3.ps6.canonical.> 2 6 17 0 -2376us[-2376us] +/- 83ms ^- sth1-ts.nts.netnod.se 1 6 17 4 +3798us[+3798us] +/- 19ms ^+ sth2-ts.nts.netnod.se 1 6 17 3 +2253us[+2253us] +/- 17ms ^* time.cloudflare.com 3 6 17 5 -883us[-1072us] +/- 22ms ^+ ntppool1.time.nl 1 6 17 6 -12ms[ -13ms] +/- 23ms ^+ ntppool2.time.nl 1 6 17 6 -10ms[ -11ms] +/- 21ms
Podsumowanie:
Zanim IETF wprowadził standard NTS, bezpieczeństwo NTP opierało się na zaleceniach zawartych w RFC 8633 (Best Current Practices). Dokument ten wskazywał na dwa główne mechanizmy ochrony, które jednak w większych infrastrukturach okazywały się niewystarczające. Pierwszym było uwierzytelnianie kluczem symetrycznym, polegająca na tym, że klient i serwer dzielili ten sam poufny klucz (naczęściej MD5 lub SHA-1). Niestety każdy klient musiał ręcznie konfigurować klucz, który odpowiadał kluczowi na serwerze. Nie istniał również standardowy sposób na automatyczne odświeżanie kluczy. Jeśli klucz został skompromitowany, należało go ręcznie zmienić na wszystkich klientach. Później mechanizm AutoKey miał rozwiązać problem skalowalności kluczy symetrycznych poprzez użycie kryptografii klucza publicznego do automatycznej negocjacji zabezpieczeń. Jednak proces generowania i weryfikacji certyfikatów był obciążający dla procesora, co przy setkach zapytań na sekundę mogło doprowadzić do degradacji w precyzji ustawiania czasu. Pojawiły się również problemy z sieciami korzystającymi z translacji adresów (NAT), ponieważ AutoKey wiązał ciasteczka z adresami IP, co sprawiało, że mechanizm ten często nie działał poprawnie w tego typu sieciach. Innym problemem były też ciasteczka sesyjne – miały tylko 32 bity, co pozwalało na ich odgadnięcie metodą brute force w bardzo krótkim czasie. Do tego doszły liczne luki typu buffer overflow (np. CVE-2009-1252, CVE-2014-9295) pozwalały na zdalne wykonanie kodu poprzez specjalnie spreparowane pakiety. Mimo, że upływa 5 lat od wprowadzenia NTS w wielu sieciach firmowych i pojedynczych serwerach komunikacja NTP nadal jest przesyłana przez „publiczny internet” w „otwartej” formie. Stanowi to potencjalną lukę w infrastrukturze takich organizacji. Dlatego, jeśli NTPv4 posiada już łatwe i skalowalne mechanizmy zabezpieczające komunikację NTP warto z nich skorzystać, aby klienci w wiarygodny sposób potwierdzali, że serwer czasu jest tym, za kogo się podaje i nikt nie może zmanipulować jego przesyłanymi ustawieniami czasu.
Więcej informacji: Manipulating time through (S)NTP, NTP amplification DDoS attack, Network Time Security (NTS) RFC 8915, How to use NTS, Secure NTP with NTS
Poprzedni wpis Brak nowszych postów

