STRESZCZENIE: Security Enhanced Linux jest produktem stworzonym na zamówienie amerykańskiej agencji bezpieczeństwa (NSA). Rozszerza on mechanizmy kontroli dostępu i uprawnień użytkowników w elastyczny i prosty sposób, zwiększając efektywne bezpieczeństwo systemów linuksowych. Podstawowym mechanizmem kontroli dostępu wykorzystywanym przez SELinuksa jest Role Based Access Controls (RBAC), który znacząco różni się od standardowych praw uniksowych, czy ACL-i. Instalacja tego systemu nie jest zbyt skomplikowana, a praktyczne użytkowanie nie zwiększa czasu potrzebnego na administrowanie systemem. Z cała pewnością jest to bardzo ciekawy projekt, który stoi u progu swojej popularności.
Jądro - SELinux używa obecnie (nie zawsze tak było) infrastruktury jądra Linuksa znanej pod nazwą LSM (ang. Linux Security Modules - moduły bezpieczeństwa Linuksa), która dostarcza interfejsów pozwalających kontrolować dostęp do obiektów systemu podczas wykonywania działań przez użytkowników (otwarcie pliku, utworzenie katalogu, bindowanie do portu itd.). SELinux podłącza się do tego interfejsu i wymusza w systemie własną politykę bezpieczeństwa. Z punktu widzenia administratora instalującego SELinuksa stanowi on po prostu łatę na jądro.
Zmodyfikowane kluczowe programy - SELinux w większości przypadków pozwala, aby programy działające w systemie nie musiały rozumieć, że system ten nie jest zwykłym Linuksem. Jednak pewne kluczowe dla bezpieczeństwa i w ogóle działania systemu programy muszą zostać rozszerzone o obsługę SELinuksa. Do tych programów należą między innymi: ssh, ls, ps, xdm, login. Administrator systemu musi podczas instalacji albo pobrać zmodyfikowane już wersje używanych programów, albo zaaplikować odpowiednie łaty na źródła używanych programów.
Zasady, czyli Policy - określają prawa dostępu, prawa wykonywania działań w systemie, zachowanie się systemu. Jest to w praktyce najważniejsza część systemu SELinux, gdyż to właśnie te Zasady decydują o skutecznym działaniu całego systemu. Poświęcę część miejsca na wyjaśnienie jak konstrowane są elementy Policy. Administrator systemu generalnie nie powinien być zmuszony do pisania własnych zasad w Policy (chyba, że istnieją pewne niestandardowe wymagania co do kształtu polityki bezpieczeństwa), ale powinien umieć je czasem zmodyfikować do swoich potrzeb, a na pewno powinien rozumieć zasady już istniejące.
Ponieważ SELinux bywa porównywany z systemami z ACL, czy też (całkowicie błędnie) do systemu z ACL (ang. Access Control Lists), to warto wiedzieć, że:
Ponieważ znane już są podstawowe pojęcia, spróbuję lepiej określić w jaki sposób działa SELinux. Przede wszystkim jeden użytkownik w systemie może posiadać wiele ról, przy czym jedna z nich jest rolą domyślną. Każda rola użytkownika posiada zestaw domen dostępu, a jedna z nich jest domyślną dla danej roli. W danej chwili użytkownik może wykonywać jedną rolę w jednej domenie. Mogą następować przełączenia między rolami i domenami. Dla wybranych skrzyżowań domeny i każdego typu definiowane są reguły zachowania się (prawa i inne). Efektywne uprawnienia procesu w systemie zależą więc od domeny w której w danej chwili działa. SELinux potrafi też współpracować ze standardowym mechanizmem 'capabilities', pozwalając ustalać zestaw 'capabilities' startującego programu zależnie od domeny procesu, który próbuje go uruchomić.
Trzeba jeszcze rozumieć jedną istotną rzecz, czyli to, w jaki sposób reguły SELinuksa współgrają ze standardowym modelem uprawnień UGO (ang. User, Group, Others - Użytkownik, Grupa, Inni) systemu uniksowego. Generalna zasada stanowi, iż SELinux ogranicza uprawnienia do wykonywania zadań w stosunku do systemu bez SELinuksa, natomiast nie nadaje dodatkowych uprawnień, których użytkownik nie miał w niezmodyfikowanym systemie. Jest to podejście praktycznie bardzo poprawne, gdyż w przypadku błędów w polityce bezpieczeństwa SELinuksa, w najgorszym wypadku, gdyby nawet Policy SELinuksa pozwalało wszystkim na wszystko, otrzymalibyśmy zwykły system uniksowy, którego zabezpieczenia wcale nie są takie złe (przecież używamy ich na codzień!).
Niestety, ze względu na specyfikę rozwiązań wewnątrz różnych pakietów oprogramowania serwerowego, elementy Policy SELinuksa muszą być definiowane specjalnie dla każdego oprogramowania lub rozszerzane w ramach klasy oprogramowania o wpisy potrzebne do poprawnego działania jej konkretnej implementacji.
Serwer Bind jest przykładową implementacją dla klasy oprogramowania Serwery DNS. Potrzebuje on praw roota co najmniej do startu, a częstokroć także do działania (jeśli musi bindować się do podnoszonych podczas jego działania dynamicznych interfejsów). W tym wypadku, niezależnie od tego, czy działa on z prawami roota, czy też zwykłego użytkownika, będziemy chcieli ograniczyć jego uprawnienia do następujących:
Listing 1. Definicje Type Enforcement w SELinux Policy
* deklaracje typów type sshd_t, domain, privuser, privrole, privlog, privowner; type sshd_exec_t, file_type, exec_type, sysadmfile; type sshd_tmp_t, file_type, sysadmfile, tmpfile; type sshd_var_run_t, file_type, sysadmfile, pidfile; * definicje wymuszonych przejść (makra) domain_auto_trans(initrc_t, sshd_exec_t, sshd_t) file_type_auto_trans(sshd_t, tmp_t, sshd_tmp_t) domain_auto_trans(sshd_t, shell_exec_t, user_t) * definicje dozwolonych przejść (bez makr i z makrem) type_change user_t tty_device_t:chr_file user_tty_device_t; type_change sysadm_t tty_device_t:chr_file sysadm_tty_device_t; type_change user_t sshd_devpts_t:chr_file user_devpts_t; type_change sysadm_t sshd_devpts_t:chr_file sysadm_devpts_t; domain_trans(sshd_t, shell_exec_t, sysadm_t) * definicje wektorów dostępu allow sshd_t sshd_exec_t:file { read execute entrypoint }; allow sshd_t sshd_tmp_t:file { create read write getattr setattr link unlink rename }; allow sshd_t user_t:process transition;Typy, które będą używane przez inne reguły w Policy, muszą zostać najpierw zdefiniowane. W pierwszej części listingu widać definicje typów: domeny sshd_t (główna domena używana przez programy z pakietu SSH) i typy plików używane przez programy działające w tej domenie. Dzięki tym dodatkowym typom można będzie rozdzielić np. uprawnienia do plików tymczasowych SSH (typ: sshd_tmp_t) od innych plików tymczasowych (zwykle mających typ tmp_t).
W drugiej części listingu widać definicje wymuszonych przejść. W tym wypadku definicja jest bardziej czytelna, dzięki zastosowaniu makr, np. file_type_auto_trans. Mechanizm makr w SELinux Policy w znakomity sposób ułatwia proces jej tworzenia i modyfikacji. W tym wypadku file_type_auto_trans mówi, że gdy proces w domenie sshd_t otworzy (np. jednocześnie go tworząc) plik, który normalnie miałby domenę tmp_t, to nastąpi automatyczna zmiana domeny pliku na sshd_tmp_t. Z kolei pierwsze makro domain_auto_trans mówi, iż jeżeli proces działający w domenie initrc_t (a w takiej domenie są uruchamiane wszystkie skrypty w /etc/init.d/) uruchomi program z pliku o typie sshd_exec_t, to nowouruchomiony program będzie działał w domenie sshd_t. Taka deklaracja (i specjalny typ *_exec_t) jest konieczna praktycznie dla każdego pakietu oprogramowania uruchamianego w /etc/init.d/.
W trzeciej części listingu umieszczone są zezwolenia na zmianę typu obiektu z jednego na inny dokonywaną przez działający w pewnej domenie program. Na przykład program działający w domenie user_t będzie miał prawo zmienić typ pliku urządzenia znakowego z tty_device_t na user_tty_device_t. Widać tutaj, że w szczególny sposób potraktowane są konsole, na których ma działać użytkownik w domenie sysadm_t - będzie on mógł zmienić typ pliku urządze- nia znakowego (konsoli, z której ma zamiar korzystać) na sysadm_tty_device_t. Ma to uniemożliwić ewentualne podsłuchiwanie lub modyfikowanie komunikacji dokonywanej z użyciem tego urządzenia.
W ostatniej części listingu zawarte są szczegółowe informacje o tym, co proces działający w danej domenie może zrobić z obiektem danego typu.
Listing 2. Definicje Role Based Access Control w SELinux Policy
* definicje ról role system_r types { kernel_t initrc_t getty_t klogd_t }; role user_r types { user_t user_netscape_t user_irc_t }; role sysadm_r types { sysadm_t run_init_t }; * definicje dozwolonych przejść allow system_r { user_r sysadm_r }; allow user_r sysadm_r; allow sysadm_r system_r; * definicje rozpoznawanych użytkowników user system_u roles system_r; user root roles { user_r sysadm_r }; user jdoe roles user_r;
Ponieważ, jak nazwa głosi, jest to system oparty na rolach, to nie może zabraknąć definicji ról. W tym wypadku definiujemy również to, z jakich domen kiedykolwiek dana rola może korzystać. Na przykład, dla roli user_r, dostępna jest podstawowa, domyślna domena user_t, a także pomocnicze domeny user_netscape_t i user_irc_t, które zostały omówione wcześniej.
W pewnych okolicznościach przydatna jest możliwość przełączania się między rolami na życzenie (służy do tego program newrole). Przykłady dozwolonych przejść miedzy rolami zawarte są w drugiej części listingu.
Generalnie rzecz biorąc system RBAC jest mocno niezależny od kont użytkowników uniksowych. Jednak w wielu przypadkach pożądane jest powiąza- nie konkretnych użytkowników z zestawami ról, które są dla nich dozwolone. Na załączonym przykładzie widać np., że użytkownik root domyślnie występuje w roli user_r, chociaż ma również dostęp do roli sysadm_r.
Listing 3. Definicje kontekstów bezpieczeństwa (SC) obiektów systemu
* definicje kontekstów sieciowych + porty portcon tcp 80 system_u:object_r:http_port_t portcon tcp 8080 system_u:object_r:http_port_t + interfejsy sieciowe netifcon eth0 system_u:object_r:netif_eth0_t system_u:object_r:netmsg_eth0_t netifcon eth1 system_u:object_r:netif_eth1_t system_u:object_r:netmsg_eth1_t * definicje domyślnych kontekstów plików /home system_u:object_r:home_root_t /home/[^/]+ -d system_u:object_r:user_home_dir_t /home/[^/]+/.+ system_u:object_r:user_home_t /home/[^/]+/.ssh(/.*)? system_u:object_r:user_home_ssh_t
SC plików (a przede wszystkim ich typy) nie są nadawane w sposób automatyczny w momencie uruchomienia systemu z jądrem SELinuksa. Muszą one być nadane w procesie etykietowania (ang. labelling), który musi zostać przeprowadzony wcześniej, zanim zaczniemy używać systemu z SELinuksem. Pytanie jakie należy sobie zadać, jest następujące: skąd wiadomo, jaki typ powinien mieć dany plik?
Gdybyśmy zainstalowali źródła SELinuksa, odpowiedź możnaby znaleźć w pliku o nazwie file_contexts, stanowiącym składową Policy. Zawiera on definicje, których przykład znajduje się w drugiej części listingu 3.
Informują one program przeprowadzający etykietowanie jakie powinien nadać typy (a dokładniej konteksty bezpieczeństwa) poszczególnym plikom w systemie. W podanym przykładzie widać, że katalog /home otrzyma typ home_root_t, katalogi użytkowników - user_home_dir_t, a znajdujące się w nich pliki i katalogi - typ user_home_t. W sposób szczególny potraktowane zostaną pliki używane przez SSH, a znajdujące się w katalogach domowych użytkowników. Otrzymają one własny typ user_home_ssh_t. Podobne definicje istnieją dla katalogów używanych przez np. klientów IRC, gdzie trzymane są ich logi i konfiguracja.
Mając już podstawową wiedzę na temat SELinuksa - najwyższy czas przystąpić do jej praktycznego wdrożenia! Aby móc używać SELinuksa trzeba zgromadzić potrzebne elementy:
Zamiast kłopotać się z łatami można ze strony NSA pobrać pełne źródła zmodyfikowanego jądra i zmodyfikowanych programów systemowych. Jeżeli korzystamy z dystrybucji Debiana (stabilnej, bądź niestabilnej), to są dostępne źródła APT zawierające wszystko, co jest potrzebne do instalacji i użytkowania SELinuksa.
W załatanym jądrze należy włączyć następujące opcje:
* Networking Options + [Y] Network Packet Filtering * Security Options + [Y] Enable different security models + [Y] Capabilities Support + [Y] NSA SELinux Support + [Y] NSA SELinux Development Support
Ponieważ i tak musimy kompilować jądro samodzielnie najlepiej nie korzystać z obrazu initrd. W przeciwnym wypadku, po każdej zmianie Policy, nową będzie trzeba umieścić również w obrazie initrd, a to jest zawsze kłopotliwe i czasochłonne.
Po instalacji jądra i instalacji programów użytkowych zmodyfikowanych do potrzeb SELinuksa potrzeba jeszcze wykonać operację etykietowania. Jednak przed jej przeprowadzeniem należy sprawdzić, czy ścieżki podane w pliki file_contexts są odpowiednie dla naszej dystrybucji. Jeżeli korzystamy ze źródeł pobranych ze strony NSA, to domyślnie wpisy są odpowiednie dla dystrybucji RedHat. Jeżeli korzystamy z Debiana i pobraliśmy pakiety z odpowiedniego źródła APT, to są one już odpowiednio poprawione. Użytkownicy pozostałych dystrybucji powinni koniecznie sprawdzić zawartość tego pliku. Potem można już wykonać operację etykietowania.
W dystrybucji SELinuksa znajduje się plik Makefile, który zawiera następujące cele: install - kompilacja i instalacja Policy, load - kompilacja, instalacja i załadowanie Policy, reload - kompilacja, instalacja i załadowanie lub przeładowanie Policy, relabel - reetykietowanie systemu plików (FCs), policy - lokalna kompilacja Policy do testów. Operacja etykietowania może trwać dość długo, ponieważ wymaga operacji na każdym z plików w lokalnych systemach plików. Można zauważyć, że w katalogu głównym każdej partycji powstał katalog o nazwie ...security zawierający kilka plików binarnych z dodatkowymi informacjami o każdym z plików na partycji. Po zakończeniu całej operacji, mając zainstalowane jądro z SELinuksem i programy do niego dostosowane, można przystąpić do testów praktycznych.
Nawet jeśli wszystko zostało wykonane z należyta starannością podczas pierwszego startu z pewnością pojawi się wiele komunikatów o błędach zgłaszanych przez rozszerzenie SELinuksa. Mimo to system powinien w całości wystartować (dlaczego - to za chwilę). Przykładowy (jeden!) komunikat o błędzie: avc: denied { write } for pid=1112 exe=/bin/login path=/dev/log dev=03:01 ino=15 scontext=system_u:system_r:local_login_t tcontext=system_u:object_r:device_t tclass=sock_file
Oznacza on, że proces /bin/loginposiadający SC system_u:system_r:local_login_t
próbował zapisywać do gniazda /dev/log o typie device_t. Komunikat ten wy-
stąpił w rzeczywistej sytuacji i wynikał z niedostosowania Policy do używanego
przeze mnie demona syslog-ng. Po dodaniu do Policy dwóch linijek (podanych
mi przez Russella Cokera, dewelopera Debiana i SELinuksa) problem ustąpił.
Dzięki zaznaczeniu podczas konfiguracji jądra opcji NSA SELinux Develop-
ment Support SELinux startuje w trybie permissive, w którym wszystkie błędy
wynikające z zabronionego dostępu są zgłaszane, ale sam dostęp do obiektów
nie jest zabraniany. System działa wtedy tak, jak normalny Linux, ale zgłasza
błędy. Istnieje kilka metod na przełączenie do trybu enforcing, kiedy to SELinux
rzeczywiście realizuje zasady zawarte w Policy:
wyłączenie NSA SELinux Development Support,
przełączenie poleceniem avc_toggle (jeśli zezwala na to Policy - można np.
nie pozwolić na powrót do trybu permissive),
podanie jądru parametru permissive=1.
System można startować w trybie enforcing dopiero po upewnieniu się, że
zasady Policy są odpowiednio dostosowane i że system będzie w stanie działać
tym trybie. Nie należy próbować elemininować wszystkich zgłaszanych błędów,
gdyż nie wszystkie one są krytyczne i czasami wynikają z w pełni zamierzonej
polityki bezpieczeństwa.
Należy w szczególności zwrócić uwagę na procesy działające (lub próbujące działać) w domenie initrc_t (ps -e --context pokazuje konteksty procesów). Oznacza to, że najprawdopodobniej dla pakietu oprogramowania do którego należy dany program brakuje odpowiednich wpisów w Policy i podczas startu ze skryptów /etc/init.d/ SC nie jest zmieniany na właściwy dla danego pakietu oprogramowania. Należy skontrolować file_contexts i sprawdzić, czy przypadkiem ścieżki nie są nieprawidłowe. Jeżeli dany pakiet oprogramowania w ogóle nie jest objęty wpisami w Policy, najlepiej zwrócić się o pomoc w ich napisaniu do deweloperów SELinuksa. Pewną pomocą może też być skrypt scripts/newrules.pl, który stara się generować nowe zasady allow na podstawie zgłaszanych błędów.
Po starcie systemu będzie można się zalogować. Jeżeli spróbujemy zalogować się jako root z lokalnej konsoli, to będziemy mięli bezpośredni dostęp do roli sysadm_r (która w odróżnieniu od domyślnej user_r daje rzeczywiste możliwości administrowania systemem). Fragment ekranu logowania użytkownka root wygląda tak:
Your default context is root:user_r:user_t Do you want to choose a different one? [n]y [1] root:user_r:user_t [2] root:sysadm_r:sysadm_t Enter number of choice: 2
Rolę można też zmienić później (w ramach dozwolonych przez Policy) za pomocą polecenia newrole -r sysadm_r. Dostęp do roli sysadm_r jest zwykle również zabezpieczony drugim hasłem, innym niż hasło roota.
Jeżeli korzystamy z któregoś z graficznych menedżerów logowania, jak xdm, gdm czy kdm, to musi on być załatany aby działał pod SELinuksem. Jeżeli nie chcemy go łatać, to zawsze można użyć startx, startując konsolę graficzną z konsoli tekstowej (login już wykonał pracę zmiany domeny, którą inaczej musiałby wykonać xdm).
Dobrze jest wiedzieć, czy działamy w trybie enforcing, czy permissive.
Można to sprawdzić poleceniem avc_enforcing.
Demony, które w trybie permissive startują w domenie initrc_t prawie
na pewno nie będą poprawnie działać w trybie enforcing. Trzeba poprawić
Policy, aby działały we własnych domenach.
Przydatne polecenia, to ps -e --context i ls --context. Pierwsze z nich
pozwala sprawdzić z jakimi SC działają procesy, a drugie z nich jakie typy
mają pliki. Do celów testowych można zmieniać SC plików za pomocą polecenia chcon. Należy pamiętać, że jeśli nie zostaną dodane odpowiednie wpisy
do file_contexts zmiana ta zostanie zniwelowana przy kolejnym etykietowaniu.
Jeżeli przełączamy się między jądrem skompilowanym z SELinuksem, a jądrem bez niego, to przed ponownym włączeniem jądra z SELinuksem należy ponownie przeprowadzić etykietowanie, ponieważ w międzyczasie mogły powstać pliki nie posiadające nadanego SC. Chociaż nic nie stoi na przeszkodzie, aby cały czas używać jądra z wkompilowanym SELinuksem, ale w trybie permissive.
Policy jest komponowane z wielu elementów, z których każdy odpowiada za obsługę zazwyczaj jednego pakietu oprogramowania, np. serwera DNS. Jednak w większości przypadków w naszym systemie nie ma zainstalowanych wszystkich pakietów oprogramowania, dla których są dostępne elementy Policy. Dlatego np. podczas instalacji pakietów dla Debiana zostaniemy zapytani, których elementów Policy chcemy rzeczywiście używać. Używając wszystkich dostępnych będziemy mieli około 200 tysięcy zasad. Być może warto tę liczbę zmniejszyć do kilkudziesięciu tysięcy rzeczywiście potrzebnych.
W sprawie patentów sytuacja wygląda znacznie bardziej pozytywnie. W tej chwili NSA finansuje rozwój SELinuksa, ale patenty na niego posiada komercyjna firma. Może się rodzić podejrzenie, czy firma ta nie zechce w pewnej chwili pieniędzy za użytkowanie oprogramowania korzystającego z opatetnowanych przez nią rozwiązań. Na całe szczęście wydaje się to w tej chwili mało prawdopodobne. NSA wcale nie ma zamiaru np. wykupować tych patentów (co stworzyło by niemiły precedens), ani też Secure Computing Corp. nie bardzo chce walczyć z potężną agencją rządową (bo to ona byłaby pierwszym celem). W przypadku SELinuksa NSA zdaje się całkowicie popierać idee Open Source i Free Software, możemy więc spać spokojnie.
Ciekawy pokaz możliwości SELinuksa przeprowadził Russell Coker, deweloper Debiana, a także jeden z nielicznych nieopłacanych przez nikogo deweloperów SELinuksa. Udostępnił on w Internecie maszynę z publicznie znanym hasłem roota. Okazało się, że będąc rootem można było np. wykonywać chroot, ale praktycznie niczego w systemie nie dało się popsuć. Zastosowane wpisy w Policy nie były wcale bardziej restrykcyjne od standardowych, zostały wręcz w pewnych miejscach złagodzone, np. tak, by każdy mógł odczytać logi systemowe i wiedzieć, dlaczego nie mógł wykonać danego działania. Myślę, że dobrze świadczy to o sile pomysłu SELinuksa.
W chwili obecnej SELinux wychodzi z ukrycia. Rysują się następujące możliwości rozwoju i upowszechnienia tej technologii:
Nie należy jednak ulegać złudzeniu, że technologia ta dopiero będzie zasługiwała na zainteresowanie. Fakty są takie, iż już w chwili obecnej SELinux jest w pełni sprawnym, działającym, przetestowanym, elastycznym i potężnym narzędziem podwyższania bezpieczeństwa systemów linuksowych. Posiada sprawne zaplecze aktywnych deweloperów, wkrótce będzie zintegrowany ze standardowym jądrem i popularnymi dystrybucjami. Z pewnością dużym błędem byłoby zwlekać z poznaniem tak fascynującej i użytecznej technologii!
źrodło: artykuł Grzegorza B. Prokopskiego.