Bezpieczeństwo kontenerów: Czy izolacja jest absolutna? (Docker vs. Rootless Podman) | INTROSERV

Bezpieczeństwo kontenerów: Czy izolacja jest absolutna? (Docker vs. Rootless Podman)

by Nataliya Oteir
Bezpieczeństwo kontenerów: Czy izolacja jest absolutna? (Docker vs. Rootless Podman)
star 5
0
Czytaj 12 min.

Podstawowe ograniczenia izolacji kontenerów

Konteneryzacja stała się dominującą metodą pakowania i dostarczania aplikacji w architekturach chmurowych i mikrousługowych. Kontenery umożliwiają łączenie kodu, bibliotek i zależności, zapewniając wysoką przenośność i wydajność operacyjną.

Jednak masowa migracja krytycznych obciążeń do kontenerów sprawia, że odporność mechanizmów izolacji staje się fundamentalnym problemem. Badania i ankiety przeprowadzane wśród zespołów DevOps i bezpieczeństwa konsekwentnie pokazują, że bezpieczeństwo kontenerów pozostaje jednym z największych zmartwień: luki w zabezpieczeniach jądra i środowiska wykonawczego, wraz z błędami konfiguracji, regularnie prowadzą do rzeczywistych naruszeń izolacji.

Kluczowe pytanie brzmi: czy izolacja kontenerów jest absolutna?

Odpowiedź brzmi nie, a przyczyna leży w ich architekturze. W tym artykule zagłębimy się w to pytanie i zbadamy dostępne środki ograniczania ryzyka podatności na zagrożenia.

Kontenery a maszyny wirtualne: współdzielone jądro

Maszyna wirtualna (VM):

  • Każda maszyna wirtualna uruchamia własne jądro systemu operacyjnego, całkowicie oddzielone od hosta.

  • Izolacja jest wymuszana przez hiperwizor (KVM, Xen, ESXi itp.).

  • Atak zazwyczaj musi być wymierzony w hiperwizor, co znacznie zawęża wektory ataku.

Kontenery:

  • Kontener to proces odizolowany przy użyciu prymitywów jądra Linux (przestrzenie nazw, grupy cgroup itp.).

  • Kontener zawiera tylko przestrzeń użytkownika (biblioteki, środowisko uruchomieniowe, aplikacje), ale współdzieli jedno jądro z hostem i innymi kontenerami.

  • Każda krytyczna luka w jądrze automatycznie staje się potencjalnym wektorem ataku dla wszystkich kontenerów w węźle.

Wybór architektury współdzielonego jądra jest tym, co sprawia, że izolacja kontenerów jest zasadniczo nieabsolutna: udane wykorzystanie luki w jądrze pozwala atakującemu ominąć granice dowolnej przestrzeni nazw.

Rola przestrzeni nazw i grup C w tworzeniu izolacji

Podstawą izolacji kontenerów w systemie Linux są przestrzenie nazw i grupy Cgroups.

  • Przestrzenie nazw - izolacja widoku systemu: PID, Mount, Network, User, IPC, UTS i innych. Procesy "widzą" tylko swoją własną przestrzeń: swój system plików, swój PID, swoją nazwę hosta i swoją sieć.

  • Cgroups - kontrola i ograniczanie zasobów: CPU, pamięć, I/O, liczba procesów itp.

Przestrzenie nazw tworzą iluzję oddzielnego systemu, a grupy C zapobiegają przejmowaniu zasobów hosta przez jeden kontener. Należy jednak pamiętać, że przestrzenie nazw są mechanizmem izolacji, a nie pełnoprawnym mechanizmem zabezpieczającym przed celowym obchodzeniem barier. Nie zapobiegają one wykorzystywaniu luk w jądrze, nie rozwiązują problemów z nadmiernymi uprawnieniami roota lub uprzywilejowanymi kontenerami, nie filtrują wywołań systemowych i nie zarządzają zasadami dostępu.

Dlatego przestrzenie nazw i grupy są jedynie warstwą podstawową, którą należy wzmocnić:

  1. filtrowanie wywołań systemowych (Seccomp)

  2. polityki MAC (AppArmor/SELinux)

  3. Ograniczenia możliwości

  4. Idealnie, przestrzenie nazw użytkowników + tryb rootless

Bezpieczeństwo platformy kontenerowej: krytyczne zagrożenia i wektory ataku

Powierzchnia ataku platformy kontenerowej jest wielowarstwowa. Można zidentyfikować następujące główne powierzchnie:

  • Runtime i jądro (runc, containerd, CRI-O, jądro Linux).

  • Łańcuch dostarczania obrazów.

  • Konfiguracja kontenera i orkiestratora.

  • Chmura i infrastruktura (IAM, API, pamięć masowa, sieć).

Przegląd wektorów ataku i krytycznych luk w zabezpieczeniach: Ucieczka z kontenera

Typowe wektory w środowisku kontenerowym obejmują: wykorzystanie CVE w jądrze systemu Linux lub środowisku uruchomieniowym kontenera; korzystanie z niezabezpieczonych obrazów (przestarzałe pakiety, zestawy exploitów); błędy konfiguracji w Kubernetes/Docker (nadmierne uprawnienia, montowanie systemu plików hosta, stos sieciowy hosta); oraz naruszenie rejestru i CI/CD.

Ważne jest, aby zrozumieć, że Container Escape jest często kombinacją różnych czynników:

Podatność jądra / środowiska wykonawczego + słaba konfiguracja (uruchamianie jako root, --privileged, montowanie systemu plików hosta, brak MAC/Seccomp).

Podatności w łańcuchu dostaw

Łańcuch dostaw obrazów kontenerów jest jednym z głównych zagrożeń, ponieważ obrazy bazowe z publicznych rejestrów często zawierają znane CVE. Zależności (moduły pip/npm/gem/go) są pobierane tranzytowo i nie zawsze są kontrolowane. Co najniebezpieczniejsze, złośliwe oprogramowanie może być "uśpione" i ujawniać się dopiero w czasie wykonywania.

Dlatego też następujące najlepsze praktyki są obowiązkowe w produkcji:

  • Skanowanie obrazów w poszukiwaniu CVE przy użyciu narzędzi takich jak Trivy, Clair, Grype itp.

  • Korzystanie z rejestrów świadomych zasad z egzekwowaniem, takich jak Harbor, Quay lub GHCR.

  • Podpisywanie i weryfikacja obrazów przed wdrożeniem.

Błędy konfiguracji i kontenery uprzywilejowane

Najczęstszym błędem, który szeroko otwiera drzwi do luk w zabezpieczeniach, jest uruchamianie procesów wewnątrz kontenera jako root! Jeśli aplikacja w kontenerze jest uruchamiana z prawami superużytkownika, po naruszeniu kontenera atakujący uzyskuje roota wewnątrz kontenera. Udana ucieczka na zewnątrz kontenera znacznie upraszcza eskalację do roota hosta.

Zakaz uruchamiania aplikacji jako root i wykorzystywanie nieuprzywilejowanych UID/GID jest podstawową zasadą prawidłowego zabezpieczenia.

Uprzywilejowane kontenery używające flagi --privileged praktycznie wyłączają kluczowe mechanizmy izolacji, w szczególności niektóre grupy C, AppArmor/SELinux i ograniczenia Seccomp. Daje to kontenerowi bezpośredni dostęp do urządzeń hosta i pseudosystemów plików (/proc, /sys, /dev itp.). Z uprzywilejowanego kontenera można łatwo montować dyski hosta i modyfikować system plików i konfiguracje.

Zasadniczo uprzywilejowany kontener jest odpowiednikiem celowej eskalacji uprawnień. Pamiętaj, że jest to dopuszczalne tylko w rzadkich, dobrze odizolowanych scenariuszach, a na pewno nie w środowisku multi-tenant.

Istnieją również "ciche" błędy konfiguracji, które mogą sprawić, że środowisko kontenera będzie wyjątkowo podatne na ataki, nawet bez użycia flagi --privileged. Najbardziej niebezpieczne z nich to:

  • Montowanie hostPath do wrażliwych katalogów hosta, takich jak /etc lub /var/run/docker.sock.

  • Przyznawanie niepotrzebnych Capabilities, na przykład CAP_SYS_ADMIN, który praktycznie przyznaje prawa roota na hoście.

  • Nieuzasadnione użycie trybów hostNetwork lub hostPID.

Te pozornie drobne ustawienia mogą pozwolić atakującemu na ucieczkę z kontenera i przejęcie kontroli nad jądrem lub całym systemem hosta.

Porównanie architektury: Docker vs. Podman

Różnice architektoniczne między Dockerem a Podmanem bezpośrednio wpływają na model zagrożeń. Docker, ze swoim demonem o wysokich uprawnieniach, stanowi główne zagrożenie: pojedynczy punkt awarii.

Docker i tryb rootful

W klasycznej, czyli standardowej architekturze Dockera, interfejs Docker CLI komunikuje się z demonem dockerd za pośrednictwem gniazda /var/run/docker.sock lub protokołu TCP. Demon dockerd działa jako użytkownik root i wykonuje podstawowe operacje:

  • Tworzenie/usuwanie kontenerów

  • Tworzenie obrazów

  • Zarządzanie sieciami/wolumenami

  • Interakcja z rejestrami

Wynika z tego, że bezpośredni dostęp do interfejsu API Docker jest równoważny niemal pełnemu dostępowi roota do hosta - umożliwiając atakującemu zamontowanie systemu plików, uruchomienie uprzywilejowanych kontenerów itp. W tym scenariuszu demon staje się pojedynczym punktem awarii - jeśli zostanie naruszony, atakujący uzyska dostęp do hosta.

Dlatego Docker wymaga ścisłej kontroli dostępu do gniazda, obowiązkowego włączenia MAC i Seccomp oraz ograniczenia możliwości. Co najważniejsze, niezbędne jest zminimalizowanie liczby użytkowników i usług z dostępem do interfejsu API Docker.

Podman bez demonów: natywne podejście linuksowe

Podman został opracowany przez Red Hat i społeczność jako bezpieczniejsza, "natywna" alternatywa dla Linuksa. Pierwotnie został zaprojektowany z architekturą bezdemonową, co oznacza, że nie ma trwałego, scentralizowanego demona. Zamiast tego kontenery są procesami potomnymi użytkownika, który uruchomił polecenie. Podstawą jest głęboka integracja z systemd, gdzie jednostki i usługi są tworzone bezpośrednio.

Eliminuje to pojedynczy punkt awarii prezentowany przez głównego demona i lepiej pasuje do tradycyjnego modelu uniksowego: "ktokolwiek uruchomił proces, jest jego właścicielem".

Tryb bez roota: Przestrzenie nazw użytkowników jako główna bariera bezpieczeństwa

Tryb rootless jest zasadniczo logiczną odpowiedzią na podstawowe zagrożenie: "Co jeśli kontener się wyłamie?".

Rola przestrzeni nazw użytkownika i ograniczanie szkód

Przestrzenie nazw użytkowników izolują UID/GID i umożliwiają ponowne mapowanie UID. Na przykład, jeśli proces wewnątrz kontenera ma UID 0 (root), ten sam proces jest mapowany na nieuprzywilejowany UID z zakresu subuid/subgid na hoście.

Dlatego też, nawet jeśli atakujący wewnątrz kontenera ma uprawnienia roota i uda mu się wykorzystać lukę w zabezpieczeniach runtime/jądra, aby uciec do poziomu hosta, nadal będzie działał jako nieuprzywilejowany użytkownik na hoście.

Wiele łańcuchów exploitów, w tym runc-escape, zostaje w ten sposób przerwanych lub ma znacznie ograniczony wpływ. Wynika to z faktu, że atakujący nie może nadpisać binariów/konfiguracji należących do roota, nie może montować systemów plików ani zarządzać urządzeniami bez uprawnień, a zasady MAC nadal działają również na hoście.

Rootless Podman: Ograniczenia i stos sieciowy

Podman został zaprojektowany od samego początku z naciskiem na operacje bez roota. Kontenery są tworzone i zarządzane przez nieuprzywilejowanego użytkownika, przestrzenie nazw użytkowników są domyślnie włączone, a SELinux/AppArmor i Cgroups są używane w możliwym zakresie bez dostępu roota.

Istnieją jednak pewne kompromisy w tym schemacie. Gdy kontener bez roota działa w zakresie subuid/subgid, możliwe są błędy mapowania, jeśli obraz zawiera pliki z wartościami UID/GID, które wykraczają poza ten zakres.

Inną pośrednią wadą jest to, że nieuprzywilejowany użytkownik nie może swobodnie konfigurować sieciowych przestrzeni nazw. Od początku 2025 roku Podman używa makaronu stosu przestrzeni użytkownika jako zamiennika dla slirp4netns. Wtyczka ta działa w całości w przestrzeni użytkownika, ale dzięki interfejsowi tap i zerowemu kopiowaniu splice zapewnia niemal natywną wydajność sieci. Niemniej jednak, spowolnienia wydajności są nadal możliwe i są zdecydowanie gwarantowane, jeśli użytkownicy nadal używają slirp4netns.

Rootless Docker: implementacja i wymagania

Docker obsługuje również pełnoprawny tryb rootless, w którym demon dockerd i kontenery są uruchamiane w przestrzeni nazw użytkownika bez uprawnień użytkownika root hosta. Co ważne, różni się to od starszej funkcji userns-remap, w której sam demon pozostawał uprzywilejowany.

Z punktu widzenia bezpieczeństwa gwarantuje to, że naruszenie kontenera nie spowoduje automatycznej eskalacji do poziomu użytkownika root hosta. W przypadku udanego ataku na dockerd w trybie rootless, dostęp do zasobów uzyska tylko nieuprzywilejowany użytkownik, a nie cały system.

Wybór pomiędzy trybami rootful i rootless jest przede wszystkim równowagą pomiędzy maksymalizacją wydajności i maksymalnym ograniczeniem potencjalnych szkód w przypadku naruszenia.

Wnioski i zalecenia dotyczące zabezpieczeń

Analiza potwierdza, że izolacja kontenerów nie jest absolutna ze względu na ich architekturę. Ponieważ kontenery współdzielą jądro systemu hosta, luki w zabezpieczeniach na poziomie jądra lub środowiska uruchomieniowego mogą z definicji "widzieć" przestrzenie nazw, naruszając oczekiwane granice bezpieczeństwa.

W praktyce większość udanych ataków wiąże się z połączeniem znanej podatności (kernel/runc) i słabej konfiguracji (root, --privileged, hostPath).

Niezawodny model bezpieczeństwa kontenera musi być zbudowany jako system wielowarstwowy:

Warstwa 1 - Segmentacja: (przestrzenie nazw, cgroups)

Warstwa 2 - Polityki i filtrowanie: (Seccomp, MAC, Capabilities)

Warstwa 3 - Architektoniczne ograniczenie uprawnień: (poprzez tryb rootless i przestrzenie nazw użytkowników)

Lista kontrolna: wzmocnienie hosta dla kontenerów Docker i Podman

Domyślnie rootless

Rozważ Podman lub Docker w trybie rootless jako domyślny model dla wewnętrznych i wielodostępnych obciążeń.

Hartowanie i łatanie jądra

Natychmiast aktualizuj jądro (Dirty COW, Dirty Pipe i podobne CVE prawie zawsze są już załatane łatkami). Używaj dystrybucji z dobrą historią łatek bezpieczeństwa (RHEL, OpenSUSE, Ubuntu LTS itp.).

Przyjmowanie wyspecjalizowanych, niezmiennych dystrybucji systemu operacyjnego

Aby zwiększyć bezpieczeństwo środowiska kontenerowego, należy korzystać z niezmiennych dystrybucji systemu operacyjnego, takich jak openSUSE MicroOS lub Flatcar Linux. Ich główny system plików jest domyślnie tylko do odczytu, co znacznie zmniejsza powierzchnię ataku. Kluczowym mechanizmem są aktualizacje atomowe: tworzony jest nowy obraz systemu operacyjnego, a aktualizacja jest stosowana całkowicie lub całkowicie wycofywana, co zapobiega uszkodzeniu systemu i przyspiesza odzyskiwanie.

Zasada najmniejszych uprawnień

Nigdy nie używaj flagi --privileged w środowisku produkcyjnym, z wyjątkiem wysoce wyspecjalizowanych, odizolowanych środowisk. Unikaj uruchamiania aplikacji wewnątrz kontenerów jako użytkownik root i używaj systemu plików tylko do odczytu, minimalnego zestawu możliwości i ścisłych profili Seccomp.

Zasady MAC i Seccomp

Włącz i skonfiguruj SELinux\AppArmor dla kontenerów. Używaj profili Seccomp, najlepiej niestandardowych, opartych na rzeczywistych wywołaniach systemowych aplikacji, a nie tylko domyślnych ustawieniach Docker.

Bezpieczeństwo łańcucha dostaw

Wdrożenie skanowania obrazów kontenerów. Ogranicz źródła obrazów bazowych do oficjalnych lub wewnętrznych rejestrów i włącz podpisywanie i weryfikację obrazów przed wdrożeniem.

Monitorowanie środowiska uruchomieniowego

Stosuj narzędzia do wykrywania anomalii i IDS/EDR kontenerów (Falco, Sysdig Secure lub Aqua Security), które mogą wykrywać próby ucieczki kontenera i monitorować wykonywanie złośliwych poleceń. Śledzenie nietypowego ruchu sieciowego, nieoczekiwanych wywołań systemowych i dostępu do poufnych plików.

Przyszłość izolacji: Kata Containers, gVisor i Micro-VMs

Tryb rootless znacznie zmniejsza ryzyko całkowitego naruszenia bezpieczeństwa hosta, ale nie rozwiązuje wszystkiego, ponieważ zależności od jądra hosta pozostają, a niektóre klasy ataków nie są eliminowane.

Dlatego też podejścia hybrydowe zyskują na popularności w przypadku krytycznych obciążeń:

  • Kontenery Kata: Każdy pod lub kontener jest uruchamiany wewnątrz lekkiej mikro-VM z oddzielnym jądrem, łącząc zalety maszyn wirtualnych i kontenerów.
  • gVisor: Jądro sandbox napisane w języku Go, które działa jako warstwa pośrednia między aplikacją a prawdziwym jądrem Linux.

Rozwiązania te zmniejszają zależność od współdzielonego jądra i przybliżają nas do modelu izolacji maszyn wirtualnych, zachowując deklaratywny charakter i wygodę orkiestratorów kontenerów.

Przekształć wskazówki zawarte w tym poście w rzeczywiste zabezpieczenia podczas następnego wdrożenia.

Kup VPS lub serwer dedykowany i już dziś zacznij konfigurować bezpieczną platformę kontenerową.

Nowe posty:

Docker vs. Podman: Kompletny przewodnik po bezdemonowej konteneryzacji

    Nowe posty

    VAT

    • Other

      Other

      0%
    • austria

      Austria

      20%
    • Belgium

      Belgium

      21%
    • Bulgaria

      Bulgaria

      20%
    • Croatia

      Croatia

      25%
    • Cyprus

      Cyprus

      19%
    • Czech Republic

      Czech Republic

      21%
    • Denmark

      Denmark

      25%
    • Estonia

      Estonia

      22%
    • France

      France

      20%
    • Finland

      Finland

      24%
    • Germany

      Germany

      19%
    • Greece

      Greece

      24%
    • Hungary

      Hungary

      27%
    • Ireland

      Ireland

      23%
    • Italy

      Italy

      22%
    • Latvia

      Latvia

      21%
    • Lithuania

      Lithuania

      21%
    • Luxembourg

      Luxembourg

      17%
    • Malta

      Malta

      18%
    • Netherlands

      Netherlands

      21%
    • Poland

      Poland

      23%
    • Portugal

      Portugal

      23%
    • Romania

      Romania

      19%
    • Slovakia

      Slovakia

      20%
    • Slovenia

      Slovenia

      %
    • Spain

      Spain

      21%
    • Sweden

      Sweden

      25%
    • USA

      USA

      0%
    european
    states
    • Other
    • canada
    • poland
    • european-union
    • france
    • germany
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria
    • austria