Od Redakcji: artykuł pochodzi z lutowego wydania Linux Magazine. Kompletną listę artykułów możecie znaleźć na stronach miesięcznika.
Zamiast pozwalać użytkownikom logować się bezpośrednio do konta root, administratorzy systemu często uciekają się do polecenia su. Pozwala ono wykonywać operacje z konta innego użytkownika, z jego zestawem uprawnień. Podejście to ma swoje wady: użytkownik su może robić wszystko to, co użytkownik docelowy.
W wielu firmach uważa się, że do zachowania bezpieczeństwa wystarczy, by użytkownicy logowali się do własnego konta, a następnie wykonywali czynności na koncie administratora za pomocą polecenia su. To wygodne rozwiązanie, gdyż wystarczy dać użytkownikom dostęp do hasła administratora. Pojawia się jednak problem: każda osoba posiadająca dostęp do konta root może w praktyce zrobić wszystko.
Dobrą alternatywą jest polecenie sudo. Podobnie jak su, pozwala ono na wykonanie polecenia jako użytkownik docelowy, ale po jego zakończeniu wracamy do bieżącego konta. Prawdę mówiąc, taką możliwość oferuje również su, jednak ograniczenia wprowadzane przez sudo są znacznie większe.
Mimo to miejmy się na baczności. Jeśli polecenie zostanie źle skonfigurowane, może nie stanowić dla nas praktycznie żadnej ochrony. W tym artykule opisujemy niektóre techniki pracy z sudo.
Mądre ograniczenia
Spotkałem wielu administratorów, którzy używali sudo po prostu jako zmodyfikowanej wersji su, wykonując każde możliwe polecenie z konta administratora. Choć samo wykonywanie tej komendy przy każdej operacji przypomina o konieczności zachowania ostrożności, to wystarczy przecież użyć sudo do uruchomienia basha i otrzymamy sesję, która będzie praktycznie taka sama, jak przy poleceniu su. Niektórzy administratorzy robią więcej i ograniczają zakres możliwych poleceń, ale to zaledwie czubek góry lodowej.
Domyślna konfiguracja w wielu dystrybucjach Linuksa pozwala użytkownikom na wykonanie poprzez polecenie sudo dowolnej czynności z konta administratora, o ile posiadają do niego hasło. Nawet jeśli pracujemy na własnym komputerze i mamy do niego pełen dostęp, korzystanie z sudo zamiast z su jest dobrym nawykiem. Wiele zadań administratorskich wykonywanych poprzez interfejs KDE korzysta z polecenia kdesu, które na początku zawsze pyta nas o hasło do konta root (Rysunek 1).
Rysunek 1: Za pomocą kdesu KDE pyta nas o hasło administratora.
W przypadku sudo posiadanie hasła użytkownika docelowego nie wystarczy. Jesteśmy ograniczeni do poleceń znajdujących się w pliku konfiguracyjnym sudo, /etc/sudoers. Plik ten edytujemy za pomocą komendy visudo, która najpierw sporządza jego kopię, a następnie zastępuje oryginał zmodyfikowaną przez nas wersją. Przed zapisaniem sprawdzana jest składnia. W razie jakichkolwiek niezgodności pojawia się wiadomość, wskazująca numer wiersza i rodzaj błędu. Daje nam to możliwość poprawienia pliku; możemy też wyjść bez zapisywania zmian lub mimo wszystko zapisać błędną wersję (spowoduje to ostrzeżenie ze strony systemu) (Rysunek 2).
Rysunek 2: Visudo informuje o błędzie składniowym.
Konfiguracja sudo
W standardowym pliku sudoers zdefiniowana jest zaledwie garstka opcji, które dzielą się na trzy grupy. Pierwsza z nich definiuje pewne domyślne zachowania. Ustawienia mogą mieć formę wartości logicznych (włączone / wyłączone), liczb lub łańcuchów znaków. Zwykle jedna dyrektywa zajmuje jeden wiersz, ale jeśli jest zbyt długa, kontynuujemy na linuksową modłę, kończąc każdą linię lewym ukośnikiem ().
Przy definiowaniu zachowań domyślnych posługujemy się następującą składnią:
Defaults opcja
Na przykład:
Defaults env_reset
W wierszu tym każemy sudo zresetować zmienne środowiskowe, dostosowując je do ustawień użytkownika docelowego. env_reset stanowi parę z parametrem env_keep, który zawiera listę zmiennych środowiskowych do zachowania. Z reguły są to elementy związane z językiem i lokalizacją. Właściwie jest to funkcja bezpieczeństwa, gdyż złośliwy użytkownik mógłby tak ustawić ich ścieżki, by najpierw przeszukiwane były niestandardowe katalogi. Jeśli zmienna PATH nie zostanie zresetowana, umożliwia to wykonywanie kolejnych poleceń jako użytkownik docelowy. Na przykład skrypt powłoki uruchomiony poprzez sudo i korzystający z find mógłby posłużyć do uruchomienia /tmp/find, co może mieć niebezpieczne konsekwencje.
Warto również wiedzieć, że w przypadku sudo domyślnym użytkownikiem docelowym jest administrator. Możemy to zmienić, dodając do polecenia parametr -u. Mimo to wielu użytkowników jest przekonanych, że sudo oznacza tyle, co uruchomić polecenie z konta administratora. Choć jest to zapewne najpopularniejsza jego funkcja, nie zawsze jest ona konieczna lub pożądana. Na przykład konto użytkownika miewa zmienne środowiskowe, których nie posiada konto root.
Kolejną opcją związaną z bezpieczeństwem jest targetpw. Sprawia ona, że sudo pyta o hasło użytkownika docelowego. Jeśli nie ma on zdefiniowanego hasła, polecenie domaga się hasła użytkownika wywołującego.
Pamiętajmy, że są to domyślne ustawienia. Możemy skonfigurować konkretne polecenia (lub zestawy poleceń) tak, by zmienne środowiskowe podane poprzez wiersz poleceń nie były usuwane zgodnie z wcześniejszymi ustawieniami. Szczegółowe informacje znajdziemy na stronach dokumentacji sudoers.
Składnia może początkowo wydawać się skomplikowana, ale opanowanie jej nie sprawia większych problemów. Format poszczególnych wpisów jest następujący:
alias_użytkownika alias_hosta = (alias_użytkownika_docelowego) tag alias_polecenia
Zwróćmy uwagę, że alias nie oznacza, że możemy używać wyłącznie aliasów, gdyż każda jednostka jest sama dla siebie aliasem. Możemy na przykład określić użytkownika, polecenie itp. bez konieczności uprzedniego definiowania aliasów.
Ponieważ pierwszy wpis to użytkownik, wiersze te określa się mianem specyfikacji użytkownika. Możemy natrafić na następujący przykład zastosowania:
ALL ALL=(ALL) ALL
Jak łatwo odgadnąć, pozwala on wszystkim użytkownikom na wykonywanie za pomocą sudo z dowolnego komputera dowolnych poleceń poprzez dowolnego użytkownika docelowego. Nie daje nam to absolutnej swobody działania, gdyż wciąż musimy znać hasło wybranego użytkownika, jednak zapewnia dodatkowe zabezpieczenie, gdyż nie ma potrzeby uruchamiania nielimitowanej sesji z konta użytkownika docelowego.
Możemy też natknąć się na wpis:
root ALL=(ALL) ALL
Pełni on praktycznie tą samą funkcję, co poprzednie polecenie, ale dotyczy wyłącznie administratora, który uzyskuje uprawnienia do uruchamiania dowolnych poleceń z kont dowolnych użytkowników.
Przydatna jest też możliwość definiowania aliasów. Są one z reguły używane w przypadku list różnych obiektów (na przykład operatorów, którzy pełnią w firmie podobne funkcje).
Definicje aliasów mają jeden podstawowy format:
rodzaj_aliasu spacja nazwa_aliasu = obiekt1, obiekt2, ...
Nie jesteśmy tu ograniczeni do standardowych obiektów, jak użytkownicy w /etc/passwd lub konkretne hosty, lecz mamy do wyboru szeroką gamę opcji (patrz: dokumentacja sudoers).
Z mojego doświadczenia wynika, że grupowanie obiektów pod aliasami znacznie upraszcza skomplikowaną konfigurację. Jeśli różne grupy użytkowników mają mieć dostęp do różnych zestawów poleceń, jesteśmy pewni, że każdy z nich otrzyma właściwe uprawnienia. Dodatkowo, jeśli będziemy potem chcieli dokonać modyfikacji, wystarczy zrobić to w jednym miejscu, a nie przeglądać cały plik.
Opcja alias_użytkownika_docelowego definiuje użytkownika docelowego dla listy poleceń. Tak jak w przypadku innych obiektów, w jednym wierszu znajduje się kilka takich opcji. Niektóre polecenia chcemy wykonywać z poziomu administratora, zaś dla innych wystarczy mniej uprzywilejowany użytkownik.
Na alias_polecenia składają się indywidualne nazwy poleceń, katalogów lub innych aliasów poleceń. Powinniśmy zwrócić uwagę na kilka rzeczy: po pierwsze nazwa polecenia musi zawierać pełną ścieżkę. Jeśli nie spełnimy tego warunku, visudo zakomunikuje błąd składni.
Jeśli podamy po prostu nazwę polecenia, wszelkie dodatkowe opcje czy parametry możemy wpisać z wiersza poleceń. W zależności od sytuacji, może to być korzystne lub nie. By ograniczyć pole manewru danego użytkownika, musimy zdefiniować konkretne opcje, których ma prawo używać. Pamiętajmy, że bardzo ważny jest poprawny zapis argumentów, chyba że użyliśmy wieloznaczników.
Do każdego wpisu możemy przyporządkować etykiety. Najpopularniejsza z nich to NOPASSWD, informująca, że polecenia wykonywane są bez pytania o konkretne hasło. Jej przeciwieństwem jest PASSWD, która wymaga podania poprawnego hasła (jest to opcja domyślna).
Połączenie wszystkich powyższych elementów daje, co następuje:
jimmo ALL = (operator) /bin/more /var/log/messages, (root) NOPASSWD: /sbin/fdisk -l
W naszym przykładzie użytkownik jimmo ze wszystkich komputerów może wykonywać polecenie more jako operator, ale tylko na pliku /var/log/messages. Może on również użyć jako administrator polecenia /sbin/fdisk -l, bez wpisywania hasła. Zauważmy, że w obu przypadkach podano konkretne argumenty. Przy próbie użycia innych (na przykład /sbin/fdisk /dev/hda) sudo pyta o odpowiednie hasło.
Zagrożenia dla bezpieczeństwa
Podobnie jak inne elementy systemu związane z bezpieczeństwem, sudo może otworzyć wiele luk. Część z nich powstaje w wyniku niepoprawnej konfiguracji. Za innymi problemami stoi brak zrozumienia naturalnego zachowania polecenia, które wykonujemy wraz z sudo.
Bywa też tak, że zdajemy sobie sprawę ze sposobu działania komendy, ale nie dostrzegamy pewnych jego konsekwencji. Na przykład: jednym z ważnych zadań wykonywanych przez administratora jest reagowanie na przepełniający się system plików. Oczywiście jeśli nie mamy odpowiednich uprawnień, może się to okazać kłopotliwe. W pewnej znanej mi sytuacji problem został rozwiązany poprzez skonfigurowanie sudo tak, by operatorzy mogli korzystać z gzipa. Miało to umożliwić kompresowanie logów i uwalnianie miejsca na dysku.
Rozumowanie to ma dwie wady: pierwsza z nich to podejście administratorów, którzy żądają od operatorów radzenia sobie z problemem na bieżąco, zamiast skonfigurować system tak, by automatycznie kompresował pliki. Drugi problem polega na tym, że po zakończeniu pracy gzip usuwa oryginał.
By umożliwić operatorom skompresowanie dowolnych logów, gzip wpisany został z gwiazdką, co oznacza, że może wykonać operację na dowolnym pliku. Możliwe więc jest skompresowanie pliku potrzebnego do poprawnego funkcjonowania systemu. Bardzo prostym przykładem jest plik /etc/passwd. Gdyby został on skompresowany poprzez sudo, spowodowałoby to usunięcie oryginału i niepoprawne działanie wielu elementów systemu.
To samo biuro miało problem z niekontrolowanymi procesami. Rozwiązano go poprzez umożliwienie operatorom zabijania owych procesów poprzez sudo. Tak jak w przypadku gzipa, do polecenia kill dodano gwiazdkę, więc użytkownik mógł zabić dowolny proces.
W obu przypadkach powinniśmy zakładać wiarygodność operatorów. Z drugiej strony, jeśli naszym celem jest jak najlepsze zabezpieczenie systemu, w tym uniemożliwienie ludziom robienia tego, czego robić nie powinni, to pozwolenie im na usuwanie dowolnych plików lub zabijanie dowolnych procesów jest nieco niefrasobliwe.
Kolejne zagrożenie wynika z pominięcia naturalnych zachowań definiowanego polecenia. Próby identyfikacji problemów wymagają często przeglądania różnych plików rejestru i konfiguracji. W niektórych przypadkach zadanie to może należeć do operatora. Zamiast określać, które pliki mogą być odczytywane przez których użytkowników, możemy pokusić się o umożliwienie im wykonywania polecenia more, co pozwoli przeglądać dowolne pliki w systemie.
Tu także dowolne znaczy dowolne. Nie każdy plik powinien być dostępny dla wszystkich, chociażby ten zawierający hasła. Nawet jeśli ufamy naszym użytkownikom, musimy brać pod uwagę sytuację, w której któreś z kont zostaje przejęte przez intruza.
Inny problem z poleceniem more polega na tym, że pozwala ono na wykonanie polecenia shell escape i uruchomienie dla tej komendy osobnej podpowłoki. Ponieważ more uruchamiane jest z konta administratora, wszystkie podprocesy, w tym powłoki, również działają jako root. Oznacza to, że mamy teraz dostęp do powłoki z konta administratora, a w związku z tym pełną kontrolę nad systemem! Co gorsza, zdarzają się sytuacje, gdzie do uruchomienia polecenia niepotrzebne jest nawet hasło, co oznacza zupełnie nieograniczony dostęp do powłoki superużytkownika.
Jednym z potencjalnych rozwiązań tego problemu jest zablokowanie użytkownikom dostępu do programów z opcją shell escape. Jeśli potrzebna jest możliwość przeglądania zawartości pliku, możemy pozwolić im korzystać z polecenia cat, które nie stanowi tak dużego zagrożenia. Długi plik może wprawdzie nie zmieścić się na ekranie, ale nie jest to problem, gdyż teraz możemy bezpiecznie przepuścić jego zawartość przez polecenie more. Jako że proces ten nie jest już uruchamiany z konta użytkownika docelowego (czyli administratora), wyjście do powłoki spowoduje powrót do początkowego konta.
Choć w tym przypadku odnosimy się do konkretnych poleceń, możemy trafić na program, który zaskoczy nas wyjściami do powłoki w najbardziej nieoczekiwanych momentach. Sudo rozwiązuje problem poprzez odpowiednie mechanizmy blokujące. Pierwszy z nich to opcja noexec:
Defaults noexec
Domyślnie stosuje się ona do wszystkich poleceń, bez względu na to, który użytkownik je uruchamia i jaki jest użytkownik docelowy. Możemy ewentualnie zablokować wyjścia do powłoki dla konkretnych poleceń za pomocą NOEXEC:
jimmo ALL=NOEXEC /usr/bin/view, /usr/bin/more
Sudo dobrze sobie radzi z odnotowywaniem, kto co zrobił i czy operacja zakończyła się powodzeniem. Domyślnie informacje te rejestrowane są poprzez usługę syslog. Możemy jednak zdefiniować konkretny plik rejestru za pomocą wpisu logfile w /etc/sudoers oraz przyporządkować mu dowolne opcje i priorytety. Więcej informacji znajdziemy w dokumentacji sudoers.
Podsumowanie
Tak jak w przypadku innych narzędzi bezpieczeństwa, najlepszą strategią dla sudo jest pełne zablokowanie dostępu i stopniowe odblokowywanie poszczególnych poleceń. Inną kwestią, o której musimy pamiętać, jest umiejętność powłok Linuksa do uruchamiania poleceń wspólnie, poprzez potoki.
Zanim więc zaczniemy projektować procedury administracji systemu dla naszego środowiska, warto upewnić się, czy wiemy, dlaczego korzystamy z poszczególnych poleceń i argumentów, uruchamianych poprzez sudo. Może znajdą się lepsze rozwiązania (jak zapobieganie niekontrolowanym procesom) lub bezpieczniejsze sposoby definiowania poleceń.
Podsumowując: lepiej być przesadnie ostrożnym niż przesadnie wygodnym.
nie zdawałem sobie sprawy, że to takie skomplikowane 😉 sudo, to zwyczajnie sudo i już 😉
Jestem w trakcie czytania i pewno na koment za wcześnie. Z pewnością jednak już teraz powiem, iż możliwość używania sudo przez zwykłych użytkowników nie jest bezpieczne. Tak i już ;).
Czytam dalej bo artykuł bardzo fajny i ważny.