SELinux - tworzenie własnej polityki

Fri 18 June 2010 by admin

SELinux umożliwia lepszą kontrolę nad aplikacjami, bez ingerencji w kod danej aplikacji – tak najogólniej brzmi jedno z głównych założeń zaimplementowanego w Linux’ie mechanizmu zabezpieczeń. Sposób realizacji owej lepszej kontroli nad aplikacjami opiera się o implementację MAC (Mandatory Access Control). Otóż każdemu obiektowi w systemie (plik, proces, port etc.) jest przypisany do konkretny typ (label) mając tak zdefiniowaną listę możemy napisać polityki, które np. konkretnemu procesowi (dla przeglądarki www firefox_t) dadzą dostęp do zapisu tylko do określonych plików (np. domowe pliki użytkowników user_home_t) bez względu na uprawnienia dostępu DAC (rwx). Postaram się przedstawić sposób tworzenia polityki dla prostego skryptu oraz opisać korzyści płynące z tego tytułu…

SELinux najlepiej się ma w dystrybucjach ,,redhatopodobnych” Fedora, RedHat, CentOS. Na bazie tych dystrybucji i oferowanych przez nie narzędzi zbuduję politykę, która ograniczy ,,szkodliwe” działanie pewnego skryptu. Za nim jednak przejdę do tworzenia polityki opiszę krótki scenariusz jak może dość do nadużycia z owym tajemniczym skryptem w tle.

Załóżmy sytuację, w której nasz skrypt generuje poufny raport, który dostępny ma być tylko dla wybranych osób. Raport zapisywany jest tylko w wybranych katalogach domowych użytkowników. Co więcej autor skryptu poszedł po najmniejszej linii oporu określając root’a jako użytkownika z poziomu, którego można tylko uruchamiać skrypt. Załóżmy, że wychodzi nowa wersja skryptu do pobrania z internetu, w tej chwili do gry wchodzi napastnik, który kieruje administratora na spreparowaną stronę zawierającą dziurawą wersję skryptu. W efekcie napastnik, który jest autorem dziurawej wersji skryptu uzyskuje dostęp do poufnego raportu, który zapisuje się też w jego domowym katalogu oraz  zdobywa hasła np. z pliku /etc/shadow. W tradycyjnym podejściu bez uciekania się do SELinux’a taka sztuka się powiedzie, co jednak się stanie, gdy opiszemy działanie skryptu przy pomocy konkretnej polityki…

Przystępując do napisania polityki możemy skorzystać z narzędzia sepolgen:

# sepolgen -t 3 getresults

getresults to nazwa skryptu/programu.

Wynikiem polecenia sepolgen bedą cztery pliki, główny plik zawierający polityki i który to będziemy edytować to getresults.te.

Skrypt getresult będzie działał w domenie (typ) getresults_t a plik wykonywalny będzie oznaczony label’em getresults_exec_t:

type getresults_t;

type getresults_exec_t;

application_domain(getresults_t, getresults_exec_t);

standardowo użytkownik root jak i zresztą każdy inny użytkownik działa w domenie unconfined_t, zatem po uruchomieniu powinien taki proces powinien przejść do domeny skryptu getresults_t:

role unconfined_r types getresults_t;

type_transition unconfined_t getresults_exec_t:process getresults_t;

allow unconfined_t getresults_t:process transition;

skrypt getresults wyniki powinien zapisywać w katalogu ( i plikach) oznaczonych label'em getresults_t:

allow getresults_t getresults_t:file { write getattr open create };
allow getresults_t getresults_t:dir { write add_name };

użytkownik root niestety nie jest w stanie zmienić katalogu na nowy label getresults_t w tym celu należy:

allow getresults_t getresults_t:file { write getattr open create };
allow getresults_t getresults_t:dir { write add_name };

wspomniane w pliku inne domeny (np. unconfined_t) muszą być uwzględnione w:

require {
type unconfined_t;
type proc_t;
type user_devpts_t;
type fs_t;
}

tak przygotowane politykę możemy przekompilować i dodać do zestawu:

# make -f /usr/share/selinux/devel/Makefile && semodule -i getresults.pp

następnie przełączamy SELinux’a w tryb Permissive (tj. raportuje i nie blokuje):

# setenforce 0

analizujemy plik audytu /var/log/audit/audit.log po uruchomieniu skryptu getresults, jeżeli zauważymy jakieś informacje o blokadach wówczas:

# audit2allow -i /var/log/audit/audit.log

wygeneruje nam potrzebne wpisy do poprawnego zadziałania, dopisujemy je do pliku getresults.te oraz podnosimy wersję:

policy_module(getresults,1.0.1)

oraz przekompilowujemy i upgrade’ujemy politykę:

# make -f /usr/share/selinux/devel/Makefile && semodule -u getresults.pp

ponownie uruchamiamy skrypt i analizujemy audit.log. Jeżeli nie ma już żadnych zastrzeżeń przełączamy się na tryb Enforcing:

# setenforce 1

Zobaczymy czy teraz skrypt getresults zapisze nam zawartość raportu i pliku shadow do nowej nieoznaczonej lokalizacji:

# ./getresults
./getresults: line 4: /tmp/results: Permission denied

./getresults: line 5: /tmp/results: Permission denied

okazuje się, że sztuka ta nawet z poziomu konta root’a się nie udaje. Skrypt zapisuje tylko dane do katalogu oznaczonego label’em getresults_t:

ls -lZR
.:
drwxr-xr-x. root root unconfined_u:object_r:getresults_t:s0 results
./results:
-rw-r–r–. root root unconfined_u:object_r:getresults_t:s0 results

Tym sposobem możemy się ustrzec przed błędami w programach, koszt jaki musimy ponieść to z pewnością czas na dostosowanie polityki do potrzeb konkretnej aplikacji. Na całe szczęście najpopularniejsze usługi dostępne w systemie Linux w szczególności w dystrybucjach redhatopodobnych mają już gotowy zestaw polityk. Nie mniej jednak zachęcam do zapoznania się z nimi tak, gdyż mogą nam posłużyć jako wzorce do napisania własnych polityk, które uchwycić mogą nietypowe programy w bezpiecznych domenach bez uciekania się do wyłączanie SELinux’ach lub przełączania go w tryb Permissive.

Zbiór informacji o SELinux:  http://selinuxproject.org/

Plik: getresults.te

Skrypt: getresults


Comments