Uwalniamy program ping od setuid i capabilities
Napisał: Patryk Krawaczyński
Wczoraj w Administracja, Bezpieczeństwo Brak komentarzy. (artykuł nr 949, ilość słów: 483)
N
iewiele osób wie, że od wersji jądra 3.0 (Lipiec 2011 rok – szybsza wzmianka grudzień 2010 r.) program ping nie potrzebuje bitu SUID (ang. Set User ID), ani innych rozszerzonych zdolności typu CAP_NET_RAW, aby poprawnie działać. Wprowadzona do tej wersji jądra łatka dodała gniazdo typu IPPROTO_ICMP, które umożliwia wysyłanie wiadomości typu ICMP_ECHO i odbieranie odpowiadających im komunikatów ICMP_ECHOREPLY bez żadnych specjalnych uprawnień. Jest to podobny mechanizm do tego, który został zaimplementowany w MacOS X. Wcześniej, aby wysłać pakiet ICMP_ECHO (Echo Request), program musiał otworzyć tzw. surowe gniazdo (ang. raw socket). W systemach *nix surowe gniazda są niezwykle potężne i niebezpieczne, ponieważ pozwalają programowi samodzielnie konstruować dowolne nagłówki pakietów, co może być wykorzystane np. do podszywania się (spoofingu) pod inne adresy IP lub ataków DoS/DDoS. Dlatego dostęp do nich zazwyczaj ma tylko administrator systemu. Jednak poprawka c319b4d wprowadziła nowy typ gniazda, który jest „bezpieczniejszy”, ponieważ jądro systemu samo pilnuje struktury pakietu ICMP. Użytkownik może wysłać prośbę o komunikat diagnostyczny do sieci za pomocą programu ping, ale jądro nie pozwoli mu sfałszować adresu źródłowego ani zmodyfikować krytycznych części nagłówka, które mogłyby zaszkodzić badanej sieci.
Niestety wiele dystrybucji wciąż jeszcze ustawia bit SUID dla programu ping:
root@darkstar:~# ls -al /bin/ping -rwsr-xr-x 1 root root 74384 Mar 31 2024 /bin/ping
Powoduje to, że każdy użytkownik uruchamiający program ping na moment staje się administratorem, a jeśli w kodzie tego programu znajdzie się błąd (np. przepełnienie bufora) – atakujący może przejąć pełną kontrolę nad systemem. Spójrzmy teraz na wprowadzone ustawienia jądra net.ipv4.ping_group_range (dostępne przez sysctl), które definiuje zakres identyfikatorów grup (GID), mających prawo do tworzenia specjalnego typu gniazd:
socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)
Czyli:
root@darkstar:~# sysctl net.ipv4.ping_group_range net.ipv4.ping_group_range = 1 0
Domyślnie większość dystrybucyjnych jąder systemu wciąż ma ustawioną wartość „1 0„. Jest to sztuczka powodująca, że jeśli „startowa” wartość identyfikatora grupy (GID) jest większa niż „końcowa” wartość GID to zakres jest uważany za pusty. To skutecznie wyłącza tę funkcję dla wszystkich, dopóki administrator systemu jej nie skonfiguruje. Co w uproszczeniu oznacza, że żaden nieuprzywilejowany użytkownik nie będzie mógł używać nowego typu gniazd ICMP, a polecenie ping powróci do używania tradycyjnych (i bardziej uprzywilejowanych) surowych gniazd. Sprawdźmy jak to działa w praktyce:
root@darkstar:~# chmod u-s /bin/ping agresor@darkstar:~$ ping nfsec.pl ping: Lacking privilege for icmp socket. root@darkstar:~# id agresor uid=1000(agresor) gid=1000(agresor) groups=1000(agresor) root@darkstar:~# echo "1000 1000" > /proc/sys/net/ipv4/ping_group_range agresor@darkstar:~$ ping -c 1 nfsec.pl PING nfsec.pl (147.135.209.161): 56 data bytes 64 bytes from 147.135.209.161: icmp_seq=0 ttl=125 time=26.176 ms --- nfsec.pl ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max/stddev = 26.176/26.176/26.176/0.000 ms
Powyższy zabieg daje nam kilka korzyści. Po pierwsze eliminację bitu SUID, co zmniejsza powierzchnię ataku na system. Po drugie administrator systemu może precyzyjnie określić, które grupy użytkowników mogą używać narzędzi sieciowych (np. 0 2147483647 da je praktycznie każdemu użytkownikowi). I ostatnim argumentem jest także uproszczenie uprawnień w środowiskach kontenerowych (Docker / Kubernetes), które również nie będą wymagały CAP_NET_RAW do używania programu ping.
Więcej informacji: ICMP
Poprzedni wpis Brak nowszych postów

