- Container sind keine Sicherheitsgrenze. Ein kompromittierter Container kann bei falscher Konfiguration den Host-Kernel und andere Container angreifen.
- Image-Scanning in der CI/CD-Pipeline ist die erste Verteidigungslinie. Verwende nur vertrauenswürdige Basis-Images und scanne jedes Image vor dem Deployment auf Schwachstellen.
- Container sollten nie als Root laufen. Verwende non-root User, Read-only Filesystems und Security Contexts, um die Angriffsfläche zu minimieren.
- Kubernetes Network Policies sind das Container-Äquivalent zur Netzwerksegmentierung. Ohne sie kann jeder Pod mit jedem anderen Pod kommunizieren.
- Secrets gehören nicht in Container-Images oder Umgebungsvariablen. Nutze Kubernetes Secrets (verschlüsselt) oder externe Vault-Systeme (HashiCorp Vault, AWS Secrets Manager).
Container und Sicherheit: Die Grundlagen
Container haben die Softwareentwicklung und den IT-Betrieb grundlegend verändert. Anwendungen werden in standardisierte, portable Einheiten verpackt, die überall gleich laufen: auf dem Entwickler-Laptop, im CI/CD-System und in der Produktion. Docker hat die Technologie populär gemacht, Kubernetes hat die Orchestrierung auf einer höheren Ebene standardisiert.
Was bei aller Begeisterung für die Vorteile (Portabilität, Skalierbarkeit, Reproduzierbarkeit) oft untergeht: Container bringen eigene Sicherheitsrisiken mit sich, die sich von klassischen Server-Deployments unterscheiden. Ein Container ist keine VM. Er teilt sich den Kernel mit dem Host-System und anderen Containern. Die Isolierung ist eine Softwareabstraktion (Namespaces, Cgroups), keine Hardware-Grenze.
Das bedeutet nicht, dass Container unsicher sind. Es bedeutet, dass du die spezifischen Risiken verstehen und adressieren musst.
Die Angriffsfläche von Containern
Die Container-Angriffsfläche lässt sich in mehrere Ebenen unterteilen.
Container-Image
Das Image ist das Fundament. Es enthält das Betriebssystem, die Laufzeitumgebung und die Anwendung. Wenn das Basis-Image verwundbare Softwareversionen enthält, erbt jeder daraus erstellte Container diese Schwachstellen. Wenn vertrauliche Daten (API-Keys, Passwörter, SSH-Schlüssel) im Image enthalten sind, kann jeder, der Zugriff auf das Image hat, diese Daten extrahieren. Ein durchdachtes Secrets Management verhindert dieses Problem von vornherein.
Häufige Probleme: Veraltete Basis-Images (z.B. ubuntu:20.04 mit ungepatchten Schwachstellen), unnötige Pakete im Image (Build-Tools, Compiler, Debug-Werkzeuge, die in der Produktion nicht benötigt werden), Secrets in Image-Layern (selbst wenn du eine Datei in einem späteren Layer löschst, bleibt sie in den vorherigen Layern erhalten und extrahierbar).
Container-Runtime
Die Runtime (Docker Engine, containerd, CRI-O) ist die Softwareschicht, die Container startet und verwaltet. Eine Schwachstelle in der Runtime kann zur Container-Escape führen, also dem Ausbruch aus dem Container auf das Host-System. Container-Escapes sind selten, aber wenn sie auftreten, haben sie katastrophale Auswirkungen, weil der Angreifer plötzlich Root-Zugriff auf den Host hat.
Häufige Probleme: Docker-Socket gemountet (-v /var/run/docker.sock:/var/run/docker.sock), was dem Container vollen Zugriff auf die Docker-API und damit auf alle anderen Container und den Host gibt. Privilegierte Container (--privileged), die praktisch alle Sicherheitsmechanismen deaktivieren. Veraltete Runtime-Versionen mit bekannten Schwachstellen.
Container-Orchestrierung (Kubernetes)
Kubernetes fügt eine weitere Komplexitätsschicht hinzu. Der API-Server, etcd (die Kubernetes-Datenbank), Kubelet und die verschiedenen Controller bieten Angriffsflächen. Die Standardkonfiguration von Kubernetes ist auf Benutzerfreundlichkeit ausgelegt, nicht auf Sicherheit.
Häufige Probleme: Ungeschützter API-Server (keine Authentifizierung oder zu weitreichende RBAC-Rechte), kein NetworkPolicy (jeder Pod kann mit jedem anderen Pod im Cluster kommunizieren), Secrets in etcd unverschlüsselt (standardmäßig sind Kubernetes Secrets nur Base64-kodiert, nicht verschlüsselt), überdimensionierte Service Accounts mit Cluster-Admin-Rechten.
Supply Chain
Container-Images werden aus öffentlichen Registries (Docker Hub, GitHub Container Registry) bezogen. Wenn ein Image in der Registry kompromittiert wird, erben alle davon abhängigen Images die Malware. Supply-Chain-Angriffe auf Container-Images sind ein wachsendes Problem.
Docker absichern: Die wichtigsten Maßnahmen
Sichere Basis-Images verwenden
Verwende minimale Basis-Images. Statt ubuntu:22.04 (77 MB, hunderte Pakete) nutze ubuntu:22.04-minimal oder besser noch distroless-Images von Google (nur die Laufzeitumgebung, kein Shell, keine Paketverwaltung) oder Alpine-basierte Images (5 MB, minimale Paketauswahl).
Je weniger Software im Image enthalten ist, desto kleiner ist die Angriffsfläche. Ein Container, der keine Shell hat, kann nicht von einem Angreifer für eine interaktive Session missbraucht werden.
Verwende immer spezifische Image-Tags (z.B. node:20.11.1-alpine) und nie latest. Der latest-Tag kann sich jederzeit ändern, und du weißt nicht, welche Version du in Produktion hast.
Multi-Stage Builds
Multi-Stage Builds trennen die Build-Umgebung von der Laufzeitumgebung. Im ersten Stage compilierst du den Code mit allen nötigen Build-Tools. Im zweiten Stage kopierst du nur das fertige Artefakt in ein minimales Laufzeit-Image. Die Build-Tools, der Quellcode und alle Zwischenprodukte bleiben im Build-Stage und sind im finalen Image nicht enthalten.
Das reduziert die Image-Größe erheblich und eliminiert eine ganze Klasse von Sicherheitsrisiken: Ein Angreifer, der in den Container eindringt, findet keine Compiler, keine Build-Tools und keinen Quellcode vor.
Container nicht als Root laufen lassen
Standardmäßig laufen Prozesse in Docker-Containern als Root (UID 0). Wenn ein Angreifer aus dem Containerprozess ausbricht, ist er auf dem Host möglicherweise ebenfalls Root (abhängig von der User-Namespace-Konfiguration).
Erstelle in deinem Dockerfile einen dedizierten Benutzer und wechsle mit der USER-Anweisung zu diesem Benutzer. Beispiel: RUN addgroup --system app && adduser --system --ingroup app app gefolgt von USER app. Teste, ob die Anwendung als Non-Root-Benutzer funktioniert. Manchmal binden Anwendungen an privilegierte Ports (unter 1024) oder schreiben in Verzeichnisse, für die Root-Rechte nötig sind. Passe in diesen Fällen die Anwendungskonfiguration an (Port ändern, Schreibverzeichnis anpassen).
Read-only Filesystem
Setze das Container-Dateisystem auf Read-only (docker run --read-only). Das verhindert, dass ein Angreifer Dateien im Container verändern oder Malware herunterladen und ausführen kann. Wenn die Anwendung temporäre Dateien schreiben muss, mounte ein tmpfs-Volume für das benötigte Verzeichnis.
Image-Scanning
Scanne jedes Container-Image vor dem Deployment auf bekannte Schwachstellen. Die gängigsten Tools sind Trivy (Open Source, von Aqua Security, sehr schnell, unterstützt OS-Pakete und Sprachpakete), Grype (Open Source, von Anchore, gute Integration mit Syft für SBOM-Generierung) und Snyk Container (kommerziell, gute IDE-Integration, priorisiert Schwachstellen nach Erreichbarkeit).
Integriere das Scanning in deine CI/CD-Pipeline als Teil des Secure Development Lifecycle. Definiere eine Policy: z.B. "kein Deployment, wenn kritische oder hohe Schwachstellen im Image sind". Scanne nicht nur beim Build, sondern regelmäßig auch laufende Images, weil neue Schwachstellen jederzeit entdeckt werden können.
Docker-Socket niemals mounten
Den Docker-Socket in einen Container zu mounten ist ein häufiges Anti-Pattern, das z.B. für CI/CD-Runner (Jenkins, GitLab Runner) oder Monitoring-Tools verwendet wird. Es gibt dem Container die volle Kontrolle über die Docker-Engine und damit über alle anderen Container und den Host.
Verwende stattdessen rootless Docker, kaniko (für Container-Builds in der CI/CD-Pipeline ohne Docker-Socket) oder podman (daemonless, kein zentraler Socket).
Kubernetes absichern: Die wichtigsten Maßnahmen
RBAC richtig konfigurieren
Kubernetes Role-Based Access Control (RBAC) steuert, wer was im Cluster tun darf. Die häufigsten Fehler sind zu weitreichende ClusterRoles (z.B. cluster-admin für einen Service Account, der nur Pods in einem Namespace lesen muss), Default Service Accounts mit zu vielen Rechten und fehlende Namespace-Isolation (Workloads verschiedener Teams oder Umgebungen im selben Namespace).
Erstelle für jede Anwendung einen dedizierten Service Account mit minimalen Rechten. Verwende Roles (Namespace-scoped) statt ClusterRoles, wo möglich. Deaktiviere die automatische Montage des Service-Account-Tokens, wenn die Anwendung keinen Zugriff auf die Kubernetes-API braucht: automountServiceAccountToken: false.
Network Policies
Ohne Network Policies kann jeder Pod im Kubernetes-Cluster mit jedem anderen Pod kommunizieren. Das ist das Äquivalent eines flachen Netzwerks ohne Segmentierung: Wenn ein Pod kompromittiert wird, kann der Angreifer alle anderen Pods im Cluster angreifen.
Network Policies definieren, welcher Traffic zwischen Pods erlaubt ist – das Container-Pendant zur Netzwerksegmentierung. Beginne mit einer Default-Deny-Policy für jeden Namespace (blockiert allen eingehenden Traffic) und öffne dann gezielt die benötigten Verbindungen.
Beispiel: Dein Frontend-Pod darf nur mit dem Backend-Pod auf Port 8080 kommunizieren. Der Backend-Pod darf nur mit dem Datenbank-Pod auf Port 5432 kommunizieren. Der Datenbank-Pod darf von niemandem außer dem Backend-Pod angesprochen werden.
Network Policies erfordern ein CNI-Plugin, das sie unterstützt (z.B. Calico, Cilium, Weave Net). Das Standard-CNI in vielen managed Kubernetes-Diensten (z.B. AWS VPC CNI ohne Calico-Addon) unterstützt Network Policies nicht.
Pod Security Standards
Kubernetes Pod Security Standards (PSS) definieren drei Sicherheitsstufen für Pods.
Privileged: Keine Einschränkungen. Für Systemkomponenten und Infrastruktur-Workloads.
Baseline: Verhindert die offensichtlichsten Sicherheitsrisiken. Blockiert privilegierte Container, Host-Namespace-Zugriff und gefährliche Capabilities. Geeignet für die meisten Anwendungen.
Restricted: Strikte Sicherheitsanforderungen. Non-Root, Read-only Root-Filesystem, keine zusätzlichen Capabilities, Seccomp-Profile. Geeignet für sicherheitskritische Anwendungen.
Konfiguriere Pod Security Standards auf Namespace-Ebene. Für Produktions-Namespaces solltest du mindestens "Baseline", besser "Restricted" verwenden.
Secrets sicher verwalten
Kubernetes Secrets sind standardmäßig nur Base64-kodiert und unverschlüsselt in etcd gespeichert. Jeder, der Lesezugriff auf etcd hat, kann alle Secrets im Klartext lesen.
Aktiviere Encryption at Rest für etcd. Das verschlüsselt Secrets, bevor sie in etcd geschrieben werden. Besser noch: Verwende einen externen Secrets-Store (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault) und den External Secrets Operator oder Secrets Store CSI Driver, um Secrets zur Laufzeit in Pods zu injizieren.
Secrets sollten als Volume gemountet werden, nicht als Umgebungsvariablen. Umgebungsvariablen tauchen in Prozesslisten, Crash-Dumps und Logs auf.
Admission Controller
Kubernetes Admission Controller prüfen Anfragen an den API-Server, bevor sie ausgeführt werden. Mit Policy-Engines wie OPA Gatekeeper oder Kyverno kannst du Sicherheitsregeln erzwingen.
Beispiele für sinnvolle Policies: Kein Container darf als Root laufen. Kein Container darf privilegierte Capabilities haben. Alle Images müssen aus einer erlaubten Registry stammen. Alle Images müssen signiert sein. Jedes Deployment muss Resource Limits haben.
Sichere CI/CD-Pipeline für Container
Die CI/CD-Pipeline ist der Weg vom Quellcode zum laufenden Container. Wenn die Pipeline kompromittiert wird, kann ein Angreifer bösartigen Code in jedes Deployment injizieren.
Pipeline-Sicherheitsmaßnahmen
Image-Scanning als Quality Gate: Integriere Trivy oder Grype als Schritt in die Pipeline. Wenn kritische Schwachstellen gefunden werden, bricht der Build ab.
Image-Signierung: Signiere Container-Images mit Cosign (von Sigstore) oder Notary. Kubernetes-Admission-Controller können dann prüfen, ob ein Image eine gültige Signatur hat, bevor es deployed wird.
SBOM generieren: Erstelle für jedes Image eine Software Bill of Materials (SBOM) mit Tools wie Syft. Die SBOM dokumentiert, welche Software-Komponenten im Image enthalten sind, und ist die Grundlage für Schwachstellen-Tracking.
Least Privilege für Pipeline-Zugriffe: Der CI/CD-Runner braucht Zugriff auf die Container-Registry (push) und den Kubernetes-Cluster (deploy). Beschränke die Rechte auf das absolute Minimum: Push-Zugriff nur auf bestimmte Repositories, Deployment-Zugriff nur auf bestimmte Namespaces.
Monitoring und Runtime-Schutz
Container laufen, Container sterben, neue Container starten. Dieses dynamische Verhalten macht klassisches Monitoring und Sicherheitsüberwachung herausfordernd.
Runtime-Sicherheit
Tools wie Falco (Open Source, CNCF-Projekt) überwachen das Verhalten laufender Container in Echtzeit und erkennen verdächtige Aktivitäten wie unerwartete Shell-Aufrufe in Containern, Zugriff auf sensible Dateien (/etc/shadow, /etc/passwd), ausgehende Netzwerkverbindungen zu unbekannten Zielen oder das Starten unerwarteter Prozesse.
Falco definiert Regeln, die normales Verhalten beschreiben. Jede Abweichung wird als Alert gemeldet. Für Container, die keine Shell haben sollten (z.B. ein Node.js-Anwendungscontainer), ist jeder Shell-Aufruf ein starkes Indiz für eine Kompromittierung.
Logging und Audit
Zentralisiere Container-Logs mit einem Log-Aggregator (z.B. Fluentd, Loki, Elasticsearch). Container-Logs sind flüchtig und gehen verloren, wenn der Container beendet wird. Ohne zentrale Sammlung hast du nach einem Vorfall keine Möglichkeit zur Analyse.
Aktiviere Kubernetes-Audit-Logging als Teil deiner Logging- und Monitoring-Strategie. Es protokolliert alle API-Aufrufe an den Kubernetes-API-Server und ist unverzichtbar für die Forensik nach einem Sicherheitsvorfall.
Container-Sicherheit im Mittelstand: Pragmatisch starten
Nicht jedes mittelständische Unternehmen braucht ein vollständiges Container-Sicherheitsprogramm mit Service Mesh, RBAC-Automation und Runtime-Sicherheit. Wenn du gerade erst mit Containern anfängst oder ein kleines Cluster betreibst, starte mit den Grundlagen.
Woche 1: Führe Trivy als Image-Scanner in deiner CI/CD-Pipeline ein. Behebe kritische und hohe Schwachstellen in deinen Images.
Woche 2: Stelle sicher, dass kein Container als Root läuft. Passe Dockerfiles und Kubernetes-Manifeste an.
Woche 3: Implementiere Network Policies mit Default-Deny in deinen Produktions-Namespaces. Öffne gezielt die benötigten Verbindungen.
Woche 4: Aktiviere Encryption at Rest für etcd und migriere Secrets aus Umgebungsvariablen in gemountete Kubernetes Secrets.
Diese vier Maßnahmen adressieren die häufigsten und kritischsten Container-Sicherheitsrisiken und sind innerhalb eines Monats umsetzbar.
Container-Sicherheit und regulatorische Anforderungen
Container sind kein regulatorisches Sonderthema. Sie fallen unter die allgemeinen Anforderungen an sichere Entwicklung und Betrieb von IT-Systemen.
NIS2 Artikel 21 fordert Sicherheitsmaßnahmen bei Erwerb, Entwicklung und Wartung von Netz- und Informationssystemen. Container-Images, Kubernetes-Cluster und CI/CD-Pipelines sind Bestandteile dieser Systeme. ISO 27001 Annex A, Kontrolle A.8.25 (Secure development lifecycle), gilt auch für containerisierte Anwendungen. Kontrolle A.8.9 (Configuration management) fordert, dass die Konfiguration von Software und Diensten dokumentiert und kontrolliert wird, was Dockerfiles, Kubernetes-Manifeste und Helm Charts einschließt.
Dokumentiere deine Container-Sicherheitsrichtlinie in deinem ISMS – in ISMS Lite lassen sich Richtlinien, Scanning-Ergebnisse und Pod-Security-Standards zentral verwalten und für Audits aufbereiten. Halte fest: Welche Basis-Images sind erlaubt? Welche Scanning-Tools werden eingesetzt? Welche Pod-Security-Standards gelten? Wie werden Secrets verwaltet? Diese Dokumentation ist dein Nachweis für Audits.
Häufige Fehler und Anti-Patterns
Container als Ersatz für VMs betrachten. Container sind keine kleinen VMs. Ein Container, der eine komplette Linux-Distribution mit SSH-Server, Cron-Jobs und mehreren Diensten enthält, verliert alle Vorteile der Container-Technologie und erbt die Sicherheitsprobleme beider Welten. Ein Container sollte einen Prozess ausführen und nichts anderes.
Alles in einem Namespace. Wenn Entwicklungs-, Staging- und Produktionsumgebung im selben Kubernetes-Namespace laufen, fehlt die Isolation. Ein Fehler in der Entwicklungsumgebung kann die Produktion beeinflussen. Verwende separate Namespaces, besser separate Cluster, für verschiedene Umgebungen.
Container-Updates ignorieren. Container werden gebaut und laufen dann monatelang unverändert. Neue Schwachstellen in den Basis-Images werden nicht behoben, weil niemand die Images neu baut. Implementiere einen regelmäßigen Rebuild-Zyklus (mindestens monatlich) und scanne laufende Images kontinuierlich auf neue Schwachstellen.
Kein Resource Limiting. Container ohne CPU- und Memory-Limits können den gesamten Host oder Cluster destabilisieren. Ein einzelner Container, der aufgrund eines Memory-Leaks unbegrenzt Speicher anfordert, kann andere Container auf demselben Host zum Absturz bringen. Setze immer Resource Requests und Limits in deinen Kubernetes-Manifesten.
Weiterführende Artikel
- Secure Development Lifecycle (SDL): Sicherheit in den Entwicklungsprozess einbauen
- Secrets Management: Passwörter, API-Keys und Zertifikate sicher verwalten
- Dependency Scanning: Schwachstellen in Drittbibliotheken finden
- Netzwerksegmentierung für KMU: Zonen, VLANs und Firewalls
- API-Sicherheit: Authentifizierung, Rate Limiting und Input Validation
