BPF basierte Syscall Filterung zwischen Sicherheit und Kompatibilität
Namespaces isolieren, was ein Prozess sieht, seccomp begrenzt, was ein Prozess überhaupt tun darf. Wer Container Härtung ausschließlich über Capabilities und Namespaces denkt, übersieht damit eine der wirkungsvollsten Verteidigungslinien gegen Kernel Exploits: die gezielte Sperrung von Systemaufrufen, die eine Anwendung im Normalbetrieb schlicht nie benötigt.
Inhaltsverzeichnis
- 1. Was seccomp ist und wofür es entwickelt wurde
- 2. Wie die BPF basierte Filterung technisch funktioniert
- 3. Filter-Aktionen: von ALLOW bis KILL
- 4. Das Docker-Default-Profil im Detail
- 5. Ein eigenes seccomp-Profil erstellen
- 6. Ein eigenes Profil auf einen Container anwenden
- 7. Abwägung zwischen Sicherheit und Kompatibilität
- 8. Debugging bei blockierten Syscalls
- 9. Praxisrelevanz für Magento-Container
- 10. Zusammenfassung
- 11. FAQ
1. Was seccomp ist und wofür es entwickelt wurde
seccomp, kurz für Secure Computing Mode, ist ein Kernel Feature, das die Menge der Systemaufrufe einschränkt, die ein Prozess ausführen darf. Ursprünglich 2005 als extrem restriktiver Modus eingeführt, der nur noch read, write, exit und sigreturn erlaubte, entwickelte sich seccomp mit dem 2012 hinzugekommenen seccomp-bpf Modus zu einem deutlich flexibleren Werkzeug, das komplexe, programmierbare Filterregeln statt eines starren Alles oder Nichts Modells erlaubt.
Der grundlegende Gedanke ist simpel: Ein Webserver Prozess wird niemals reboot aufrufen, ein PHP FPM Worker wird niemals ein neues Kernel Modul laden, und ein Datenbank Prozess wird niemals die Systemzeit manipulieren. Jeder dieser Syscalls, die eine Anwendung im Normalbetrieb nie benötigt, aber ein Angreifer nach einem erfolgreichen Exploit potenziell missbrauchen könnte, lässt sich mit seccomp präventiv blockieren, lange bevor eine Anwendungslogik überhaupt zum Tragen kommt.
2. Wie die BPF basierte Filterung technisch funktioniert
seccomp-bpf nutzt dieselbe Berkeley Packet Filter Technologie, die ursprünglich für Netzwerkpaket Filterung entwickelt wurde, jetzt aber auf Syscall Nummern und deren Argumente angewendet wird. Bei jedem Systemaufruf durchläuft der Kernel das geladene BPF Programm, das anhand der Syscall Nummer und optional einzelner Argumente entscheidet, ob der Aufruf erlaubt, verweigert, protokolliert oder mit einem Fehlercode simuliert wird, alles innerhalb weniger Kernel Zyklen ohne spürbaren Performance Einfluss.
Ein seccomp Filter wird als kleines BPF Bytecode Programm über den Systemaufruf seccomp() beziehungsweise das ältere prctl(PR_SET_SECCOMP) geladen und ist danach unumkehrbar an den Prozess und alle seine Kindprozesse gebunden: Ein einmal gesetzter Filter lässt sich niemals lockern, nur durch zusätzliche, restriktivere Filter weiter verschärfen. Diese Einwegrichtung ist ein bewusstes Sicherheitsdesign, das verhindert, dass ein kompromittierter Prozess seine eigenen Beschränkungen nachträglich aufhebt.
# Aktuellen seccomp Status eines Prozesses pruefen (0=disabled, 2=filter aktiv)
grep Seccomp /proc/$$/status
# Verfuegbare seccomp Aktionen des laufenden Kernels anzeigen
cat /proc/sys/kernel/seccomp/actions_avail
3. Filter-Aktionen: von ALLOW bis KILL
Ein seccomp Filter kann für jeden Syscall eine von mehreren Aktionen zurückgeben: SCMP_ACT_ALLOW lässt den Aufruf unverändert durch, SCMP_ACT_ERRNO lässt den Syscall fehlschlagen und liefert einen definierten Fehlercode zurück, ohne den Prozess zu beenden, SCMP_ACT_TRAP löst ein SIGSYS Signal aus, das der Prozess selbst behandeln kann, und SCMP_ACT_KILL beendet den aufrufenden Thread oder gleich den gesamten Prozess sofort.
Für Produktivumgebungen ist SCMP_ACT_ERRNO meist die pragmatischere Wahl gegenüber SCMP_ACT_KILL: Ein Prozess, der einen blockierten Syscall mit einem sauberen Fehlercode wie EPERM zurückerhält, kann diesen Fehler oft abfangen und weiterlaufen, während ein hartes Kill die gesamte Anwendung sofort beendet und im schlimmsten Fall unerwartete Downtime verursacht, nur weil ein selten genutzter, aber legitimer Syscall übersehen wurde.
4. Das Docker-Default-Profil im Detail
Docker aktiviert seit Version 1.10 standardmäßig ein vordefiniertes seccomp Profil für jeden neu gestarteten Container, das von den über 300 verfügbaren Linux Syscalls etwa 44 explizit blockiert, während der weitaus größere Rest erlaubt bleibt. Blockiert werden unter anderem reboot, swapon, mount außerhalb spezifischer, erlaubter Ausnahmen, kexec_load, sowie Syscalls zum Manipulieren von Kernel Modulen und zur Kontrolle der Systemzeit, allesamt Operationen, die für einen normalen Applikations Container niemals legitim gebraucht werden.
Wichtig ist die Abgrenzung zu Capabilities: Ein blockierter Syscall im seccomp Profil bleibt blockiert, selbst wenn der Prozess theoretisch die passende Capability besäße, denn seccomp arbeitet als zusätzliche, unabhängige Schutzschicht auf Syscall Ebene, die vor und unabhängig von der Capability Prüfung greift. Docker deaktiviert das Default Profil vollständig über --security-opt seccomp=unconfined, was in produktiven Umgebungen praktisch niemals angebracht ist und ausschließlich für sehr spezifisches Debugging reserviert bleiben sollte.
# Aktives seccomp Profil eines laufenden Containers inspizieren
docker inspect shop-php --format '{{.HostConfig.SecurityOpt}}'
# Default Profil bewusst deaktivieren (nur für isoliertes Debugging!)
docker run --rm -it --security-opt seccomp=unconfined alpine sh
5. Ein eigenes seccomp-Profil erstellen
Ein eigenes seccomp Profil beginnt üblicherweise als restriktive Basis, die eine Whitelist erlaubter Syscalls definiert, statt vom permissiveren Default Profil auszugehen und einzelne zusätzliche Syscalls zu blockieren. Für Docker ist ein Profil eine JSON Datei mit einer defaultAction, die für alle nicht explizit aufgeführten Syscalls gilt, sowie einer Liste von syscalls Einträgen, die davon abweichende Aktionen definieren.
Die größte praktische Herausforderung beim Erstellen eines eigenen, restriktiven Profils ist die vollständige Ermittlung aller tatsächlich benötigten Syscalls einer Anwendung, weil selbst einfache PHP oder Node.js Prozesse überraschend viele, teils selten genutzte Syscalls für Edge Cases wie Signal Handling oder bestimmte Speicherverwaltungsoperationen benötigen. In der Praxis empfiehlt sich deshalb ein iterativer Ansatz: Mit einem sehr restriktiven Profil starten, systematisch blockierte Syscalls über Audit Logs identifizieren, und das Profil schrittweise um die tatsächlich benötigten Syscalls erweitern.
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": [
"read", "write", "open", "openat", "close", "stat", "fstat",
"mmap", "munmap", "brk", "rt_sigaction", "rt_sigprocmask",
"access", "socket", "connect", "accept4", "epoll_wait",
"exit", "exit_group", "futex", "clone", "execve"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
6. Ein eigenes Profil auf einen Container anwenden
Ein fertiges Profil wird bei Docker über --security-opt seccomp=/pfad/zum/profil.json beim Container Start eingebunden und ersetzt dabei das Default Profil vollständig, statt es zu ergänzen. Podman verwendet dieselbe Syntax mit identischer JSON Struktur, was den Wechsel zwischen beiden Runtimes für dieses spezifische Feature reibungslos macht.
Für Kubernetes existiert seit Version 1.19 ein dedizierter SeccompProfile Abschnitt in der Security Context Definition, der entweder auf das Runtime Default Profil, ein am Node lokal vorhandenes Profil, oder seit 1.27 alternativ auf einen inline definierten Localhost Pfad verweisen kann. Dieser deklarative Ansatz erlaubt es, seccomp Profile als Teil des Deployment Manifests zu versionieren, statt sie manuell auf jedem Node zu pflegen.
# Eigenes Profil beim Container Start einbinden
docker run -d --name shop-php \
--security-opt seccomp=/etc/docker/seccomp/php-restrictive.json \
magento-php-fpm:8.4
7. Abwägung zwischen Sicherheit und Kompatibilität
Ein zu restriktives Profil führt zu Anwendungsabstürzen oder mysteriösen Fehlern, die auf den ersten Blick nichts mit Sicherheit zu tun haben, etwa ein PHP Prozess, der bei bestimmten Filesystem Operationen unerklärlich hängen bleibt, weil ein selten aufgerufener, aber notwendiger Syscall blockiert wurde. Ein zu permissives Profil dagegen verliert genau den Schutz, den seccomp eigentlich bieten soll, und degeneriert im Extremfall zu einer reinen Formalität ohne echten Sicherheitsgewinn.
Die pragmatische Faustregel für Produktivumgebungen lautet, mit dem Docker Default Profil zu starten, das bereits einen sinnvollen Kompromiss zwischen breiter Kompatibilität und dem Blockieren offensichtlich gefährlicher Syscalls darstellt, und ein eigenes, restriktiveres Profil nur für hochsensible Workloads zu entwickeln, bei denen der zusätzliche Pflegeaufwand durch das tatsächliche Risikoprofil gerechtfertigt ist, etwa Container mit direktem Zugriff auf sensible Kundendaten oder Zahlungsinformationen.
8. Debugging bei blockierten Syscalls
Ein durch seccomp blockierter Syscall äußert sich je nach konfigurierter Aktion unterschiedlich: Bei SCMP_ACT_ERRNO meldet die Anwendung meist einen scheinbar harmlosen Permission denied oder Function not implemented Fehler, ohne dass der eigentliche Auslöser sofort ersichtlich wird. Der zuverlässigste Weg, den blockierten Syscall konkret zu identifizieren, führt über strace, das jeden Systemaufruf samt Rückgabewert protokolliert und damit exakt zeigt, an welcher Stelle der Prozess auf eine seccomp Blockade läuft.
Für eine systematischere Analyse eignet sich der Audit Modus über SCMP_ACT_LOG statt SCMP_ACT_ERRNO als default Aktion: Blockierte Syscalls werden dann protokolliert statt tatsächlich verweigert, sodass sich über einen repräsentativen Testlauf hinweg alle tatsächlich benötigten Syscalls im Kernel Audit Log oder über journalctl -k sammeln lassen, bevor das Profil im produktiven Modus scharf geschaltet wird.
# Syscalls eines Prozesses live mitschneiden, um blockierte Aufrufe zu finden
strace -f -e trace=all -o /tmp/trace.log php-fpm8.4 -F
# Seccomp bezogene Kernel Audit Meldungen filtern
journalctl -k | grep -i seccomp
9. Praxisrelevanz für Magento-Container
Für einen typischen Magento PHP FPM Container ist das Docker Default Profil in aller Regel ausreichend und deckt sämtliche für die Ausführung von PHP, Composer und die üblichen Filesystem und Netzwerkoperationen benötigten Syscalls bereits ab, ohne dass ein eigenes Profil notwendig wäre. Ein eigenes, restriktiveres Profil lohnt sich vor allem für spezialisierte Hilfscontainer mit stark eingeschränktem Aufgabenbereich, etwa einen dedizierten Cron Container, der ausschließlich planmäßige Magento Indexer Läufe ausführt und keinerlei Netzwerk oder Datei Operationen jenseits dessen benötigt.
Bei allen Härtungsmaßnahmen gilt: seccomp ersetzt keine der übrigen Schutzschichten wie Namespaces, Capabilities oder Read Only Root Filesystems, sondern ergänzt sie um eine zusätzliche, orthogonale Verteidigungslinie. Erst das Zusammenspiel mehrerer unabhängiger Mechanismen macht einen Container Escape für einen Angreifer tatsächlich signifikant schwerer, weil jede einzelne Schicht für sich genommen umgangen werden könnte, während alle gemeinsam einen deutlich robusteren Schutz bilden.
| Filter-Aktion | Verhalten bei blockiertem Syscall | Prozess läuft weiter | Typischer Einsatz |
|---|---|---|---|
| SCMP_ACT_ALLOW | Syscall wird normal ausgefuehrt | ja | Whitelist erlaubter Syscalls |
| SCMP_ACT_ERRNO | Syscall schlaegt mit definiertem Fehlercode fehl | ja, sofern Anwendung Fehler abfaengt | Produktivumgebungen, sanftes Blockieren |
| SCMP_ACT_TRAP | SIGSYS Signal an den Prozess ausgeloest | abhaengig vom eigenen Signal Handler | spezialisiertes Fehler Handling |
| SCMP_ACT_KILL | Prozess oder Thread wird sofort beendet | nein | maximale Haertung, hohes Risiko für Fehlalarme |
| SCMP_ACT_LOG | Syscall wird ausgefuehrt und protokolliert | ja | Audit Modus zur Profilentwicklung |
Mironsoft
Server-Administration, Docker-Hosts und Performance-Tuning
Linux-Server, die niemand im Team richtig versteht?
Wir übernehmen Setup, Absicherung und Performance-Tuning von Linux-Servern und Docker-Hosts für Magento-Deployments, dokumentiert und nachvollziehbar statt gewachsen und unklar.
Server-Audit
Bestehende Server-Konfiguration auf Sicherheitslücken und Performance-Bremsen prüfen.
Docker-Host-Setup
Produktionsreife Docker-Umgebungen für Magento sauber aufsetzen und absichern.
Monitoring & Tuning
Ressourcenverbrauch messen und Systemd, Kernel und Dienste gezielt optimieren.
10. Zusammenfassung
seccomp
Grundprinzip
BPF basierte Filterung erlaubter und blockierter Syscalls pro Prozess
Docker Default
Etwa 44 von über 300 Syscalls blockiert, breite Kompatibilitaet
Eigenes Profil
Whitelist Ansatz, iterativ über Audit Logs entwickelt
Debugging Werkzeug
strace für akute Fälle, SCMP_ACT_LOG für systematischen Audit