Blog

Verdedigen tegen Container Escape: Een Praktische Gids voor Docker-isolatie voor Multi-Tenant Hosting

Leer hoe u Docker-containers beveiligt tegen escape-kwetsbaarheden en isolatiefouten in multi-tenant omgevingen met concrete stappen en voorbeelden.

Samenvatting

Docker-containers delen de host-kernel, waardoor isolatie cruciaal is—vooral in multi-tenant hosting waar een enkele container escape alle tenants kan compromitteren. Veel ontwikkelaars gaan ervan uit dat containers perfect geïsoleerde virtuele machines zijn, maar de realiteit is anders. Dit artikel legt de Linux-kernelfuncties achter Docker-isolatie (namespaces, cgroups) en de aanvalsvectoren die deze bedreigen uit. U leert praktische stappen om uw Docker-setup te versterken: privileges beperken, een veilige runtime gebruiken, images scannen en netwerksegmentatie implementeren. Door een real-world voorbeeld van een multi-tenant WordPress-hostingprovider te volgen, ziet u hoe u deze verdedigingen toepast. We behandelen ook kanttekeningen zoals prestatieafwegingen en het gebruik van seccomp/AppArmor. Het doel is om u een robuuste isolatiestrategie te geven die container escapes voorkomt en uw tenants veilig houdt.

Introductie

Als u een multi-tenant hostingplatform runt—of het nu gedeelde WordPress-hosting is, een SaaS-applicatie of een dev-omgevingsservice—is container escape het nachtmerriescenario. Een kwetsbaarheid in de kernel of een verkeerde configuratie kan een tenant ertoe aanzetten om uit hun container te breken en toegang te krijgen tot de gegevens van andere tenants of de host zelf. Docker's isolatie is afhankelijk van Linux-kernelfuncties zoals namespaces en cgroups, maar out-of-the-box configuraties zijn vaak onvoldoende voor robuuste beveiliging. Dit artikel leidt u door de aanvalsvectoren en biedt bruikbare stappen om uw Docker-containers te vergrendelen, geïllustreerd met een real-world multi-tenant WordPress-voorbeeld. Voor een breder overzicht van productie-orkestratie, zie onze gids over Orchestrating Production-Ready Containerized Applications.

Docker-isolatie Begrijpen

Docker-containers gebruiken Linux-namespaces om procesniveau-isolatie te bieden: PID-namespaces isoleren processen, netwerk-namespaces scheiden netwerkinterfaces, mount-namespaces isoleren bestandssysteem-mounts en gebruikers-namespaces maken het mogelijk om de container-root toe te wijzen aan een niet-geprivilegieerde hostgebruiker. Control groups (cgroups) beperken het gebruik van bronnen zoals CPU, geheugen en schijf-I/O. Deze functies creëren samen een "sandbox" rond elke container. Echter, in tegenstelling tot een virtuele machine die een aparte kernel draait, delen containers de host-kernel. Dit betekent dat een kwetsbaarheid in de kernel (bijv. CVE-2022-0492) kan worden uitgebuit om uit de namespace-isolatie van de container te breken. Bovendien kunnen verkeerde configuraties zoals het draaien van containers als root binnen de container, het geven van alle capabilities aan de container, of het niet laten vallen van onnodige Linux-capabilities het aanvalsoppervlak vergroten.

Aanvalsvectoren

Veelvoorkomende aanvalsvectoren zijn:

  • Kernel-exploits: Het uitbuiten van een bug in de host-kernel om toegang tot de host te krijgen.
  • Geprivilegieerde containers: Draaien met --privileged verleent alle capabilities en omzeilt de meeste isolatie.
  • Capability-misbruik: Zelfs zonder volledige geprivilegieerde modus kan een container met gevaarlijke capabilities zoals CAP_SYS_ADMIN of CAP_NET_ADMIN bestandssystemen mounten of netwerkinstellingen manipuleren.
  • Onveilige image-praktijken: Het gebruik van basisimages met bekende kwetsbaarheden of het opnemen van onnodige tools zoals compilers of shell-interpreters.
  • Gedeelde mount-namespaces: Het mounten van host-directories in containers kan ontsnapping mogelijk maken als ze niet read-only zijn.

Praktische Beveiligingsstappen

1. Containers Draaien als Niet-Root Gebruiker

Standaard draait Docker containers als root binnen de container. Als een aanvaller root binnen de container verkrijgt, hebben ze meer invloed. Maak een gebruiker aan in uw Dockerfile en gebruik de USER-richtlijn. Vermijd ook het gebruik van de --user-vlag in Docker Compose om toe te wijzen aan een willekeurige hostgebruiker indien mogelijk.

2. Alle Capabilities Laten Vallen en Alleen Nodige Toevoegen

Linux-capabilities breken superuser-privileges op in kleinere eenheden. Gebruik in Docker Compose cap_drop: ALL en voeg vervolgens alleen de benodigde cap_add toe (bijv. NET_BIND_SERVICE). Vermijd gevaarlijke capabilities zoals SYS_ADMIN, NET_ADMIN, SYS_PTRACE.

3. Read-Only Root Bestandssysteem Gebruiken

Stel read_only: true in uw containerdefinitie in. Dit voorkomt dat aanvallers naar het bestandssysteem van de container schrijven. Als uw app tijdelijke bestanden moet schrijven, mount dan een tmpfs-volume op die locatie.

4. User Namespace Remapping Inschakelen

User namespace remapping wijst de root-gebruiker van de container toe aan een niet-geprivilegieerde hostgebruiker. Dit voegt een isolatielaag toe, want zelfs als een container root ontsnapt, hebben ze de privileges van de opnieuw toegewezen gebruiker. Schakel dit in /etc/docker/daemon.json in met "userns-remap": "default". Houd er rekening mee dat dit volume-permissies kan compliceren. Voor meer details, zie Mastering Docker Isolation for Secure and Efficient Web Hosting.

5. Seccomp en AppArmor/AppArmor Profielen Toepassen

Seccomp beperkt de systeemaanroepen die een container kan maken. Docker biedt een standaard seccomp-profiel dat gevaarlijke syscalls blokkeert. U kunt ook aangepaste profielen maken. Op dezelfde manier biedt AppArmor (of SELinux) verplichte toegangscontrole. Gebruik AppArmor om uw container te beperken tot een minimale set toegestane bewerkingen. Het beveiligingsprofiel kan worden ingesteld via security_opt in Docker Compose.

6. Minimale Basisimages Gebruiken en Scannen op Kwetsbaarheden

Kies kleine images zoals Alpine of Distroless die een kleiner aanvalsoppervlak hebben. Scan regelmatig images met tools zoals Docker Scout, Trivy of Clair. Integreer scannen in uw CI/CD-pipeline om te voorkomen dat kwetsbare images worden geïmplementeerd.

7. Netwerksegmentatie met Aangepaste Bridge-netwerken

Maak aparte bridge-netwerken voor elke tenant of applicatietier. Dit beperkt het oost-west verkeer. Definieer in Docker Compose netwerken en isoleer services. Gebruik internal: true als een service geen uitgaand internetverkeer nodig heeft. Firewallregels op de host beperken verder het verkeer tussen containers.

8. Resources Beperken met Cgroups

Stel CPU- en geheugenlimieten in Docker Compose in met deploy.resources.limits. Dit voorkomt dat een gecompromitteerde container een aanval met uitputting van bronnen lanceert. Stel bovendien kernel_memory en memory_reservation in voor fijnere controle.

Real-World Voorbeeld: Multi-Tenant WordPress Hosting met Docker Compose

Beschouw een scenario waarin u meerdere WordPress-sites voor verschillende klanten host, elk in zijn eigen Docker-container. Een onveilige opstelling zou er als volgt uit kunnen zien:

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:

Deze opstelling is kwetsbaar: de WordPress-container draait als root binnenin, heeft alle capabilities (aangezien er geen zijn gedropt), mount een hostdirectory met schrijftoegang en heeft onbeperkte netwerktoegang.

Laten we het nu versterken:

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:

Belangrijke verbeteringen:

  • Beide containers draaien als niet-root gebruikers (www-data en mysql).
  • Alle capabilities gedropt, alleen NET_BIND_SERVICE toegevoegd.
  • WordPress-bestandssysteem is read-only, behalve een tmpfs-mount en een uploads-volume.
  • Seccomp- en AppArmor-profielen zijn toegepast (u zou aangepaste profielen moeten leveren).
  • Aparte netwerken isoleren web van database, met het database-netwerk intern.
  • Resource-limieten voorkomen uitputting van bronnen.

Voor meer informatie over WordPress-specifieke Docker-versterking, zie Docker for WordPress: Why Isolated Containers Change Everything.

Kanttekeningen

  • User Namespace Remapping: Hoewel krachtig, breekt het volume-mounting omdat de opnieuw toegewezen host UID niet hetzelfde is als de container UID. Mogelijk moet u directories vooraf aanmaken met de juiste permissies of Docker-volumes gebruiken met remapping-ondersteuning.
  • Seccomp/AppArmor Profielen: Aangepaste profielen vereisen begrip van de systeemaanroep- en bestandsaccess-patronen van uw applicatie. Te restrictieve profielen kunnen functionaliteit breken. Test grondig.
  • Prestaties: Extra beveiligingslagen zoals seccomp en AppArmor hebben minimale overhead, maar resource-limieten en read-only bestandssystemen kunnen schrijftoepassingen met veel schrijven beïnvloeden.
  • Orchestratie Complexiteit: In een multi-tenant omgeving kan het beheren van per-tenant Docker Compose-bestanden onhandelbaar worden. Overweeg een hoger niveau orchestratietool zoals Kubernetes te gebruiken, maar dat brengt zijn eigen beveiligingsoverwegingen met zich mee.

Conclusie

Container escape is een reële dreiging in multi-tenant Docker-hosting, maar het is te voorkomen. Door de isolatiemechanismen te begrijpen en defense-in-depth toe te passen—capabilities laten vallen, draaien als niet-root, user namespaces inschakelen, seccomp, AppArmor, netwerksegmentatie en regelmatige image-scanning—kunt u het risico drastisch verminderen. Onthoud dat de standaardinstellingen van Docker niet productieklaar zijn voor multi-tenant workloads. Implementeer deze stappen vandaag nog om uw tenants en uw infrastructuur te beschermen. Voor een uitgebreid overzicht van Docker-beveiligingsbest practices, raadpleeg Securing Your Web Applications with Docker: A Practical Guide to Isolation and Best Practices.

Sources (5)