NFsec Logo

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

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

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.
  • Możemy też potwierdzić skuteczność ataku DoS poprzez porównanie wartości uptime przed i po ataku.
  • A także określić, czy host został zaktualizowany na ostatnio wykrytą podatność wymagającą restartu serwera.

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

Do sprawdzania serwerów znajdujących się za load balancerem możemy użyć polecenia hping3:

root@darkstar:~# hping3 -c 4 -S -p 443 --tcp-timestamp firma.corp
HPING firma.corp (eth0 1.2.3.4): S set, 40 headers + 0 data bytes
len=56 ip=1.2.3.4 ttl=53 DF id=0 sport=443 flags=SA seq=0 win=28480 rtt=35.7 ms
  TCP timestamp: tcpts=184791668

len=56 ip=1.2.3.4 ttl=53 DF id=0 sport=443 flags=SA seq=1 win=28480 rtt=39.4 ms
  TCP timestamp: tcpts=184791918
  HZ seems hz=100
  System uptime seems: 21 days, 9 hours, 18 minutes, 39 seconds

len=56 ip=1.2.3.4 ttl=53 DF id=0 sport=443 flags=SA seq=2 win=28480 rtt=39.1 ms
  TCP timestamp: tcpts=184792168
  HZ seems hz=100
  System uptime seems: 21 days, 9 hours, 18 minutes, 41 seconds

len=56 ip=1.2.3.4 ttl=53 DF id=0 sport=443 flags=SA seq=3 win=28480 rtt=38.9 ms
  TCP timestamp: tcpts=184792418
  HZ seems hz=100
  System uptime seems: 21 days, 9 hours, 18 minutes, 44 seconds


--- firma.corp hping statistic ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 35.7/38.3/39.4 ms
root@darkstar:~# hping3 -c 4 -S -p 443 --tcp-timestamp firma.corp
HPING firma.corp (eth0 1.2.3.4): S set, 40 headers + 0 data bytes
len=56 ip=1.2.3.4 ttl=54 DF id=0 sport=443 flags=SA seq=0 win=28480 rtt=39.2 ms
  TCP timestamp: tcpts=144218929

len=56 ip=1.2.3.4 ttl=54 DF id=0 sport=443 flags=SA seq=1 win=28480 rtt=39.0 ms
  TCP timestamp: tcpts=144219179
  HZ seems hz=100
  System uptime seems: 16 days, 16 hours, 36 minutes, 31 seconds

len=56 ip=1.2.3.4 ttl=54 DF id=0 sport=443 flags=SA seq=2 win=28480 rtt=38.9 ms
  TCP timestamp: tcpts=144219429
  HZ seems hz=100
  System uptime seems: 16 days, 16 hours, 36 minutes, 34 seconds

len=56 ip=1.2.3.4 ttl=54 DF id=0 sport=443 flags=SA seq=3 win=28480 rtt=38.9 ms
  TCP timestamp: tcpts=144219679
  HZ seems hz=100
  System uptime seems: 16 days, 16 hours, 36 minutes, 36 seconds


--- firma.corp hping statistic ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 38.9/39.0/39.2 ms
root@darkstar:~# hping3 -c 4 -S -p 443 --tcp-timestamp firma.corp
HPING firma.corp (eth0 1.2.3.4): S set, 40 headers + 0 data bytes
len=56 ip=1.2.3.4 ttl=54 DF id=0 sport=443 flags=SA seq=0 win=28480 rtt=35.7 ms
  TCP timestamp: tcpts=1766083410

len=56 ip=1.2.3.4 ttl=54 DF id=0 sport=443 flags=SA seq=1 win=28480 rtt=35.5 ms
  TCP timestamp: tcpts=1766083660
  HZ seems hz=100
  System uptime seems: 204 days, 9 hours, 47 minutes, 16 seconds

len=56 ip=1.2.3.4 ttl=54 DF id=0 sport=443 flags=SA seq=2 win=28480 rtt=35.2 ms
  TCP timestamp: tcpts=1766083910
  HZ seems hz=100
  System uptime seems: 204 days, 9 hours, 47 minutes, 19 seconds

len=56 ip=1.2.3.4 ttl=54 DF id=0 sport=443 flags=SA seq=3 win=28480 rtt=38.9 ms
  TCP timestamp: tcpts=1766084160
  HZ seems hz=100
  System uptime seems: 204 days, 9 hours, 47 minutes, 21 seconds


--- firma.corp hping statistic ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 35.2/36.3/38.9 ms

Jak widzimy, udało nam się zidentyfikować trzy różne serwery za tym samym adresem IP i portem. 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, Misusing TCP Timestamps

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

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

Komentowanie tego wpisu jest zablokowane.