SELinux - zabawka dla dorosłych administratorów
Jakiś czas temu spotkałem się z pewnym doświadczonym administratorem systemów linuxowych. Po krótkiej wymianie najciekawszych wdrożeń i ocenie nowości technologicznych, nasza rozmowa skierowała się na ostatnio przez niego napotkany problem z SELinux. Od słowa do słowa okazało się, że nawet doświadczony administrator, który z różnych przyczyn nie uważał tej technologii za potrzebną, popełnił kardynalny błąd - wyłączył SELinux. Dlaczego? "Bo blokował mi porty mimo, że byłem root'em".
SELinux przez znaczną grupę administratorów uważany jest za zło, którego trzeba się pozbyć w jednym z pierwszych kroków po zainstalowaniu nowego systemu. Co robią tacy administratorzy? Ustawiają SELinux w tryb "disabled". Rozumiem, że nie wszystkim podniesione bezpieczeństwo systemu pasuje, niektórzy chcą po prostu móc swobodnie korzystać z Linuxa, ale to raczej dotyczy systemów domowych/biurkowych/developerskich/lamerskich.
Umówmy się, że świadomy admin nie cofa się o jeden krok w technologii zabezpieczeń systemów Linux tylko dlatego, że będzie miał więcej pracy administracyjnej przy strojeniu systemu. SELinux jest naprawdę fajny. Trzeba tylko się do niego przyzwyczaić, może nawet dać mu się oswoić z naszym systemem. Służy do tego tryb "permissive", który działa bardzo podobnie do trybu "disabled" z tą różnicą, że SELinux loguje wszystko (a nawet więcej) czego by zabronił pracując w trybie "enforcing".
Wracając do mojego znajomego admina. Jego problem był taki, że nie był w stanie zmusić Apache do nasłuchiwania na porcie 81. Przy próbie uruchomienia usługi httpd w logach widniał zapis:
Dla administratora, który nie miał styczności z SELinux, zapis powyższy może okazać się nieco enigmatyczny. Z pomocą przychodzi nam polecenie audit2why, które w bardziej czytelny sposób wyjaśnia powód blokady:
type=AVC msg=audit(1263975645.022:18): avc: denied { name_bind } for pid=3217 comm="httpd" src=81 scontext=root:system_r:httpd_t:s0 tcontext=system_u:object_r:reserved_port_t:s0 tclass=tcp_socket
Was caused by:
Missing or disabled TE allow rule.
Allow rules may exist but be disabled by boolean settings; check boolean settings.
You can see the necessary allow rules by running audit2allow with this audit message as input.
Najciekawiej brzmi ostatnia linijka, w której istnieje odwołanie do polecenia audit2allow. Po jego użyciu otrzymujemy formułkę, która ma rzekomo rozwiązać problem:
#============= httpd_t ==============
allow httpd_t reserved_port_t:tcp_socket name_bind;
Rozsądny administrator po przeczytaniu wyniku tego polecenia zorientuje się, że nie tędy droga. Propozycja jaką otrzymaliśmy od audit2allow, to zmiana uprawnień dla modułu. W szczególności zezwolenie dla typu httpd_t na otwieranie portów zarezerwowanych (domyślnie porty o numerach poniżej 1024). Skoro Apache startował poprawnie na porcie 80 to dlaczego nie chce na porcie 81. Oba porty mają typ reserved_port_t, co oznacza że audit2allow nie podpowiada nam prawidłowego rozwiązania. Mówiąc bardziej szczegółowo audit2allow podpowiada nam zbyt szerokie rozwiązanie problemu, ponieważ umożliwi ono wprawdzie na nasłuchiwanie na porcie 81 dla Apache, ale także na każdym innym z zakresu portów uprzywilejowanych. Będzie to według mnie zbyt ugodowe potraktowanie dość kluczowego procesu serwera.
Właściwe rozwiązanie jest bardzo proste o ile dokładnie wiemy jaki efekt chcemy osiągnąć. W naszym przypadku zmieniliśmy, a właściwie dodaliśmy, dodatkowy port, który powinien być w jakiś sposób związany z procesem Apache. Pomocne będzie teraz narzędzie konfiguracji polis SELinux zwane semanage. Za pomocą tego programu możemy modyfikować i przeglądać pewne parametry całej polityki (ang. policy) SELinux'a. Poszukajmy więc czy nie ma odwołania do portu 80, który domyślnie pracuje z naszym Apachem.
amanda_port_t tcp 10080, 10081, 10082, 10083
amanda_port_t udp 10080, 10081
hplip_port_t tcp 1782, 2207, 2208, 8290, 50000, 50002, 8292, 9100, 9101, 9102, 9220, 9221, 9222, 9280, 9281, 9282, 9290, 9291, 9292
http_cache_port_t tcp 3128, 8080, 8118, 11211, 10001-10010
http_port_t tcp 80, 443, 488, 8008, 8009, 8443
ocsp_port_t tcp 9080
pki_ca_port_t tcp 9180, 9701, 9443, 9444, 9445
pki_kra_port_t tcp 10180, 10701, 10443, 10444, 10445
pki_ocsp_port_t tcp 11180, 11701, 11443, 11444, 11445
pki_tks_port_t tcp 13180, 13701, 13443, 13444, 13445
soundd_port_t tcp 8000, 9433, 16001
transproxy_port_t tcp 8081
xen_port_t tcp 8002
zope_port_t tcp 8021
Widzimy, że w polityce został zdefiniowany dedykowany typ dla portów Apache o nazwie http_port_t. Jedyne co pozostało nam do zrobienia, to dodatnie do tego typu naszego nowego portu 81. Wykonujemy polecenie:
Od tej chwili nasz system zezwala procesowi Apache na nasłuchiwanie na porcie 81. Jeśli kiedyś przyjdzie nam to zmienić i port 81 nie będzie już potrzebny dla Apache, to możemy go usunąć wykonując polecenie:
Tym sposobem bardzo elastycznie bez użycia regułek iptables administrator może wyizolować dla każdego z procesów sieciowych odpowiedni zakres portów. W przypadku kompromitacji systemu, nie będzie ryzyka, że zostanie otwarty jakiś nowy port nasłuchiwania, mimo przejęcia praw root'a przez proces skompromitowany.
To tylko kropelka możliwości SELinux, a radość mojego kolegi, który odkrył jego potencjał, jest nie do opisania.
