Blog

Obrana od bijega iz kontejnera: Praktični vodič za Docker izolaciju za višekorisničko hostiranje

Saznajte kako zaštititi Docker kontejnere od ranjivosti bijega i kvarova izolacije u višekorisničkim okruženjima s konkretnim koracima i primjerima.

Sažetak

Docker kontejneri dijele kernel hosta, što čini izolaciju kritičnom—posebno u višekorisničkom hostiranju gdje jedan bijeg iz kontejnera može ugroziti sve korisnike. Mnogi programeri pretpostavljaju da su kontejneri savršeno izolirani virtualni strojevi, ali stvarnost je drugačija. Ovaj članak objašnjava značajke Linux kernela iza Docker izolacije (namespaces, cgroups) i vektore napada koji ih ugrožavaju. Naučit ćete praktične korake za jačanje vaše Docker postavke: ograničavanje privilegija, korištenje sigurnog runtime okruženja, skeniranje slika i implementaciju mrežne segmentacije. Prateći primjer iz stvarnog svijeta pružatelja višekorisničkog WordPress hostinga, vidjet ćete kako primijeniti ove obrane. Također pokrivamo napomene poput kompromisa u performansama i korištenja seccomp/AppArmor. Cilj je dati vam robusnu strategiju izolacije koja sprječava bijeg iz kontejnera i čuva vaše korisnike na sigurnom.

Uvod

Ako vodite višekorisničku hosting platformu—bilo da se radi o dijeljenom WordPress hostingu, SaaS aplikaciji ili usluzi razvojnog okruženja—bijeg iz kontejnera je noćna mora. Ranljivost u kernelu ili pogrešna konfiguracija može dopustiti jednom korisniku da se izvuče iz svog kontejnera i pristupi podacima drugih korisnika ili samom hostu. Dockerova izolacija oslanja se na značajke Linux kernela poput namespaces i cgroups, ali zadane konfiguracije često nisu dovoljne za robusnu sigurnost. Ovaj članak će vas provesti kroz vektore napada i pružiti primjenjive korake za zaključavanje vaših Docker kontejnera, ilustrirano primjerom višekorisničkog WordPressa iz stvarnog svijeta. Za širi pogled na produkcijsku orkestraciju, pogledajte naš vodič o Orkestriranju produkcijski spremnih kontejneriziranih aplikacija.

Razumijevanje Docker izolacije

Docker kontejneri koriste Linux namespaces za pružanje izolacije na razini procesa: PID namespaces izoliraju stabla procesa, network namespaces odvajaju mrežna sučelja, mount namespaces izoliraju mountove datotečnog sustava, a user namespaces omogućuju mapiranje root kontejnera na neprivilegiranog korisnika hosta. Kontrolne grupe (cgroups) ograničavaju korištenje resursa poput CPU-a, memorije i I/O diska. Ove značajke zajedno stvaraju "sandbox" oko svakog kontejnera. Međutim, za razliku od virtualnog stroja koji pokreće zaseban kernel, kontejneri dijele kernel hosta. To znači da se ranjivost u kernelu (npr. CVE-2022-0492) može iskoristiti za bijeg iz izolacije namespacea kontejnera. Dodatno, pogrešne konfiguracije poput pokretanja kontejnera kao root unutar kontejnera, davanja kontejneru svih mogućnosti ili neispuštanja nepotrebnih Linux mogućnosti mogu proširiti površinu napada.

Vektori napada

Uobičajeni vektori napada uključuju:

  • Iskorištavanje kernela: Iskoristite grešku u kernelu hosta za dobivanje pristupa hostu.
  • Privilegirani kontejneri: Pokretanje s --privileged dodjeljuje sve mogućnosti i zaobilazi većinu izolacije.
  • Zlouporaba mogućnosti: Čak i bez punog privilegiranog načina rada, kontejner s opasnim mogućnostima poput CAP_SYS_ADMIN ili CAP_NET_ADMIN može montirati datotečne sustave ili manipulirati mrežnim postavkama.
  • Nesigurne prakse slika: Korištenje osnovnih slika s poznatim ranjivostima ili uključivanje nepotrebnih alata poput kompajlera ili interpretatora ljuske.
  • Zajednički mount namespaces: Montiranje host direktorija u kontejneri može dopustiti bijeg ako nije samo za čitanje.

Praktični sigurnosni koraci

1. Pokrenite kontejnere kao korisnik koji nije root

Prema zadanim postavkama, Docker pokreće kontejnere kao root unutar kontejnera. Ako napadač dobije root pristup unutar kontejnera, ima više poluga. Stvorite korisnika u svom Dockerfileu i koristite direktivu USER. Također, izbjegavajte korištenje --user zastavice u Docker Composeu za mapiranje na proizvoljnog korisnika hosta ako je moguće.

2. Ispustite sve mogućnosti i dodajte samo potrebne

Linux mogućnosti razbijaju privilegije superkorisnika na manje jedinice. U Docker Composeu koristite cap_drop: ALL, a zatim cap_add samo potrebne (npr. NET_BIND_SERVICE). Izbjegavajte opasne mogućnosti poput SYS_ADMIN, NET_ADMIN, SYS_PTRACE.

3. Koristite root datotečni sustav samo za čitanje

Postavite read_only: true u definiciji vašeg kontejnera. Ovo sprječava napadače da pišu u datotečni sustav kontejnera. Ako vaša aplikacija treba pisati privremene datoteke, montirajte tmpfs volumen na toj lokaciji.

4. Omogućite ponovno mapiranje korisničkih imena (User Namespace Remapping)

Ponovno mapiranje korisničkih imena mapira root korisnika kontejnera na neprivilegiranog korisnika hosta. Ovo dodaje sloj izolacije, jer čak i ako se root kontejnera izvuče, imat će privilegije ponovno mapiranog korisnika. Omogućite ga u /etc/docker/daemon.json s "userns-remap": "default". Imajte na umu da ovo može zakomplicirati dozvole za volume. Za više detalja, pogledajte Ovladavanje Docker izolacijom za sigurno i učinkovito web hostiranje.

5. Primijenite Seccomp i AppArmor/AppArmor profile

Seccomp ograničava sistemske pozive koje kontejner može napraviti. Docker pruža zadani seccomp profil koji blokira opasne sistemske pozive. Također možete izraditi prilagođene profile. Slično tome, AppArmor (ili SELinux) pruža obaveznu kontrolu pristupa. Koristite AppArmor za ograničavanje vašeg kontejnera na minimalan skup dopuštenih operacija. Sigurnosni profil može se postaviti putem security_opt u Docker Composeu.

6. Koristite minimalne osnovne slike i skenirajte na ranjivosti

Odaberite male slike poput Alpine ili Distroless koje imaju manju površinu napada. Redovito skenirajte slike alatima poput Docker Scout, Trivy ili Clair. Integrirajte skeniranje u svoj CI/CD pipeline kako biste spriječili implementaciju ranjivih slika.

7. Mrežna segmentacija s prilagođenim bridge mrežama

Stvorite zasebne bridge mreže za svakog korisnika ili sloj aplikacije. Ovo ograničava promet od istoka prema zapadu. U Docker Composeu, definirajte mreže i izolirajte usluge. Koristite internal: true ako usluga ne treba izlazni pristup internetu. Firewall pravila na hostu dodatno ograničavaju promet između kontejnera.

8. Ograničite resurse s cgroups

Postavite ograničenja CPU-a i memorije u Docker Composeu pomoću deploy.resources.limits. Ovo sprječava kompromitirani kontejner da pokrene napad iscrpljivanja resursa. Dodatno, postavite kernel_memory i memory_reservation za finije podešavanje.

Primjer iz stvarnog svijeta: Višekorisničko WordPress hostiranje s Docker Composeom

Razmotrite scenarij gdje hostirate više WordPress stranica za različite klijente, svaku u vlastitom Docker kontejneru. Nesigurna postavka bi mogla izgledati ovako:

version: '3'
services:
  wordpress:
    image: wordpress:latest
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - ./wp-content:/var/www/html/wp-content
  db:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_ROOT_PASSWORD: somewordpress
    volumes:
      - db_data:/var/lib/mysql
volumes:
  db_data:

Ova postavka je ranjiva: WordPress kontejner radi kao root iznutra, ima sve mogućnosti (budući da nijedna nije ispuštena), montira host direktorij s pristupom pisanju i ima neograničen mrežni pristup.

Sada ćemo je ojačati:

version: '3'
services:
  wordpress:
    image: wordpress:latest
    user: www-data
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    read_only: true
    tmpfs:
      - /var/www/html/wp-content/plugins
    security_opt:
      - seccomp=seccomp-profile.json
      - apparmor=wordpress-profile
    networks:
      - frontend
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wp-uploads:/var/www/html/wp-content/uploads
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 256M
  db:
    image: mysql:5.7
    user: mysql
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    networks:
      - backend
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_ROOT_PASSWORD: somewordpress
    volumes:
      - db_data:/var/lib/mysql
    deploy:
      resources:
        limits:
          cpus: '0.25'
          memory: 128M
networks:
  frontend:
    driver: bridge
    internal: false
  backend:
    driver: bridge
    internal: true
volumes:
  wp-uploads:
  db_data:

Ključna poboljšanja:

  • Oba kontejnera rade kao korisnici koji nisu root (www-data i mysql).
  • Sve mogućnosti su ispuštene, dodana je samo NET_BIND_SERVICE.
  • WordPress datotečni sustav je samo za čitanje osim tmpfs mounta i volumena za upload.
  • Primijenjeni su seccomp i AppArmor profili (morali biste osigurati prilagođene profile).
  • Odvojene mreže izoliraju web od baze podataka, s internom mrežom za bazu podataka.
  • Ograničenja resursa sprječavaju iscrpljivanje resursa.

Više o jačanju Docker-a specifičnom za WordPress, pogledajte Docker za WordPress: Zašto izolirani kontejneri mijenjaju sve.

Napomene

  • Ponovno mapiranje korisničkih imena (User Namespace Remapping): Iako moćno, narušava montiranje volumena jer ponovno mapirani UID hosta nije isti kao UID kontejnera. Možda ćete morati unaprijed stvoriti direktorije s ispravnim dozvolama ili koristiti Docker volumene s podrškom za ponovno mapiranje.
  • Seccomp/AppArmor profili: Prilagođeni profili zahtijevaju razumijevanje obrazaca sistemskih poziva i pristupa datotekama vaše aplikacije. Previše restriktivni profili mogu narušiti funkcionalnost. Testirajte temeljito.
  • Performanse: Dodatni sigurnosni slojevi poput seccomp i AppArmor imaju minimalan utjecaj, ali ograničenja resursa i datotečni sustavi samo za čitanje mogu utjecati na aplikacije koje intenzivno pišu.
  • Složenost orkestracije: U višekorisničkom okruženju, upravljanje Docker Compose datotekama po korisniku može postati nepraktično. Razmislite o korištenju alata za orkestraciju više razine poput Kubernetes, ali to uvodi vlastite sigurnosne razmatranja.

Zaključak

Bijeg iz kontejnera je stvarna prijetnja u višekorisničkom Docker hostiranju, ali se može spriječiti. Razumijevanjem mehanizama izolacije i primjenom obrane u dubinu—ispuštanjem mogućnosti, pokretanjem kao korisnik koji nije root, omogućavanjem korisničkih imena, seccomp, AppArmor, mrežnom segmentacijom i redovitim skeniranjem slika—možete drastično smanjiti rizik. Zapamtite da zadane postavke Dockera nisu spremne za produkciju za višekorisnička opterećenja. Implementirajte ove korake danas kako biste zaštitili svoje korisnike i svoju infrastrukturu. Za sveobuhvatan pregled najboljih praksi za sigurnost Dockera, pogledajte Osiguravanje vaših web aplikacija s Dockerom: Praktični vodič za izolaciju i najbolje prakse.

Sources (5)