Container Security
Sicherheitsmaßnahmen für containerisierte Anwendungen (Docker, Kubernetes). Container teilen den Host-Kernel - ein kompromittierter Container kann andere Container oder den Host gefährden. Container Security umfasst Image-Härtung, Laufzeit-Schutz, Netzwerksegmentierung und Supply Chain Sicherheit.
Container Security schützt containerisierte Anwendungen über den gesamten Lebenszyklus: von der Image-Erstellung über die Registry bis zur Laufzeit. Im Gegensatz zu VMs teilen Container den Kernel des Host-Betriebssystems - was Performance-Vorteile bringt, aber auch spezifische Sicherheitsrisiken schafft.
Das Container-Bedrohungsmodell
| Schicht | Gegenmaßnahme |
|---|---|
| Anwendung (Code-Schwachstellen) | SAST/DAST |
| Container Image (Base Image) | Image Scanning |
| Container Runtime (Docker) | Runtime Security |
| Kubernetes / Orchestration | K8s Hardening |
| Host OS (Linux Kernel) | gVisor / Kata |
| Infrastruktur (Cloud/On-Prem) | IaC Security |
Phase 1: Sichere Images bauen
Dockerfile Best Practices
# SCHLECHT: fat image, root-User
FROM ubuntu:latest
RUN apt-get update && apt-get install -y python3 pip curl wget
COPY . /app
CMD ["python3", "/app/app.py"]
# GUT: minimal image, non-root, pinned versions
FROM python:3.12.2-slim@sha256:abc123... # Digest pinnen statt Tag!
# Dependencies als separater Layer (Cache)
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# App-Code
COPY --chown=appuser:appuser . .
# Non-root User
RUN useradd --uid 10001 --no-create-home appuser
USER appuser
# Nur Health-Port exposieren
EXPOSE 8080
# Kein Shell-Entrypoint (verhindert Shell-Injection)
ENTRYPOINT ["python3", "-m", "uvicorn", "main:app"]
Image Scanning
# Trivy - kostenlos, CNCF-Projekt
trivy image --severity HIGH,CRITICAL myapp:latest
# Output:
# myapp:latest (debian 12.4)
# Total: 3 (HIGH: 2, CRITICAL: 1)
# ┌──────────────┬────────────────┬──────────┬──────────────────────────┐
# │ Library │ Vulnerability │ Severity │ Installed Version │
# ├──────────────┼────────────────┼──────────┼──────────────────────────┤
# │ libssl3 │ CVE-2024-5535 │ CRITICAL │ 3.0.11-1~deb12u2 │
# └──────────────┴────────────────┴──────────┴──────────────────────────┘
# In CI/CD (GitHub Actions)
- name: Scan image
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:${{ github.sha }}'
exit-code: '1' # Pipeline bricht bei CRITICAL ab
severity: 'CRITICAL'
Supply Chain Security (SLSA)
# Cosign - Image-Signierung
cosign sign --key cosign.key myregistry.io/myapp:1.0.0
# Verifizierung vor Deployment
cosign verify --key cosign.pub myregistry.io/myapp:1.0.0
# SBOM generieren (Software Bill of Materials)
syft myapp:latest -o spdx-json > sbom.json
# SBOM auf Schwachstellen prüfen
grype sbom:sbom.json
Phase 2: Registry Security
Registry-Sicherheit:
- Private Registry verwenden: Harbor, ECR, ACR (keine öffentliche Registry!)
- Image Scanning vor Push (Admission Policy)
- Nur signierte Images deployen (Policy Engine: Kyverno, OPA Gatekeeper)
- Immutable Tags:
:1.2.3statt:latest - Registry-Credentials als Secrets (nicht in Dockerfile!)
Harbor Beispiel-Policy:
- Allow: Images mit CRITICAL: 0
- Allow: Images mit Cosign-Signatur
- Deny: Images älter als 90 Tage ohne Re-Scan
Phase 3: Kubernetes-Cluster Hardening
Pod Security Standards
# Restrictive PodSecurityContext
apiVersion: v1
kind: Pod
spec:
securityContext:
runAsNonRoot: true # Kein root!
runAsUser: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault # seccomp Profil aktiv
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false # Kein sudo in Container!
readOnlyRootFilesystem: true # Read-only Root
capabilities:
drop:
- ALL # Alle Linux Capabilities droppen
add:
- NET_BIND_SERVICE # Nur nötige hinzufügen
resources:
limits:
memory: "256Mi"
cpu: "500m"
requests:
memory: "128Mi"
cpu: "100m"
NetworkPolicy (Kubernetes-Firewall)
# Micro-Segmentierung: Frontend darf nur mit Backend, nicht direkt mit DB
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-isolation
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- port: 5432
Secrets Management
# FALSCH: Secret in YAML hardcoded
env:
- name: DB_PASSWORD
value: "super-secret-password" # → in git history, etcd, Logs!
# BESSER: Kubernetes Secret (base64-encoded, nicht encrypted by default!)
kubectl create secret generic db-secret \
--from-literal=password="super-secret-password"
# BESTE PRAXIS: External Secrets Operator + HashiCorp Vault
# secrets.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
spec:
secretStoreRef:
name: vault-backend
target:
name: db-secret
data:
- secretKey: password
remoteRef:
key: prod/database
property: password
Phase 4: Laufzeit-Sicherheit
Falco - Runtime Threat Detection
# Falco Rule: Shell in Container (häufiges Anzeichen von Compromise)
- rule: Terminal Shell in Container
desc: A shell was used as the entrypoint/exec point into a container
condition: >
spawned_process and container
and shell_procs and proc.tty != 0
and container_entrypoint
output: >
A shell was spawned in a container with an attached terminal
(user=%user.name container=%container.name image=%container.image.repository)
priority: NOTICE
Weitere Falco-Regeln:
- Privileged Container gestartet
/etc/passwdoder/etc/shadowgelesen- Netzwerkverbindung zu unbekannter IP
- Crypto-Miner Aktivität erkannt
- Kubectl in Container ausgeführt
OWASP Top 10 Container Security Risks
| Risiko | Gegenmaßnahme |
|---|---|
| C1: Insecure Supply Chain | Image Signing, SBOM, SCA |
| C2: Authorization Flaws | RBAC, NetworkPolicy, OPA |
| C3: Overly Permissive Container | Read-only FS, Drop ALL Caps |
| C4: Improper Network Access | NetworkPolicy, Service Mesh (Istio) |
| C5: Inadequate Logging | Falco, CloudTrail, Audit Logs |
| C6: Insecure Secrets | Vault, External Secrets Operator |
| C7: Vulnerable Components | Trivy, Grype, SBOM |
| C8: Runtime Threats | Falco, Tetragon, Sysdig |
| C9: Misconfigured Orchestration | kube-bench (CIS Benchmark) |
| C10: Exposed Dashboard | Kubernetes Dashboard nie public! |
kube-bench: CIS Benchmark Check
# Automatische Prüfung gegen CIS Kubernetes Benchmark
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl logs job/kube-bench
# Beispiel-Output:
# [FAIL] 1.2.1 Ensure that the --anonymous-auth argument is set to false
# [PASS] 1.2.6 Ensure that the --kubelet-https argument is set to true
# [FAIL] 4.2.1 Ensure that the --anonymous-auth argument is set to false
#
# == Summary ==
# 42 checks PASS
# 7 checks FAIL
# 11 checks WARN
Service Mesh (Istio/Linkerd)
Service Mesh erweitert Container Security:
- mTLS zwischen allen Services (automatisch)
- Feingranulare AuthorizationPolicies
- Traffic-Verschlüsselung ohne App-Code-Änderung
- Observability: Traces, Metrics per Service
Istio AuthorizationPolicy:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
spec:
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/prod/sa/frontend"]
to:
- operation:
methods: ["GET", "POST"]
paths: ["/api/*"]