Dlaczego procesy w kontenerach Dockera nie powinny działać jako root
Opublikowany: 2022-08-19 Procesy w kontenerze Docker nie powinny być uruchamiane jako root. Bezpieczniej jest uruchamiać aplikacje jako użytkownik inny niż root, który określasz jako część pliku Dockerfile lub podczas korzystania z docker docker run
. Minimalizuje to ryzyko, prezentując zmniejszoną powierzchnię ataku na wszelkie zagrożenia w Twoim kontenerze.
W tym artykule dowiesz się o zagrożeniach związanych z uruchamianiem aplikacji kontenerowych jako root. Zobaczysz również, jak utworzyć użytkownika innego niż root i skonfigurować przestrzeń nazw w sytuacjach, w których nie jest to możliwe.
Dlaczego bieganie jest niebezpieczne dla roota?
Kontenery są domyślnie uruchamiane jako root. Demon Docker jest wykonywany jako root na twoim hoście, a uruchomione kontenery również będą rootem.
Chociaż może się wydawać, że root w kontenerze jest niezależnym użytkownikiem, w rzeczywistości jest to to samo, co konto root na twoim hoście. Separację zapewniają tylko mechanizmy izolacji kontenerów platformy Docker. Nie ma silnej fizycznej granicy; inny proces twojego kontenera uruchamiany przez użytkownika root w jądrze hosta. Oznacza to, że luka w Twojej aplikacji, środowisku uruchomieniowym platformy Docker lub jądrze systemu Linux może umożliwić atakującym wyrwanie się z kontenera i wykonanie na komputerze operacji z uprawnieniami roota.
Istnieje kilka wbudowanych zabezpieczeń, które zmniejszają ryzyko takiego zdarzenia. Root wewnątrz kontenera jest nieuprzywilejowany i ma ograniczone możliwości. Uniemożliwia to kontenerowi korzystanie z poleceń administracyjnych systemu, chyba że ręcznie dodasz możliwości lub użyjesz trybu uprzywilejowanego podczas uruchamiania kontenerów.
Pomimo tego ograniczenia, pozwolenie aplikacjom na uruchamianie jako root pozostaje zagrożeniem. Tak jak ograniczyłbyś użycie roota w tradycyjnym środowisku, niemądre jest niepotrzebne używanie go w swoich kontenerach. Zapewniasz nadmiernie uprzywilejowane środowisko, które daje atakującym większą przyczółek w przypadku wystąpienia naruszenia.
Uruchamianie aplikacji kontenerowych jako użytkownik inny niż root
Najlepszym rozwiązaniem w przypadku aplikacji kontenerowych jest uruchamianie jako zwykły użytkownik. Większość oprogramowania nie wymaga dostępu do roota, więc zmiana użytkownika zapewnia natychmiastową ochronę przed pęknięciem kontenera.
Powinieneś utworzyć nowe konto użytkownika jako jeden z ostatnich etapów w pliku Dockerfile. Możesz to osiągnąć za pomocą instrukcji USER
:
Z obrazu bazowego: najnowszy URUCHOM apt install demo-pakiet USER demo-user:demo-group PUNKT WEJŚCIOWY ["demo-binarny"]
Kontenery uruchomione z tego obrazu będą działały jako demo-user
. Użytkownik będzie członkiem grupy demo-group
group. Możesz pominąć nazwę grupy, jeśli nie chcesz, aby użytkownik był w grupie:
USER demo-użytkownik
Zamiast nazw możesz podać identyfikator użytkownika (UID) i identyfikator grupy (GID):
UŻYTKOWNIK 950:950
Przypisanie znanego UID i GID jest zwykle najbezpieczniejszym sposobem postępowania. Zapobiega mapowaniu użytkownika w kontenerze na nadmiernie uprzywilejowane konto hosta.
USER
jest często określany jako przedostatni etap w pliku Dockerfile. Oznacza to, że nadal możesz uruchamiać operacje wymagające rootowania wcześniej w kompilacji obrazu. Instrukcja apt install
w powyższym przykładzie ma uzasadnioną potrzebę rootowania. Jeśli instrukcja USER
zostałaby umieszczona nad nim, apt
zostałby uruchomiony jako demo-user
który nie posiadałby niezbędnych uprawnień. Ponieważ instrukcje Dockerfile dotyczą tylko kompilacji obrazów, a nie uruchomionych kontenerów, można bezpiecznie pozostawić zmianę użytkownika na później w pliku Dockerfile.
Zmiana użytkownika uruchamianego przez kontener może wymagać zaktualizowania uprawnień do plików i folderów, do których uzyskuje dostęp. Ustaw własność na dowolnych ścieżkach, które będą używane przez Twoją aplikację:
KOPIUJ Initial-config.yaml /data/config.yaml USER demo-user:demo-group URUCHOM chown demo-user:demo-group /data
W tym przykładzie katalog /data
musi należeć do demo-user
aby aplikacja mogła wprowadzać zmiany w swoim pliku konfiguracyjnym. Wcześniejsza instrukcja COPY
skopiuje plik jako root. Skrót jest dostępny za pomocą flagi --chown
z copy
:
KOPIUJ --chown=demo-user:demo-group Initial-config.yaml /data/config.yaml
Zmiana użytkownika podczas uruchamiania kontenera
Chociaż możesz łatwo zmienić użytkownika we własnych plikach Docker, wiele aplikacji innych firm nadal działa jako root. Ryzyko związane z ich użyciem można zmniejszyć, ustawiając flagę --user
przy każdym wywołaniu docker run
. Zastępuje to użytkownika ustawionego w pliku Dockerfile obrazu.
$ docker run -d --user demo-user:demo-group obraz-demo:ostatni $ docker run -d --user demo-user demo-image: najnowszy $ docker run -d --user 950:950 obraz demonstracyjny: najnowszy
Flaga --user
uruchamia proces kontenera jako określony użytkownik. Jest mniej bezpieczna niż instrukcja Dockerfile USER
, ponieważ trzeba ją zastosować indywidualnie do każdego polecenia docker run
dockera. Lepszą opcją w przypadku regularnie używanych obrazów jest utworzenie własnego obrazu pochodnego, który może założyć nowe konto użytkownika:
OD obrazu, który działa jako root: najnowszy USER demo-użytkownik
$ kompilacja dockera . -t obraz-który-teraz-działa-jako-nie root:najnowszy
Zmiana użytkownika obrazu innej firmy może spowodować problemy: jeśli kontener oczekuje na uruchomienie jako root lub potrzebuje dostępu do ścieżek systemu plików należących do roota, podczas korzystania z aplikacji pojawią się błędy. Możesz spróbować ręcznie zmienić uprawnienia na ścieżkach, które powodują problemy. Alternatywnie sprawdź, czy dostawca ma obsługiwaną metodę uruchamiania aplikacji z kontem użytkownika bez uprawnień.
Obsługa aplikacji, które muszą działać jako root
Przestrzenie nazw użytkowników to technika radzenia sobie z aplikacjami, które wymagają pewnych uprawnień administratora. Pozwala mapować root wewnątrz kontenera na użytkownika innego niż root na twoim hoście. Symulowany root w kontenerze ma uprawnienia, których potrzebuje, ale wybicie nie zapewni hostowi dostępu do roota.
Zmiana mapowania przestrzeni nazw jest aktywowana poprzez dodanie pola userns-remap
do pliku /etc/docker/daemon.json
:
{ "userns-remap": "domyślny" }
Użycie default
jako wartości dla userns-remap
nakazuje Dockerowi automatyczne utworzenie nowego użytkownika na twoim hoście o nazwie dockremap
. Root w kontenerach zostanie zmapowany z powrotem do mapy dockremap
na Twoim hoście. Możesz opcjonalnie określić istniejącego użytkownika i grupę, używając kombinacji UID/GID lub nazwy użytkownika/nazwy grupy:
{ "userns-remap": "użytkownik demo" }
Po zastosowaniu zmiany uruchom ponownie demona Docker:
$ restart dokera usługi sudo
Jeśli używasz nsuser-remap: default
, użytkownik dockremap
powinien teraz istnieć na twoim hoście:
$ ID mapy dok uid=140(dockremap) gid=119(dockremap) groups=119(dockremap)
Użytkownik powinien również pojawić się w /etc/subuid
i /etc/subgid
identyfikatorów podrzędnych:
$ mapa doków: 231500:65535
Użytkownikowi przydzielono zakres 65 535 identyfikatorów podrzędnych, począwszy od 231500. W przestrzeni nazw użytkownika identyfikator 231500
jest mapowany na 0
, co czyni go użytkownikiem root w Twoich kontenerach. Będąc identyfikatorem UID o wysokim numerze, 231500 nie ma żadnych uprawnień na hoście, więc ataki przełamywania kontenerów nie będą w stanie zadać tak dużych obrażeń.
Wszystkie uruchomione kontenery będą uruchamiane przy użyciu zmienionej przestrzeni nazw użytkownika, chyba że zrezygnujesz z docker run --userns=host
. Mechanizm działa poprzez tworzenie katalogów z przestrzenią nazw w /var/lib/docker
, które są własnością podrzędnego UID i GID użytkownika z przestrzenią nazw:
$ sudo ls -l /var/lib/docker/231500.231500 łącznie 14 drwx------ 5 231500 231500 13 lipca 22 19:00 aufs drwx------ 3 231500 231500 13 lipca 22 19:00 kontenerów ...
Przestrzenie nazw użytkowników to skuteczny sposób na zwiększenie izolacji kontenerów, unikanie wybić i zachowanie zgodności z aplikacjami, które wymagają uprawnień administratora. Istnieją jednak pewne kompromisy: funkcja działa najlepiej na świeżej instancji platformy Docker, woluminy zamontowane z hosta muszą mieć dostosowane uprawnienia, a niektóre zewnętrzne sterowniki pamięci masowej w ogóle nie obsługują mapowania użytkowników. Przed przyjęciem tej opcji należy zapoznać się z dokumentacją.
Streszczenie
Uruchamianie aplikacji kontenerowych jako root stanowi zagrożenie bezpieczeństwa. Chociaż łatwo przeoczyć, izolacja zapewniana przez kontenery nie jest wystarczająco silna, aby w pełni oddzielić użytkowników jądra od użytkowników kontenerów. Root w kontenerze jest taki sam jak root na twoim hoście, więc udany kompromis może zapewnić kontrolę nad twoją maszyną.
Jako autor obrazu powinieneś dołączyć instrukcję USER
w pliku Dockerfile, aby aplikacja działała bez uprawnień administratora. Użytkownicy obrazu mogą to zmienić za pomocą docker run --user
, aby przypisać określony UID i GID. Pomaga to złagodzić przypadki, w których obraz zwykle używa roota.
Możesz jeszcze bardziej zwiększyć bezpieczeństwo, usuwając wszystkie możliwości z kontenera przy użyciu --cap-drop=ALL
, a następnie umieszczając na białej liście te, które są wymagane za pomocą flag --cap-add
. Połączenie tych technik spowoduje uruchomienie aplikacji jako użytkownik inny niż root z minimalnym zestawem wymaganych uprawnień, poprawiając stan bezpieczeństwa.