1. Wprowadzenie
2. Historia SELinuksa
3. Elementy składowe SELinuksa
4. MAC, RBAC i DTAC w SELinuksie
4.1 MAC - Mandatory Access Control
4.2 RBAC - Role Based Access Control
4.3 DTAC - Dynamically Typed Access Control
5. Działanie SELinuksa
6. Kontekst bezpieczeństwa procesu i obiektu
7. Rodzaje reguł w Policy
8. Definicje w SELinux Policy
8.1 Definicje Type Enforcement
8.2 Definicje RBAC
9. Najważniejsze cechy SELinuksa - podsumowanie
9.1 Zalety SELinuksa
9.2 Wady SELinuksa
10. Bibliografia
SELinux, czyli Security Enhanced Linux (Linux o wzmocnionym bezpieczeństwie) jest rozwiązaniem podnoszącym poziom bezpieczeństwa systemu Linux. W odróżnieniu jednak od dużej części innych rozwiązań nie koncentruje się on ani na usunięciu wybranych błędów w polityce bezpieczeństwa systemu, ani na rozwiązywaniu problemów wynikających z przyjętej konstrukcji systemu, ale proponuje całościowe rozwiązanie. SELinux to system z obowiązkową kontrolą dostępu (MAC - Mandatory Access Control), który realizuje politykę kontroli dostępu opartą na rolach (RBAC - Role Based Access Control) za pomocą domenowego systemu kontroli dostępu (DTAC - Dynamically Typed Access Control). Szczegółowe omówienie tego, co to znaczy znajdzie się w dalszej części prezentacji.
Ideą SELinuksa jest odebranie procesom tych uprawnień, które nie są im potrzebne. Dzięki temu zniszczenia, jakie mogą zostać poczynione w razie włamania do systemu, będą znikome (ograniczone do uprawnień jakie posiada proces, w którym błędy wykorzystano do włamania).
Historia rozwiązań, o które opiera swoje działanie SELinux, zaczyna się wraz z zapoczątkowanym w 1992 roku projektem DTMach (Distributed Trusted Mach) - wersją jądra Mach z rozbudowanymi mechanizmami kontroli dostępu. Projekt ten był kontynuowany pod nazwą DTOS (Distributed Trusted Operating System), a gdy był bliski osiągnięcia postawionych mu celów, we współpracy z uniwersytetem w Utah, powstał projekt Flux, który rozwijał architekturę zabezpieczeń dla systemu operacyjnego Fluke. Architektura ta, która czerpała z rozwiązań DTOS otrzymała nazwę Flask. Opiera się ona o przyznanie każdemu obiektowi w systemie zestawu atrybutów bezpieczeństwa (security attributes), które składają się na kontekst bezpieczeństwa (security context). SELinux jest efektem zintegrowania architektury Flask z jądrem Linuksa. Aktualnie prace nad SELinuksem są prowadzone przez firmę Secure Computing Corporation (jest ona także właścicielem patentów wykorzystanych w SELinuksie), której działania finansuje NSA (National Security Agency).
Można wyróżnić trzy najważniejsze części składowe SELinuksa:
MAC jest to system obowiązkowej kontroli dostępu. W przeciwieństwie do DAC (Discretionary Access Control) - najczęściej stosowanego w Linuksie modelu kontroli dostępu nie pozwala on użytkownikowi decydować o prawach dostępu do obiektów i zabezpieczeniach. Zamiast tego są one definiowane odgórnie przez administratora. W przypadku SELinuksa są one zapisane w postaci reguł Policy.
RBAC jest to system kontroli dostępu oparty na rolach. Rola jest pewnym zestawem praw do wykonywania określonych działań. W systemie dostępu opartym na rolach może wystąpić potrzeba zmiany roli, w ramach której wykonywane jest dane działanie. Większość systemów uniksowych zalicza się do systemów z RBAC: inną rolę w systemie ma tam zwykły użytkownik, inną użytkownik systemowy, a ponadto istnieje za pomocą SUID (SetUserID) możliwość zmiany roli przy wymagającym tego działaniu.
SELinux daje każdemu użytkownikowi zestaw ról, z czego jedna z nich jest rolą domyślną. Jedna rola może być wspólna dla wielu użytkowników, tj. wielu użytkowników może realizować tę samą rolę. SELinux pozwala na dokładniejsze dostosowanie ról do konkretnych potrzeb. Zasady RBAC są w nim realizowane za pomocą domenowego systemu kontroli dostępu (DTAC). Każda rola posiada zestaw domen dostępu.
DTAC jest to domenowy system kontroli dostępu. W DTAC każdemu obiektowi w systemie jest nadawany typ. Każdemu procesowi natomiast domena. Wszystkie obiekty o tym samym typie są traktowane jednakowo, tzn. zdefiniowany jest do nich (dla procesów każdej domeny osobno) jednakowy zestaw uprawnień. Podobnie wszystkie procesy w danej domenie mają takie same uprawnienia. Typy obiektów są nadawane odgórnie, użytkownik nie ma na nie bezpośredniego wpływu, aczkolwiek Policy może zezwalać na określoną zmianę typu w pewnych sytuacjach (por. Definicje Type Enforcement - przykład 3).
W systemie z SELinuksem każdy użytkownik ma przypisany zestaw ról, które może pełnić. Jedna z nich jest rolą domyślną. Każda rola dysponuje zestawem domen, zaś jedna z tych domen jest domyślna dla danej roli. Role mogą być wspólne dla wielu użytkowników a domeny mogą być wspólne dla wielu ról. W danym momencie użytkownik wykonuje dokładnie jedną rolę w jednej domenie. To wszystko obrazuje poniższy rysunek.
Dla każdej pary (domena, typ obiektu) zdefiniowane są reguły zachowania systemu oraz uprawnienia, jakie użytkownik w danej domenie ma do obiektu danego typu.
Standardowym modelem uprawnień w Linuksie jest UGO (User, Group, Others). SELinux nie rozszerza tego modelu - tzn. nie nadaje uprawnień, których nie miał użytkownik w systemie bez SELinuksa. Dzięki czemu, jeśli nawet zasady Policy nie ograniczałyby w żaden sposób uprawnień użytkownika (pozwalałyby na wszystko), wówczas poziom bezpieczeństwa systemu operacyjnego byłby taki jak zwykłego Linuksa (czyli nie taki zły!).
Na kontekst bezpieczeństwa procesu składają się: użytkownik który wykonuje proces (a właściwie nazwa użytkownika), rola w jakiej występuje użytkownik oraz jedna z domen tej roli:
Przykładowo po zalogowaniu się do systemu użytkownika pawel, jego proces powłoki (shell) działał będzie w domyślnej roli (user_r) w domyślnej domenie (user_t). Zatem kontekstem bezpieczeństwa tego procesu będzie:
Do sprawdzenia kontekstu służy polecenie id, wówczas pojawi się m.in. context=uzytkownik:rola:domena. Można też wywołać id -Z, co przyniesie taki skutek, jak na przykładzie poniżej.
pawel@localhost ~ $ id -Z pawel:user_r:user_t pawel@localhost ~ $ su Password: localhost pawel # id -Z pawel:user_r:user_t
Przykład ten pokazuje, że pomimo wykonania polecenia su i wprowadzenia poprawnego hasła roota nie zmieniły się ani rola użytkownika, ani domena w tej roli. Tym samym nie zmienił się zakres kompetencji użytkownika i polecenie su nie odniosło zamierzonego skutku. Żeby to zmienić należy użyć polecenia newrole, o ile oczywiście reguły Policy pozwolą na taką zmianę roli, jakiej będziemy chcieli (w tym wypadku jest to zmiana z user_r na sysadm_r).
localhost pawel # newrole -r sysadm_r Password: localhost pawel # id -Z pawel:sysadm_r:sysadm_t
Po wykonaniu polecenia newrole zmienił się kontekst procesu - nową rolą jest sysadm_r, która daje możliwości administrowania systemem, a nową domeną sysadm_t (będąca domyślną domeną sysadm_r).
Jak widać w kontekście bezpieczeństwa procesu istotne znaczenie mają rola i domena. Również obiekty mają swój (pełen) kontekst bezpieczeństwa. W nim kluczowe znaczenie ma typ. Przykładowo dla pliku wykonywalnego klienta IRC (np. Irssi) kontekstem bezpieczeństwa może być:
gdzie ostatnia część tego wyrażenia (irc_exec_t) jest typem pliku. Inne obiekty w systemie także mają swój kontekst bezpieczeństwa np.
może być kontekstem bezpieczeństwa portu TCP.
Zanim zaczniemy używać systemu z SELinuksem każdy obiekt musi mieć nadany swój kontekst bezpieczeństwa. Ma to miejsce w tzw. procesie etykietowania (labelling), który korzysta z definicji zawartych w pliku file_contexts. Poniżej przykładowe definicje z tego pliku.
/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
Pierwsza z nich oznacza, że katalog /home otrzyma typ home_root_t. Druga, że katalogi w katalogu /home otrzymają typ user_home_dir_t. Ostatnia natomiast, że wszystkie pliki i katalogi w podkatalogach katalogu /home otrzymają typ user_home_t.
Oczywiście po wykonaniu etykietowania, w trakcie działania systemu, będą mogły powstawać nowe obiekty (np. pliki). W momencie utworzenia otrzymają one typ zgodny z regułami Policy. Typ każdego obiektu nie jest nadany raz na zawsze - może ulec zmianie w wypadkach określonych regułami Policy.
Warto dodać, że wszystkie obiekty o tym samym typie są traktowane jednakowo z punktu widzenia tego, kto i jakie działania może na nich wykonywać oraz jak będzie zachowywał się system w momencie wykonywania tych działań (np. może zostać wymuszona zmiana domeny procesu, który uruchomi plik wykonywalny). Innymi słowy są traktowane tak samo z punktu widzenia Policy.
Przykład 1. Deklaracje typów (plik attrib.te)
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;
Powyżej znajdują się definicje typów, które będą używane w regułach Policy.
Przykład 2. Reguły wymuszonych przejść
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)
Powyżej znajdują się makra definiujące wymuszone przejścia. Pierwsze z powyższych makr (domain_auto_trans) jest regułą oznaczającą, że jeśli proces w domenie initrc_t uruchomi program z pliku o typie sshd_exec_t, to proces wykonujący ten program będzie działał w domenie sshd_t. Drugie z makr (file_type_auto_trans) jest natomiast regułą oznaczającą, że jeśli proces w domenie sshd_t otworzy (lub utworzy) plik o typie tmp_t, wówczas zmieni się typ tego pliku na sshd_tmp_t.
Przykład 3a. Reguły dozwolonych przejść (plik users.te)
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;
Powyżej znajdują się reguły pozwalające procesowi działającemu w określonej domenie na zmianę pliku o ustalonym typie na inny ustalony typ. Na przykład pierwsza z reguł pozwala procesowi działającemu w domenie user_t (czyli w domyślnej domenie dla roli user_r, która jest domyślną rolą dla użytkownika) na zmianę typu pliku urządzenia znakowego tty_device_t na typ user_tty_device_t.
Przykład 3b. Reguły dozwolonych przejść
domain_trans(sshd_t, shell_ecec_t, sysadm_t)
Powyżej przykład makra definiującego dozwolone przejście. Parametry mają podobne znaczenie, jak w przypadku makra domain_auto_trans.
Przykład 4 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 };
Powyżej znajdują się reguły definiujące, co proces w określonej domenie może zrobić z obiektem danego typu. Wszelkie działania, które nie zostaną w ten sposób zdefiniowane nie będą dozwolone.
Przykład 1. Definicje ról
role user_r types { user_t user_irc_t }; role sysadm_r types { sysadm_t run_init_t user_irc_t };
Powyżej znajdują się definicje ról. Dla każdej roli zostały ustalone jej domeny. Pierwsza z nich jest domeną domyślną. Domena user_irc_t jest wspólna dla ról user_r i sysadm_r.
Przykład 2. Reguły dozwolonych przejść
allow user_r sysadm_r;
Powyżej znajduje się reguła pozwalająca na zmianę domeny z user_r na sysadm_r np. za pomocą polecenia newrole.
Przykład 3. Reguły przyznające role użytkownikom
user root roles { user_r sysadm_r }; user pawel roles user_r;
Powyżej znajdują się reguły definiujące role przypisane użytkownikom. Dla obu z nich domyślną rolą jest user_r.