Jak uruchomić usługę jako użytkownik bez uprawnień
Uruchamianie procesów z konta root grozi przejęciem kontroli nad całym serwerem. Zastosuj zasadę najmniejszych uprawnień lub dyrektywę DynamicUser w systemd dla izolacji.
Dlaczego nie uruchamiać wszystkiego jako root
Użytkownik root posiada pełne uprawnienia w systemie: może odczytać każdy plik, zmienić dowolne ustawienie oraz usunąć cały system. Uruchomienie usługi jako root przekazuje te uprawnienia danej usłudze. Jeśli usługa zawiera błąd, który może zostać wykorzystany przez atakującego, przejmuje on kontrolę nie tylko nad usługą, ale nad całym serwerem. Uruchamianie procesów jako użytkownik bez uprawnień administracyjnych ogranicza zakres potencjalnych szkód. Błąd w usłudze działającej na ograniczonym koncie daje atakującemu dostęp jedynie do zasobów dostępnych dla tego konta, co w poprawnie skonfigurowanym systemie powinno być zakresem minimalnym.
Jest to zasada najmniejszych uprawnień: każdemu elementowi systemu należy nadać dokładnie takie uprawnienia, jakich wymaga do działania, i żadne inne. Jest to najskuteczniejsza metoda ograniczania skutków ewentualnego przełamania zabezpieczeń, a w nowoczesnych systemach serwerowych jej wdrożenie nie wiąże się z dodatkowym kosztem operacyjnym.
Dedykowane konto dla każdej usługi
Klasyczne podejście polega na utworzeniu osobnego użytkownika systemowego dla każdej usługi. Taki użytkownik jest właścicielem wyłącznie plików danej usługi i nie posiada uprawnień do logowania. Konto systemowe dla aplikacji webowej może wyglądać następująco:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin appsvcKażda flaga ma znaczenie. --system tworzy konto usługowe, a nie konto użytkownika. --no-create-home pomija katalog domowy, który nie jest wymagany. --shell /usr/sbin/nologin sprawia, że nawet w przypadku przejęcia konta przez atakującego, nie będzie on mógł otworzyć powłoki. Konto istnieje wyłącznie w celu obsługi procesu i jego plików.
Następnie należy nadać użytkownikowi dostęp tylko do niezbędnych plików:
sudo chown -R appsvc:appsvc /opt/myappTeraz usługa odczytuje i zapisuje dane tylko we własnym katalogu i nie ma dostępu do innych miejsc na dysku. W przypadku wykorzystania luki, atakujący może zmodyfikować jedynie pliki w /opt/myapp. Konto nadal może odczytywać wszystkie pliki dostępne dla każdego użytkownika, ale nie może modyfikować pozostałych elementów systemu.
Uruchamianie usługi przez systemd na koncie użytkownika
Po utworzeniu konta należy skonfigurować systemd tak, aby uruchamiał usługę z jego uprawnieniami. W pliku jednostki służy do tego jedna linijka:
[Service]
ExecStart=/opt/myapp/bin/server
User=appsvc
Group=appsvcUser=appsvc oznacza, że proces uruchamia się z ograniczonymi uprawnieniami danego konta, a nie z uprawnieniami root. Jest to standardowa i zalecana metoda uruchamiania aplikacji w systemd, którą warto stosować dla każdej tworzonej jednostki. Ograniczenie uprawnień nie pomoże, jeśli systemd monitoruje niewłaściwy proces. Jeśli jednostka zgłasza stan active po cichym zakończeniu działania demona, należy sprawdzić, czy wybrano właściwy parametr Type= dla sposobu uruchamiania procesu.
Pomiń całkowicie konto użytkownika dzięki DynamicUser
systemd może pójść o krok dalej i utworzyć tymczasowego użytkownika, który istnieje tylko podczas działania usługi. Ustaw DynamicUser=yes, aby w ogóle nie zarządzać kontem:
[Service]
ExecStart=/opt/myapp/bin/server
DynamicUser=yes
StateDirectory=myappPodczas uruchamiania systemd przydziela nieużywany identyfikator użytkownika; po zatrzymaniu usługi zwalnia go. Usługa otrzymuje również prywatny /tmp, widok większości systemu plików tylko do odczytu oraz katalog stanu z prawem zapisu w /var/lib/myapp, który StateDirectory= konfiguruje i udostępnia usłudze. Nic takiego nie było możliwe w SysV init, gdzie ograniczanie uprawnień zależało od tego, co robił skrypt startowy danej usługi. Ta luka w zabezpieczeniach jest w dużej mierze powodem, dla którego dystrybucje przeszły na systemd. W przypadku samodzielnej usługi, która potrzebuje jedynie własnego katalogu stanu, DynamicUser=yes jest najmniej wymagającym sposobem na uzyskanie silnej izolacji, ponieważ nie istnieje żadne długotrwałe konto, które atakujący mógłby wykorzystać.
Ręczne pisanie plików jednostek jest uciążliwe, a poprawna konfiguracja dyrektyw utwardzających stanowi największą wartość. Generator dostępny w przewodniku po usługach i timerach systemd może automatycznie wypełnić te opcje, zapewniając poprawność jednostki już przy pierwszym użyciu.
Jak to współgra z resztą
Zasada najmniejszych uprawnień stanowi jedną z warstw zabezpieczeń i współpracuje z pozostałymi, zamiast je zastępować. Firewall typu default-deny kontroluje, co może uzyskać dostęp do usługi; uruchomienie jej na koncie z ograniczonymi uprawnieniami ogranicza skutki ewentualnego przejęcia procesu; a utwardzona konfiguracja SSH zapobiega dostępowi intruzów do serwera. Żaden z tych elementów z osobna nie jest wystarczający, lecz razem sprawiają, że błąd w jednej usłudze nie prowadzi do kompromitacji całego serwera. Hostowanie usług przechowujących dane wrażliwe pokazuje granice tych warstw: ograniczone konto limituje zakres działań przejętego procesu, jednak samodzielnie hostowany menedżer haseł, taki jak Vaultwarden nadal zależy od ochrony tokena administratora oraz pliku kopii zapasowej, których izolacja użytkownika nie obejmuje.
Zanim przejdziesz dalej, wykonaj listę kontrolną utwardzania całego systemu i wygeneruj spersonalizowaną kopię, na której będziesz pracować:
FAQ
Dlaczego nie należy uruchamiać usługi jako root?
Ponieważ konto root posiada pełne uprawnienia w systemie, przejęcie usługi działającej z tymi uprawnieniami daje atakującemu kontrolę nad całym serwerem, a nie tylko nad samą usługą. Uruchomienie usługi na ograniczonym koncie bez uprawnień administracyjnych ogranicza potencjalne szkody do zasobów dostępnych dla tego użytkownika. Konto root należy zarezerwować wyłącznie do celów administracyjnych, a każdą usługę działającą w tle uruchamiać jako użytkownik o ograniczonych uprawnieniach.
Jak utworzyć użytkownika, który nie może się zalogować?
Należy wykonać polecenie sudo useradd --system --no-create-home --shell /usr/sbin/nologin NAME. Powłoka nologin oznacza, że konto nie może otworzyć sesji interaktywnej, nawet w przypadku kradzieży danych uwierzytelniających, --system oznacza konto jako usługowe, a --no-create-home pomija tworzenie katalogu domowego, który nie jest wymagany. Należy nadać użytkownikowi własność wyłącznie jego własnych plików za pomocą chown.
Czym jest systemd DynamicUser?
Opcja DynamicUser=yes instruuje systemd, aby utworzył tymczasowego użytkownika dla usługi, który istnieje tylko podczas jej działania, co eliminuje konieczność zarządzania długotrwałym kontem. Zapewnia to również usłudze prywatny /tmp, widok systemu plików w trybie głównie tylko do odczytu oraz zarządzany katalog stanu. Jest to najmniej wymagający sposób uruchomienia samodzielnej usługi z wykorzystaniem tymczasowej tożsamości o niskich uprawnieniach.
Czy uruchomienie usługi jako użytkownik inny niż root zastępuje firewall?
Nie. Chronią one przed różnymi zagrożeniami. Uruchomienie usługi jako użytkownik bez uprawnień ogranicza jej możliwości w przypadku przejęcia, natomiast firewall ogranicza dostęp do samej usługi z zewnątrz. Należy stosować oba rozwiązania wraz z zabezpieczonym SSH, aby każda warstwa uzupełniała braki pozostałych.
Które pliki powinny należeć do użytkownika usługi?
Wyłącznie te, których usługa faktycznie potrzebuje. Należy nadać użytkownikowi własność jego katalogu roboczego oraz danych, pozostawiając resztę plików jako własność root. Dobrą praktyką jest sudo chown -R svc-app:svc-app /opt/svc-app dla katalogu aplikacji, podczas gdy konfiguracja w /etc powinna pozostać własnością root i być jedynie możliwa do odczytu przez usługę. Celem jest ograniczenie możliwości modyfikacji plików przez proces w przypadku jego przejęcia wyłącznie do jego własnych danych, bez wpływu na resztę systemu.