SELinux - zabezpieczenie serwera WWW

Tue 09 November 2010 by admin

Najpopularniejszą metodą przetestowania działania SELinux jest uruchomienie serwera WWW oraz przeniesienie pliku np. z lokalizacji /tmp do lokalizacji ,,htdocs'' i próba jego otwarcia z poziomu przeglądarki. Okazuje się, że sztuka ta kończy się niepowodzeniem, pomimo nadania odpowiednich uprawnień. Dzieje się tak, gdyż przeniesiony plik posiada inny kontekst zabezpieczeń, do którego dostępu nie ma serwer WWW. Wystarczy nadać odpowiedni kontekst nowo przeniesionemu plików i problem znika, dzisiaj zatem postaram się rozszyfrować co oznacza odpowiedni kontekst zabezpieczeń dla serwera WWW.

Samo nadawanie uprawień jest dość żmudną czynnością, system posiada jednak bazę wiedzy na temat odpowiednich uprawnień do plików w wybranych katalogach i tak:

# semanage fcontext -l

prezentuje listę katalogów wraz z domyślnymi kontekstami dla znajdujących w nich obiektach. Zatem dla świeżo przeniesionego pliku możemy odtworzyć poprawny kontekst poleceniem:

# restorecon -v <nazwa_pliku>

po tej operacji plik posiada:

# ls -lZ

-rw-r--r--. root    root    system_u:object_r:httpd_sys_content_t:s0 test

Oznacza to, że serwer WWW działający w kontekście httpd_t:

# sesearch --allow -s httpd_t -t httpd_sys_content_t
...
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
...

może  taki plik  np. otworzyć, odczytać jego zawartość, nie ma jedna wzmianki o tym czy może do niego zapisywać. Dla pewności przekonajmy się czy jest to możliwe, w tym celu wystarczy napisać prosty skrypt np. w języku PHP, który zmodyfikuje zawartość wybranego pliku. Po uruchomieniu takiego skryptu powinno się pojawić zdziwienie jak to możliwe, że ta sztuka się udała. Otóż twórcy SELinux'a odciążyli użytkowników od żmudnego nadawania kontekstów w zależności od przeznaczenia plików wprowadzając opcję httpd_unified, które traktuje wszystkie pliki równo i te do zapisywania i te do odczytywania nadając mi wspólną etykietę httpd_sys_content_t. Jeśli jednak  wyłączymy tą opcję:

# setsebool httpd_unified off

wówczas musimy nadać konteksty do plików, do których nasza aplikacja ma zapisywać bądź też tylko dopisywać poprzez odpowiednio httpd_sys_rw_content_t oraz httpd_sys_ra_content_t. Początkowo wprowadza to dodatkowe zamieszanie, jednak w zamian otrzymujemy bardziej szczelne środowisko, w którym działa nasza aplikacja. Co jednak gdybyśmy poszli o krok dalej i wyodrębnili z naszej aplikacji kod PHP i nadali mu odpowiedni kontekst, niestety spotykamy się tutaj z niemiłym zaskoczeniem. Najpopularniejszym rozwiązaniem do PHPa jest kombinacja Apache plus mod_php, w takim wydaniu SELinux nie jest w stanie wyodrębnić tego co jest kodem PHP a zwykłym obrazkiem. Dopiero, gdy skorzystamy z modułu CGI, możliwe jest nadanie odpowiedniego kontekstu skryptom PHP:

-rwxr-xr-x. php php unconfined_u:object_r:httpd_sys_script_exec_t:s0 index.php

należy zwrócić uwagę na atrybut wykonywalności, dodatkowo należy uaktywnić opcję CGI:

# setsebool httpd_enable_cgi on

Dla formalności dodam, że konfiguracja Apache + php cgi jest wyjątkowo prosta wystarczy:

AddHandler cgi-script .php .php3 .php4 .php5 .phtml

oraz dopisać do opcji katalogu +ExecCGI

Tak obsługiwane skrypty PHP, wymagają modyfikacji w postaci dodania do każdego pliku ścieżki do interpretera PHP. Można jednak tego uniknąć korzystając:

echo ':PHP:E::php::/usr/bin/php-cgi:' > /proc/sys/fs/binfmt_misc/register

sprawi to, że pliki z rozszerzeniem php będą uruchamiane przez polecenie php-cgi.  Wyeliminowanie mod_php, umożliwiło nam jeszcze precyzyjniejsze definiowanie kontekstów bezpieczeństwa  i tak na przykład wgranie z zewnątrz złośliwego kodu nie zdyskredytuje naszej aplikacji, gdyż nie jest możliwe jego wykonanie, nawet sam serwer www nie może zmienić kontekstu plików, których jest właścicielem. Zastosowanie mechanizmu CGI, wiąże się jednak ze spadkiem wydajności.


Comments