Linux Capabilities in Docker begrenzen - cap-drop und cap-add

Linux Capabilities in Docker begrenzen - cap-drop und cap-add

Docker-Container laufen mit einem reduzierten, aber immer noch signifikanten Set an Linux-Capabilities — wer wirklich absichern will, muss aktiv kürzen.

Was sind Linux Capabilities?

Linux teilt Root-Privilegien in granulare Einheiten auf. Statt "alles oder nichts" (root vs. kein root) gibt es über 40 Capabilities:

| Capability | Erlaubt |
|---|---|
| NET_BIND_SERVICE | Ports unter 1024 binden |
| NET_ADMIN | Netzwerk-Interfaces konfigurieren |
| SYS_ADMIN | Systemadministration (sehr mächtig) |
| SYS_PTRACE | Prozesse tracen (strace, gdb) |
| CHOWN | Datei-Eigentümer ändern |
| KILL | Signale an Prozesse senden |
| SETUID | User-ID wechseln |

Standard-Capabilities in Docker

Docker gewährt Containern standardmäßig ca. 14 Capabilities, u.a. CHOWN, DAC_OVERRIDE, FOWNER, KILL, NET_BIND_SERVICE, SETGID, SETUID.

# Aktive Capabilities im Container prüfen
docker run --rm alpine sh -c 'apk add -q libcap && capsh --print'

Alle Capabilities entfernen, gezielt hinzufügen

Das sicherste Pattern: alles entfernen, nur das Notwendige zurückgeben:

docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx

In Compose:

services:
  app:
    image: myapp
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE   # App bindet Port 80

Einzelne Capabilities entfernen

Ohne ALL zu droppen können spezifische Capabilities entfernt werden:

docker run --cap-drop SYS_ADMIN --cap-drop NET_ADMIN myapp
services:
  app:
    image: myapp
    cap_drop:
      - SYS_ADMIN
      - NET_ADMIN
      - SYS_PTRACE

Welche Capabilities braucht eine typische Web-App?

  • Eine einfache Web-Anwendung, die:
  • Intern auf Port 3000+ lauscht (kein NET_BIND_SERVICE nötig)
  • Keine Prozesse ptracet
  • Keine Netzwerk-Interfaces konfiguriert
  • Nicht als verschiedene User laufen muss

...braucht fast keine Capabilities:

services:
  app:
    image: myapp
    cap_drop:
      - ALL    # Für die meisten Web-Apps ausreichend

Privilegierter Modus: der Worst Case

docker run --privileged myapp   # Container hat ALLE Capabilities + Device-Zugriff

Privileged-Mode gibt dem Container so gut wie vollen Host-Zugriff. Nur für sehr spezifische Fälle notwendig (Docker-in-Docker, bestimmte Kernel-Module). In Produktions-Web-Services niemals.

Typische Anwendungsfälle

Webserver (Nginx auf Port 80):

cap_drop: [ALL]
cap_add: [NET_BIND_SERVICE, CHOWN, SETGID, SETUID]

Datenbank (PostgreSQL):

cap_drop: [ALL]
cap_add: [CHOWN, DAC_OVERRIDE, FOWNER, SETGID, SETUID]

Monitoring-Agent (braucht Prozess-Informationen):

cap_drop: [ALL]
cap_add: [SYS_PTRACE, DAC_READ_SEARCH]

Capabilities und Seccomp

Capabilities und Seccomp-Profile sind komplementäre Sicherheits-Layer:

  • Capabilities: Steuern welche privilegierten Aktionen erlaubt sind
  • Seccomp: Filtert System Calls auf Kernel-Ebene
# Standard-Seccomp-Profil ist bereits aktiv
docker run --security-opt seccomp=/path/to/profile.json myapp

Effekt prüfen

# Capabilities vor und nach dem Entfernen vergleichen
docker run --rm alpine capsh --print
docker run --rm --cap-drop ALL alpine capsh --print

Das Entfernen aller nicht benötigten Capabilities ist eine der effektivsten Härtungsmaßnahmen — sie begrenzt, was ein kompromittierter Prozess überhaupt tun kann, selbst wenn er root im Container ist.

Weiterführend

Linux-Capabilities sind ein Kernthema der allgemeinen Linux-Systemhärtung — Hintergrundwissen zu Linux-Sicherheit, Rechteverwaltung und Netzwerken gibt es auf nolr.nexon.cyou.