NFsec Logo

TCP/IP Timestamps – odczytywanie uptime hosta w sieci i nie tylko

12/12/2010 w Bezpieczeństwo Brak komentarzy.  (artykuł nr 295, ilość słów: 1271)

Z

naczniki czasu określone przez RFC1323 służą między innymi do ochrony przed „owijaniem” się numerów sekwencyjnych (PAWS – ang. Protection Against Wrapped Sequence Numbers), czy obliczaniem opóźnienia pomiędzy wysłaniem segmentu (PDU – ang. Protocol Data Unit dla warstwy transportu), a otrzymaniem potwierdzenia jego otrzymania (RTTM – ang. Round-Trip-Time Measurement).

Niestety – dzięki opcji timestamp jesteśmy też w stanie bardzo prosto obliczyć uptime, czyli jak długo maszyna pracuje w sieci bez restartowania, a tym samym dowiedzieć się np. czy zostały na nią nałożone aktualizacje bezpieczeństwa wymagające restartu całego systemu. Wynika to z faktu, że wszystkie systemy operacyjne fabrycznie podnoszą wartość timestamp w przesyłanych pakietach o wartość X, co X milisekund (np. Linux podnosi wartość o 1, co 1 ms, IOS Cisco, co .1 ms, a podstawa dzisiejszych systemów BSD – 4.4BSD – co 500 ms). Jeśli więc posiadamy informację o rodzaju używanego systemu operacyjnego i informację o ile podnosi wartość timestamp – możemy podzielić ją przez liczbę inkrementacji na sekundę, aby otrzymać uptime wyrażony w sekundach. Jednak to nie wszystko. Jak wykazał Elie aka Lupin w swojej pracy pt. „TCP Timestamp to count hosts behind NAT” na łamach magazynu Phrack #63 nie koniecznie musimy znać rodzaj systemu operacyjnego oraz wartość o jaką podnosi znaczniki czasu. Wystarczy pobrać dwa razy wartość timestamp nazwać ją np. ts1 i ts2 oraz oznaczyć czas – s1 i s2 (wyrażony w sekundach), w którym zebraliśmy próbki. Z tymi informacjami do obliczenia wzrostu wystarczy użyć równania:

X = (ts1 - ts2) / (s1 - s2)

Idąc krok dalej – dzięki znacznikom czasu, które używane są w TCP i poniższemu algorytmowi – możemy policzyć liczbę komputerów znajdujących się za mechanizmem NAT (mechanizm NAT nie przepisuje wartości timestamp):

  • Każdemu odkrytemu już hostowi będzie przypisywany pakiet na podstawie równania. Każdy host posiada unikalny wynik równania chyba, że dwa hosty zostały uruchomione w tej samej sekundzie.
  • Jeśli pakiet nie zostanie dopasowany do już zebranych wzorców – oznacza to, że został wykryty nowy host za mechanizmem NAT

Patrząc na tą sytuację od strony komputera klienckiego – dzięki znacznikom czasu różne programy i urządzenia w Internecie mogą odczytywać, obliczać i tworzyć indywidualne profile (służące do śledzenia aktywności) tzw. przesunięć czasowych impulsów zegarowych (ang. clock skew) naszego komputera – w ten sposób nasza maszyna jest oznaczona „sprzętowo – programowym” ciasteczkiem już na poziomie warstwy transportowej (a nie aplikacji). Przykładem odczytania wartości uptime jest użycie popularnego skanera nmap z opcją OS detection. Na hoście agresora wywołujemy skanowanie:

nmap -PN -O -v nfsec.pl

Zwraca ono nam informację:

(...)
No exact OS matches for host (test conditions non-ideal).
Uptime: 11.853 days (since Mon Nov 29 23:29:30 2010)
TCP Sequence Prediction: Difficulty=205 (Good luck!)
IP ID Sequence Generation: All zeros
(...)

Potwierdzamy ją na skanowanym hoście:

root@nfsec:~# uname -a
Linux nfsec 2.6.33-4-smp #2 SMP Wed May 12 22:47:36 CDT 2010 (...)
root@nfsec:~# uptime
 20:01:07 up 11 days, 20:33,  1 user,  load average: 0.11, 0.04, 0.01

Jednym z możliwych rozwiązań wycieku tego typu danych przez protokół TCP jest po prostu wyłączenie opcji znaczników czasu. Dla systemu Linux możemy wykonać to za pomocą polecenia:

echo 0  >/proc/sys/net/ipv4/tcp_timestamps

Lub umieszczeniu poniższej wartości w pliku /etc/sysctl.conf:

net.ipv4.tcp_timestamps = 0

Niestety jest to bezpieczne rozwiązanie tylko dla sieci o małych prędkościach przesyłu danych. Pole numerów sekwencyjnych w protokole TCP ma tylko 32 bity, co ogranicza liczbę dostępnych numerów sekwencyjnych. W sieciach o dużej wydajności i transferze danych możliwe jest wyczerpanie się numerów sekwencyjnych przed przemierzeniem pakietu przez sieć. Jeśli dane przesyłane są w sieci z prędkością 1 Gbps, numery sekwencyjne mogą wyczerpać się np. od 17 do 34 sekund (w zależności od uzyskanej szybkości transferu). Jeśli z jakiegoś powodu jeden z pakietów został opóźniony potencjalnie możliwe jest, że inny pakiet będzie istniał z takim samym numerem sekwencyjnym i zostanie zaakceptowany jako bieżący. Wówczas może dojść do cichego zniszczenia danych (ang. silent data corruption). Dlatego w celu uniknięcia nieporozumień podczas transmisji w przypadku powtarzających się numerów sekwencyjnych używa się znaczników czasu jako rozszerzenia tych numerów. W ten sposób pakiety posiadają postępujące (wzrastające) znaczniki czasu. Jeśli host wykryje, że timestamp segmentu jest mniejszy niż wartość ostatniego dobrego znacznika lub numer sekwencyjny jest większy niż ostatnie wysłane potwierdzenie – zostaje on odrzucony w transmisji.

Opisany powyżej mechanizm nazywa się PAWS i jest on w dodatku podatny na atak Denial of Service. W przypadku, gdy atakujący naszą sieć ma możliwość ustalenia (podsłuchania) źródłowych i docelowych portów oraz adresów IP obu hostów, które są zaangażowane w aktywne połączenie – może on spróbować wstrzykiwać specjalnie spreparowane segmenty (zawierające sfałszowane wartości timestamp) w aktywne połączenie (atak Man-in-the-middle). Jeśli jeden z hostów odbierze tak podrobiony segment może ustawić swój wewnętrzny timer by dopasować się do przesłanej i sfałszowanej wartości timestamp. Jeśli sfałszowana wartość znacznika czasu jest większa od kolejnych wartości pochodzących od prawdziwych segmentów – host odbierający kolejne dane uzna, że przychodzące segmenty są zbyt stare i odrzuci je. W rezultacie przepływ danych między hostami zostanie przerwany.

Podobny wyciek danych występuje w protokole ICMP. Zapytanie ICMP Timestamp (typ 13) pozwala hostowi na poznanie czasu jaki jest aktualny w strefie, w której jest umieszczony zdalny host. Odległy host używa odpowiedzi ICMP Timestamp Replay (typ 14), aby przekazać tę informację hostowi, który o nią poprosił. Odpowiedź od odległego hosta zawiera czas jaki był aktualny, w chwili otrzymania zapytania o ten czas. Czas jest podawany w ilości milisekund jakie upłynęły od czasu północy w Czasie Uniwersalnym (ang. Universal Time (UT)):

nfsec:~# hping3 -V -C 13 -c 3 darkstar.nfsec.pl
using eth0, addr: 1.1.1.1, MTU: 1500
HPING darkstar.nfsec.pl (eth0 2.2.2.2): icmp mode set, 28 headers + 0 data bytes
len=46 ip=2.2.2.2 ttl=56 id=59885 tos=0 iplen=40
icmp_seq=0 rtt=28.7 ms
ICMP timestamp: Originate=57026070 Receive=50367488 Transmit=50367488
ICMP timestamp RTT tsrtt=29

len=46 ip=2.2.2.2 ttl=56 id=59886 tos=0 iplen=40
icmp_seq=1 rtt=21.1 ms
ICMP timestamp: Originate=57027070 Receive=50368481 Transmit=50368481
ICMP timestamp RTT tsrtt=22

len=46 ip=2.2.2.2 ttl=56 id=59887 tos=0 iplen=40
icmp_seq=2 rtt=19.3 ms
ICMP timestamp: Originate=57028071 Receive=50369479 Transmit=50369479
ICMP timestamp RTT tsrtt=19


--- darkstar.nfsec.pl hping statistic ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 19.3/23.0/28.7 ms

Blokadę tego typu komunikatów ICMP możemy skonfigurować na zaporze systemowej:

iptables -A INPUT -p icmp --icmp-type 13 -j DROP
iptables -A OUTPUT -p icmp --icmp-type 14 -j DROP

Warto wspomnieć, że w systemie OpenBSD wartość pierwszego znacznika czasu podczas nawiązywania nowej sesji TCP/IP jest wybierana losowo. W ten sposób wyeliminowany został wyciek informacji dotyczący uptime’mu badanej maszyny. Jeśli chodzi o system Linux to wyłączenie opcji timestamp w protokole TCP powinno być rozważane dla każdej infrastruktury sieciowej z osobna. Szczególnie należy wziąć pod uwagę rodzaj usług jakie świadczy się na poszczególnej maszynie np. mogą wystąpić problemy w przypadku serwerów FTP udostępniających większe objętościowo pliki z prędkością 100 Mbps. Lecz jeśli mimo np. gigabitowej szybkości łącza pojedyncza sesja TCP/IP nie przekracza 10 sekund dla przesyłanych informacji z szybkością 125 MBps – istnieje małe ryzyko wyczerpania się numerów sekwencyjnych i zniekształcenia danych (przykładowa tabela czasów i prędkości oraz wzory znajdują się na 5 i 6 stronie RFC 1323). Nie musimy również się martwić o samą wydajność transferu, która w algorytmie zapobiegania zatorów (ang. congestion avoidance algorithm) TCP Tahoe and Reno ustawiała wielkość okna na podstawie wartości RTT dostarczanej przez znaczniki czasu. Od wersji 2.6.19 i wyższych jądro Linuksa używa standardowo algorytmu CUBIC TCP, który jest niezależny od wartości RTT.

Więcej informacji: Protokół TCP, ISS 52126, ISS 20635, KB 224829, Obtaining System Uptime Remotely, Target-Based TCP Timestamp Stream Reassembly

Kategorie K a t e g o r i e : Bezpieczeństwo

Tagi T a g i : , , , , , , , , , , , , , , , ,

Zostaw odpowiedź.

Musisz być zalogowany by móc komentować.