Docker Security
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools. Get Access Today:
Silnik Docker wykorzystuje Namespaces i Cgroups jądra Linux do izolacji kontenerów, oferując podstawową warstwę zabezpieczeń. Dodatkową ochronę zapewniają Capabilities dropping, Seccomp oraz SELinux/AppArmor, co zwiększa izolację kontenerów. Plugin autoryzacji może dodatkowo ograniczyć działania użytkowników.
Silnik Docker można uzyskać lokalnie za pomocą gniazda Unix lub zdalnie przy użyciu HTTP. W przypadku dostępu zdalnego istotne jest stosowanie HTTPS i TLS, aby zapewnić poufność, integralność i uwierzytelnienie.
Silnik Docker, domyślnie, nasłuchuje na gnieździe Unix pod adresem unix:///var/run/docker.sock
. W systemach Ubuntu opcje uruchamiania Dockera są definiowane w /etc/default/docker
. Aby umożliwić zdalny dostęp do API Dockera i klienta, należy udostępnić demon Dockera przez gniazdo HTTP, dodając następujące ustawienia:
Jednakże, udostępnianie demona Docker przez HTTP nie jest zalecane z powodu obaw dotyczących bezpieczeństwa. Zaleca się zabezpieczenie połączeń za pomocą HTTPS. Istnieją dwa główne podejścia do zabezpieczenia połączenia:
Klient weryfikuje tożsamość serwera.
Zarówno klient, jak i serwer wzajemnie uwierzytelniają swoją tożsamość.
Certyfikaty są wykorzystywane do potwierdzenia tożsamości serwera. Aby uzyskać szczegółowe przykłady obu metod, zapoznaj się z tym przewodnikiem.
Obrazy kontenerów mogą być przechowywane w prywatnych lub publicznych repozytoriach. Docker oferuje kilka opcji przechowywania obrazów kontenerów:
Docker Hub: Publiczna usługa rejestru od Docker.
Docker Registry: Projekt open-source, który pozwala użytkownikom hostować własny rejestr.
Docker Trusted Registry: Komercyjna oferta rejestru Docker, z uwierzytelnianiem użytkowników opartym na rolach i integracją z usługami katalogowymi LDAP.
Kontenery mogą mieć luki w zabezpieczeniach zarówno z powodu obrazu bazowego, jak i z powodu oprogramowania zainstalowanego na obrazie bazowym. Docker pracuje nad projektem o nazwie Nautilus, który przeprowadza skanowanie bezpieczeństwa kontenerów i wymienia luki. Nautilus działa, porównując każdą warstwę obrazu kontenera z repozytorium luk, aby zidentyfikować luki w zabezpieczeniach.
Aby uzyskać więcej informacji, przeczytaj to.
docker scan
Polecenie docker scan
pozwala na skanowanie istniejących obrazów Docker za pomocą nazwy lub identyfikatora obrazu. Na przykład, uruchom następujące polecenie, aby przeskanować obraz hello-world:
Podpisywanie obrazów Docker zapewnia bezpieczeństwo i integralność obrazów używanych w kontenerach. Oto skrócone wyjaśnienie:
Aby aktywować zaufanie do treści Docker, ustaw export DOCKER_CONTENT_TRUST=1
. Ta funkcja jest domyślnie wyłączona w wersji Docker 1.10 i nowszych.
Po włączeniu tej funkcji można pobierać tylko podpisane obrazy. Początkowe przesyłanie obrazu wymaga ustawienia haseł dla kluczy głównych i tagujących, a Docker obsługuje również Yubikey dla zwiększonego bezpieczeństwa. Więcej szczegółów można znaleźć tutaj.
Próba pobrania niepodpisanego obrazu z włączonym zaufaniem do treści skutkuje błędem "No trust data for latest".
Przy przesyłaniu obrazów po pierwszym, Docker prosi o hasło klucza repozytorium, aby podpisać obraz.
Aby wykonać kopię zapasową swoich prywatnych kluczy, użyj polecenia:
When switching Docker hosts, it's necessary to move the root and repository keys to maintain operations.
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools. Get Access Today:
Namespaces to funkcja jądra Linux, która dzieli zasoby jądra w taki sposób, że jeden zestaw procesów widzi jeden zestaw zasobów, podczas gdy inny zestaw procesów widzi inny zestaw zasobów. Funkcja działa poprzez posiadanie tego samego namespace dla zestawu zasobów i procesów, ale te namespace odnoszą się do odrębnych zasobów. Zasoby mogą istnieć w wielu przestrzeniach.
Docker wykorzystuje następujące Namespaces jądra Linux do osiągnięcia izolacji kontenerów:
pid namespace
mount namespace
network namespace
ipc namespace
UTS namespace
Aby uzyskać więcej informacji o namespaces, sprawdź następującą stronę:
NamespacesFunkcja jądra Linux cgroups zapewnia możliwość ograniczenia zasobów, takich jak cpu, pamięć, io, przepustowość sieci wśród zestawu procesów. Docker pozwala na tworzenie kontenerów z wykorzystaniem funkcji cgroup, co umożliwia kontrolę zasobów dla konkretnego kontenera. Poniżej znajduje się kontener utworzony z ograniczoną pamięcią przestrzeni użytkownika do 500m, pamięcią jądra ograniczoną do 50m, udziałem CPU do 512, blkiowe ciężar do 400. Udział CPU to wskaźnik, który kontroluje wykorzystanie CPU przez kontener. Ma domyślną wartość 1024 i zakres od 0 do 1024. Jeśli trzy kontenery mają ten sam udział CPU wynoszący 1024, każdy kontener może zająć do 33% CPU w przypadku kontestacji zasobów CPU. blkio-weight to wskaźnik, który kontroluje IO kontenera. Ma domyślną wartość 500 i zakres od 10 do 1000.
Aby uzyskać cgroup kontenera, możesz zrobić:
For more information check:
CGroupsCapabilities allow finer control for the capabilities that can be allowed for root user. Docker uses the Linux kernel capability feature to limit the operations that can be done inside a Container irrespective of the type of user.
When a docker container is run, the process drops sensitive capabilities that the process could use to escape from the isolation. This try to assure that the process won't be able to perform sensitive actions and escape:
Linux CapabilitiesThis is a security feature that allows Docker to limit the syscalls that can be used inside the container:
SeccompAppArmor is a kernel enhancement to confine containers to a limited set of resources with per-program profiles.:
AppArmorSystem etykietowania: SELinux przypisuje unikalną etykietę do każdego procesu i obiektu systemu plików.
Egzekwowanie polityki: Egzekwuje polityki bezpieczeństwa, które definiują, jakie działania etykieta procesu może wykonywać na innych etykietach w systemie.
Etykiety procesów kontenerów: Gdy silniki kontenerów inicjują procesy kontenerów, zazwyczaj przypisywana jest im ograniczona etykieta SELinux, zwykle container_t
.
Etykietowanie plików w kontenerach: Pliki w kontenerze są zazwyczaj etykietowane jako container_file_t
.
Reguły polityki: Polityka SELinux przede wszystkim zapewnia, że procesy z etykietą container_t
mogą wchodzić w interakcje (czytać, pisać, wykonywać) tylko z plikami oznaczonymi jako container_file_t
.
Ten mechanizm zapewnia, że nawet jeśli proces w kontenerze zostanie skompromitowany, jest ograniczony do interakcji tylko z obiektami, które mają odpowiadające etykiety, znacznie ograniczając potencjalne szkody wynikające z takich kompromisów.
SELinuxIn Docker, an authorization plugin plays a crucial role in security by deciding whether to allow or block requests to the Docker daemon. This decision is made by examining two key contexts:
Kontekst uwierzytelniania: To obejmuje szczegółowe informacje o użytkowniku, takie jak kim jest i jak się uwierzytelnił.
Kontekst polecenia: To obejmuje wszystkie istotne dane związane z wysyłanym żądaniem.
These contexts help ensure that only legitimate requests from authenticated users are processed, enhancing the security of Docker operations.
AuthZ& AuthN - Docker Access Authorization PluginIf you are not properly limiting the resources a container can use, a compromised container could DoS the host where it's running.
CPU DoS
Atak DoS na pasmo
Na następnej stronie możesz się dowiedzieć co oznacza flaga --privileged
:
Jeśli uruchamiasz kontener, w którym atakujący zdołał uzyskać dostęp jako użytkownik o niskich uprawnieniach. Jeśli masz źle skonfigurowany binarny plik suid, atakujący może go nadużyć i eskalować uprawnienia wewnątrz kontenera. Co może pozwolić mu na ucieczkę z niego.
Uruchomienie kontenera z włączoną opcją no-new-privileges
zapobiegnie tego rodzaju eskalacji uprawnień.
For more --security-opt
options check: https://docs.docker.com/engine/reference/run/#security-configuration
Konieczne jest unikanie osadzania sekretów bezpośrednio w obrazach Docker lub używania zmiennych środowiskowych, ponieważ te metody narażają Twoje wrażliwe informacje na dostęp dla każdego, kto ma dostęp do kontenera za pomocą poleceń takich jak docker inspect
lub exec
.
Wolumeny Docker są bezpieczniejszą alternatywą, zalecaną do uzyskiwania dostępu do wrażliwych informacji. Mogą być wykorzystywane jako tymczasowy system plików w pamięci, łagodząc ryzyko związane z docker inspect
i logowaniem. Jednak użytkownicy root i ci, którzy mają dostęp do exec
w kontenerze, mogą nadal uzyskać dostęp do sekretów.
Sekrety Docker oferują jeszcze bezpieczniejszą metodę obsługi wrażliwych informacji. W przypadku instancji wymagających sekretów podczas fazy budowy obrazu, BuildKit przedstawia efektywne rozwiązanie z obsługą sekretów w czasie budowy, zwiększając prędkość budowy i oferując dodatkowe funkcje.
Aby skorzystać z BuildKit, można go aktywować na trzy sposoby:
Poprzez zmienną środowiskową: export DOCKER_BUILDKIT=1
Poprzez prefiksowanie poleceń: DOCKER_BUILDKIT=1 docker build .
Poprzez włączenie go domyślnie w konfiguracji Docker: { "features": { "buildkit": true } }
, a następnie ponowne uruchomienie Dockera.
BuildKit pozwala na użycie sekretów w czasie budowy z opcją --secret
, zapewniając, że te sekrety nie są uwzględniane w pamięci podręcznej budowy obrazu ani w finalnym obrazie, używając polecenia takiego jak:
Dla sekretów potrzebnych w działającym kontenerze, Docker Compose i Kubernetes oferują solidne rozwiązania. Docker Compose wykorzystuje klucz secrets
w definicji usługi do określenia plików sekretów, jak pokazano w przykładzie docker-compose.yml
:
Ta konfiguracja umożliwia użycie sekretów podczas uruchamiania usług za pomocą Docker Compose.
W środowiskach Kubernetes sekrety są natywnie obsługiwane i mogą być zarządzane za pomocą narzędzi takich jak Helm-Secrets. Kontrola dostępu oparta na rolach (RBAC) w Kubernetes zwiększa bezpieczeństwo zarządzania sekretami, podobnie jak w Docker Enterprise.
gVisor to jądro aplikacji, napisane w Go, które implementuje znaczną część powierzchni systemu Linux. Zawiera runtime Open Container Initiative (OCI) o nazwie runsc
, który zapewnia granice izolacji między aplikacją a jądrem hosta. Runtime runsc
integruje się z Dockerem i Kubernetes, co ułatwia uruchamianie kontenerów w piaskownicy.
Kata Containers to społeczność open source, która pracuje nad budowaniem bezpiecznego runtime kontenerów z lekkimi maszynami wirtualnymi, które działają i zachowują się jak kontenery, ale zapewniają silniejszą izolację obciążenia roboczego przy użyciu technologii wirtualizacji sprzętowej jako drugiej warstwy obrony.
Nie używaj flagi --privileged
ani nie montuj gniazda Docker wewnątrz kontenera. Gniazdo Docker umożliwia uruchamianie kontenerów, więc jest to łatwy sposób na przejęcie pełnej kontroli nad hostem, na przykład uruchamiając inny kontener z flagą --privileged
.
Nie uruchamiaj jako root wewnątrz kontenera. Użyj innego użytkownika i przestrzeni nazw użytkowników. Root w kontenerze jest taki sam jak na hoście, chyba że jest przemapowany za pomocą przestrzeni nazw użytkowników. Jest on tylko lekko ograniczony przez, głównie, przestrzenie nazw Linuxa, możliwości i cgroups.
Zrzuć wszystkie możliwości (--cap-drop=all
) i włącz tylko te, które są wymagane (--cap-add=...
). Wiele obciążeń roboczych nie potrzebuje żadnych możliwości, a ich dodanie zwiększa zakres potencjalnego ataku.
Użyj opcji zabezpieczeń „no-new-privileges” aby zapobiec uzyskiwaniu przez procesy większych uprawnień, na przykład przez binaria suid.
Ogranicz zasoby dostępne dla kontenera. Limity zasobów mogą chronić maszynę przed atakami typu denial of service.
Używaj oficjalnych obrazów docker i wymagaj podpisów lub buduj własne na ich podstawie. Nie dziedzicz ani nie używaj obrazów z backdoorem. Przechowuj również klucze root, hasła w bezpiecznym miejscu. Docker planuje zarządzać kluczami za pomocą UCP.
Regularnie przebudowuj swoje obrazy, aby zastosować poprawki zabezpieczeń do hosta i obrazów.
Zarządzaj swoimi sekretami mądrze, aby utrudnić atakującemu dostęp do nich.
Jeśli udostępniasz demona docker, użyj HTTPS z uwierzytelnianiem klienta i serwera.
W swoim Dockerfile, preferuj COPY zamiast ADD. ADD automatycznie wyodrębnia pliki skompresowane i może kopiować pliki z adresów URL. COPY nie ma tych możliwości. Kiedy to możliwe, unikaj używania ADD, aby nie być podatnym na ataki przez zdalne adresy URL i pliki Zip.
Miej osobne kontenery dla każdego mikroserwisu
Nie umieszczaj ssh wewnątrz kontenera, „docker exec” może być używane do ssh do kontenera.
Miej mniejsze obrazy kontenerów
Jeśli jesteś wewnątrz kontenera docker lub masz dostęp do użytkownika w grupie docker, możesz spróbować uciec i eskalować uprawnienia:
Docker Breakout / Privilege EscalationJeśli masz dostęp do gniazda docker lub masz dostęp do użytkownika w grupie docker, ale twoje działania są ograniczane przez wtyczkę uwierzytelniania docker, sprawdź, czy możesz to obejść:
AuthZ& AuthN - Docker Access Authorization PluginNarzędzie docker-bench-security to skrypt, który sprawdza dziesiątki powszechnych najlepszych praktyk dotyczących wdrażania kontenerów Docker w produkcji. Testy są w pełni zautomatyzowane i oparte na CIS Docker Benchmark v1.3.1. Musisz uruchomić narzędzie z hosta uruchamiającego dockera lub z kontenera z wystarczającymi uprawnieniami. Dowiedz się jak to uruchomić w README: https://github.com/docker/docker-bench-security.
Użyj Trickest, aby łatwo budować i automatyzować przepływy pracy zasilane przez najbardziej zaawansowane narzędzia społeczności. Uzyskaj dostęp już dziś:
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)