Systrace - interaktywna kontrola wywołań systemowych
Programy, z których korzystamy na codzień, mają pełen dostęp do wszystkich naszych danych. Niestety, włamywacz wykorzystujący lukę, na przykład w przeglądarce, też uzyskuje ten przywilej. Dzięki Systrace, ochrona naszych zasobów, w takich przypadkach, staje się możliwa.
http://www.citi.umich.edu/u/provos/systrace/
Największe repozytorium regułek Systrace
http://www.systrace.org/
Lektura prasy codziennej nie nastraja optymistycznie. Coraz więcej słyszy się o włamaniach komputerowych. Coraz częściej dotykają one zwykłych użytkowników. Nie można mieć pewności, czy oprogramowanie używane na codzień nie ma żadnych luk. Nawet przy mylnym założeniu, że autorzy nie popełnili żadnego błędu, zawsze istnieje ryzyko, iż serwis, z którego ściągamy żródła został skompromitowany. Obecność ostatnich gości na serwerach GNU wykazuje, że nie jest to znowu aż tak abstrakcyjne przypuszczenie.
Systrace, rozwijany przez Nielsa Provosa w Centrum Integracji Technologii Informatycznych (CITI) przy Uniwersytecie Michigan, jest próbą odpowiedzi na ten problem i zwiększenia bezpieczeństwa naszych systemów. Podstawowym założeniem tego projektu jest dokładna kontrola każdej operacji, którą wykonuje monitorowany program. Co za tym idzie, zezwolenie tylko na działania, które są faktycznie niezbędne.
Jest to bardzo praktyczne podejście. Ponieważ istotnie demon DNS standardowo nasłuchuje na porcie 53, przyjmuje połączenia klienckie oraz zwraca im odpowiedzi, ale nie oczekujemy przecież od niego, aby dodawał nowych użytkowników, uruchamiał powłokę, czy też ściągał z odległych komputerów programy. Przed tym właśnie spróbujemy się obronić.
Bez wywołań systemowych nie ma życia
Implementacja zadania postawionego przez Systrace wcale nie jest taka prosta. Aby rozwiązanie to miało praktyczny sens musi być niezależne od środowiska monitorowanych programów oraz od języka programowania w jakim zostały napisane. Wszystkie te warunki gwarantuje tylko kontrolowanie wywołań systemowych. Są to - w dużym uproszczeniu - funkcje dostępne dla użytkowników, które pozwalają na wykonywanie zewnętrznych operacji, to jest takich, które mają wpływ na środowisko programu. Począwszy od tworzenia i usuwania plików, a skończywszy na samym zakończeniu działania.
Jednym z najczęściej używanych wywołań systemowych jest execve(), które po prostu uruchamia inne programy, oraz connect(), łączące się poprzez sieć do odległego komputera. W swojej pracy często napotkamy jednak wywołania systemowe, o których nie słyszeliśmy. Szczegółówą pomoc w takich sytuacjach znajdziemy na stronach podręcznika systemowego:
Włamywacz także, gdy pragnie wtargnąć do jakiegoś systemu, korzysta z wywołań systemowych. Atak najczęściej jest przeprowadzany poprzez wysłanie spreparowanych pakietów, które wykorzystując lukę, umieszczają w usłudze specjalny kod (shellcode). Kod ten zazwyczaj uruchamia powłokę, co nie może się odbyć bez użycia wywołania systemowego execve().
Początek pracy
Systrace składa się z dwóch elementów. Najważniejszym, niezależnym od systemu operacyjnego, jest program, który podejmuje wszystkie decyzje dotyczącego tego, na co zezwolić monitorowanym procesom. To z nim będziemy pracowali w dalszej części artykułu. Informacje i moc decyzyjną, o wywołaniach systemowych kontrolowanych procesów, dostarcza mu drugi element, czyli pseudo-urządzenie w jądrze.
W NetBSD oraz OpenBSD, pod które Systrace był pisany pierwotnie, obie te części znajdują się w podstawowej instalacji. Jeśli używamy tych systemów, powinniśmy przed rozpoczęciem pracy zaktualizować swoje środowisko do najnowszej wersji, wykryto bowiem parę nieznacznych błędów oraz stosunkowo niedawno dodano opcję rozszerzenia przywilejów. Dla jąder innych niż GENERIC, upewnijmy się, czy w pliku konfiguracyjnym znajduje się linia:
Gdy używamy Linuksa lub FreeBSD, szczegóły dotyczące sposobu instalacji znajdziemy na stronie domowej projektu.
Zestawy reguł
Dla każdego monitorowanego programu Systrace potrzebuje zestawu regułek, definiujących na jakie wywołania systemowe i w jakim kontekście zezwolić. Ulokowane są one domyślnie albo w katalogu użytkownika $HOME/.systrace albo globalnie w /etc/systrace. Najprostszym przykładem są:
native-exit: permit
Odczytujemy to jako zezwolenie (permit) na wykonanie dwóch wywołań systemowych: getuid() oraz exit(). Odpowiadają one kolejno za pobranie numeru UID oraz za zakończenie programu. Ponieważ OpenBSD oraz NetBSD obsługują także wywołania systemowe innych systemów, musimy zaznaczyć, że chodzi nam o natywne (native).
Operatory dostępne w regułkach
match - Pasuje, gdy argument wywołania systemowego zawiera się w
podanym wzorze.
eq - Pasuje, gdy argument wywołania systemowego jest równy
neq - Pasuje, gdy argument wywołania systemowego jest inny.
sub - Pasuje, gdy argument wywołania systemowego zawiera się
w łańcuchu znaków.
nsub - Pasuje, gdy argument wywołania systemowego nie zawiera się
w łańcuchu znaków.
inpath - Pasuje, gdy argument wywołania systemowego znajduje się w
podanej ścieżce.
re - Pasuje, gdy argument wywołania systemowego zawiera się w
podanym wyrażeniu regularnym.
Oczywiście pozwalanie na wszystko aplikacji, nie jest dobrą polityką bezpieczeństwa. Ba, nasze postępowanie powinno być wprost przeciwne. Systrace oferuje nam możliwośc zabronienia (deny) wykonania danego wywołania systemowego, zależnie od zadanych argumentów oraz z kodem zwracanego błędu:
Każda próba odczytu z systemu plików dla argumentów równego "/etc" zakończy się z błędem "EPERM". Czyli po polsku: Aplikacja, która zapragnie otworzyć jakiś plik z katalogu "/etc", czy też chociażby go wylistować, dostanie informację, że nie ma odpowiednich uprawnień ku temu.
Aliasy oferowane przez Systrace
fsread - Wszystkie operacje odczytu z systemie plików, czyli stat(),
lstat(), readlink(), access().
fswrite - Wszystkie operacje zapisu na systemie plików, czyli open(),
unlink(), mkdir(), rmdir().
Generacja automatów
Ręczna edycja regułek przydaje się nam przede wszystkim do zrozumienia jak działa Systrace oraz później do poprawek, dodania zaawansowanych opcji, itp. Nie jest to jednak metoda odpowiednia do tworzenia konfiguracji od zera. Prosty program "ls" uruchomiony pod OpenBSD, korzysta z wywołań systemowych ponad sto trzydzieści razy. Bardziej skomplikowane aplikacje, operują o wiele większą liczbą.
Automatyczne generowanie regułek rozpoczynamy w taki sposób:
Zostanie stworzona najprostsza konfiguracja. Systrace nie będzie ingerował w to, co robi monitorowany program i jego procesy potomne, ale wszystkie użyte wywołania systemowe zostaną zapisane w formie regułek. Metoda ta przynosi wymierne efekty, jeżeli jest stosowana dłuższy czas, dzięki czemu stworzona konfiguracja przewiduje większość normalnych zachowań programu i nie wymaga dużych poprawek.
Systrace oferuje nam też interaktywne narzędzie do tworzenia konfiguracji. Zależnie od gustów i preferencji, z menu graficznym:
Lub menu tekstowym:
W tym trybie, będziemy pytani o to, jak postąpić wywołaniami systemowymi, dla których nie zostały zdefiniowane żadne akcje. Zdarza się, że Systrace jest uruchamiane w taki sposób w normalnych zastosowaniach, ponieważ pojawiające się okienko, informuje nas od razu od zainstniałej nieprawidłowości. Nie zawsze jednak interakcja użytkownika jest możliwa.
W trybie interaktywnym, Systrace poinformuje nas o każdy nieprzewidzianym zachowaniu.
Najpierw eksperymenty
Gdy uznamy, że regułki dla danej aplikacji są już gotowe, przystąpmy do
testów:
Argument "-a", w przeciwieństwie do "-A", domyślnie nie zezwala na wykonanie żadnego wywołania systemowego, poza zdefiniowanymi w konfiguracji. Także wszystkie programy, które uruchomi monitorowany proces, będą kontrolowane, jeśli posiadają zestawy regułek.
Każda próba wykonania niedozwolonej operacji zostanie notowana w logach systemowych. Może się to nam przydać do wykrycia udaremnionych poczynań włamywacza lub po prostu do poprawienia niedopieszczonych regułek.
W logach systemowych znajdziemy zanotowane wszystkie nieprzewidziane przez regułki zachowania.
Czasami w środowiskach produkcyjnych spotyka się Systrace wywoływane w taki sposób:
Dzięki opcji -i (inherit) wszystkie regułki zdefiniowane dla ftpd, są automatycznie dziedziczone przez procesy, które zostaną stworzone tylko do obsługi klientów. Jest to konieczne, gdy program rozwidla się, aby obsłużyć połączenia klienckie, ponieważ jego procesy potomne są podatne na te same błędy i mają takie same wymagania.
Zaawansowane opcje konfiguracyjne
Do tej pory poznaliśmy jedynie podstawowe i najczęściej spotykane opcje konfiguracyjne, teraz jednak skupimy się na tych bardziej zaawansowanych. Warto pamiętać, że zasugerowane zastosowania nie są bynajmniej jedynymi i można znaleźć wiele własnych ułatwiających naszą pracę.
Tak jak już wcześniej zauważyliśmy, Systrace wywołane z odpowiednimi argumentami, loguje wszystkie niepożądane operacje, co z poprawnym zestawem regułek czyni z niego całkiem niezłym IDS-em (Intrusion Detection System). Na tym jednak nie koniec. Flaga "log" pozwala logować dowolną operację:
Bez ingerowania zupełnie w wynik, każde uruchomienie jakiegokolwiek programu przez monitorowany proces pozostawi ślad w logach. Regułka ta, zdefiniowana dla powłoki jako dziedziczna, spowoduje zapis wszystkich poczynań użytkowników przy całkowitej pewności, że nie usuną oni pliku historii, w momencie, gdy uznają go za zbyteczny.
Inną ciekawą opcją jest rozszerzanie przywilejów (privilige elevation) tylko do wykonania jednej operacji. Niejednokrotnie program potrzebuje przywilejów superużytkownika jedynie po to, by nasłuchiwać na porcie systemowym lub utworzyć połączenie do konstruowanie pakietów ICMP. Za pomocą rozszerzenia przywilejów, prawa superużytkownika są przyznawane tylko na czas zdefiniowanych operacji. Na przykład:
Dzięki temu nasz serwer HTTP może być zupełnie nieuprzywilejowanym procesem. Brzmi wspaniale, ale to rozwiązanie ma parę wad. Prawa superużytkownika są w dalszym ciągu wymagane przez Systrace. Do tego, okazuje się, że są one nadużywane bardzo często przez programy w miejscach, gdzie można by się bez nich obyć. Zatem stworzenie naprawdę bezpiecznego środowiska za pomocą rozszerzania przywilejów, wymagałoby wielu poprawek i nie jest zadaniem banalnym.
Realizacja konkretnego zadania
Aby ułatwić Czytelnikowi dalszą pracę z Systrace, zrealizujemy na koniec monitoring serwera identd. Zajmuje się on w dużym uproszczeniu, identyfikowaniem użytkownika, który próbuje się połączyć z dalekim komputerem, dzięki czemu, na przykład gdy dojdzie do włamania, możemy zlokalizować sprawcę bez trudu. Użyjemy OpenBSD oraz domyślnie dołączonego do niego demona.
Na początek tworzymy podstawowy zasób regułek:
Parametr "-b" oznacza, że identd jest uruchomiony w trybie samodzielnym (stand-alone), zatem musi on samemu nasłuchiwać przychodzących połączeń na porcie 113, a nie jest wywoływany z poziomu serwera inetd.
Podczas działania łączymy się z paroma usługami, które zapytują o ident i gdy jesteśmy zdania, że stworzona konfiguracja jest już odpowiednia, kończymy tworzenie regułek:
29173 p5 Ix 0:00.00 /usr/libexec/identd -b
root@rasp:~# kill -TERM 29173
Teraz przystępujemy do sprawdzenia stworzonego zestawu regułek:
Jeżeli w logach systemowych znajdziemy informację o tym, że identd próbował wykonać jakąś niepożądaną operację, powinniśmy dokonać poprawek i uruchomić go ponownie. Gdy już nasza konfiguracja jest gotowa, przenosimy ją do systemowego katalogu z zestawami regułek:
root@rasp:~# chmod 600 /etc/systrace/usr_libexec_identd
Na koniec modyfikujemy skrypt startowy /etc/rc, zmieniając linijki:
echo -n ' identd'; /usr/libexec/identd ${identd_flags}
fi
Na:
if [ "X${identd_flags}" != X"NO" ]; then
echo -n ' identd'; systrace -a /usr/libexec/identd ${identd_flags}
fi
Dzięki czemu przy ponownym uruchomieniu systemu, identd zostawnie uruchomiony
wraz z Systrace.

Demony monitorowane przez Systrace mają na liście procesów, przedrostek
"systrace".
Zamiast podsumowania
W środowiskach produkcyjnych, poza bezpieczeństwem, ważne jest też generowane obciążenie. Narzut powodowany przez Systrace jest bardzo mały i praktycznie niezauważalny dla zwykłego użytkownika. Niels Provos w publikacji technicznej CITI "Poprawa bezpieczeństwa przy użyciu kontroli wywołań systemowych" prezentuje pełen zestaw benchmarków.
Pomimo dokładnego omówienia plików konfiguracyjnych, w ramce W SIECI znajdują się linki do repozytorium zawierającego gotowe zestawy konfiguracyjne dla większości popularnych programów. Podobnie jak i regułki generowane automatycznie, tak i te wymagają pewnych poprawek. Najczęściej były one tworzone albo z myślą o konkretnej konfiguracji, która niekoniecznie nas interesuje, albo też o wszystkich opcjach, co z kolei może ułatwić pracę włamywaczom.
tytus, nie., 20/04/2008 - 16:26
