Docker-Container mit AppArmor und SELinux härten: Praxisanleitung nach CVE-2026-31431
Nach der Copy-Fail-Schwachstelle CVE-2026-31431 reicht ein Engine-Update allein nicht aus. Diese Anleitung zeigt, wie Betreiber mit AppArmor-Profilen und SELinux-Labels ihre Docker-Container zusätzlich härten, Voraussetzungen und Zielzustand definieren, den Status prüfen und im Zweifel sauber zurückrollen. Inklusive Compose-Beispielen, Audit-Hinweisen und einer Vergleichstabelle beider LSM-Ansätze.

Wer Docker-Hosts betreibt, kennt das Problem: Ein Engine-Update schließt eine akute Lücke, doch die grundsätzliche Angriffsfläche eines Containers bleibt bestehen, solange kein Linux Security Module (LSM) greift. Genau das zeigte CVE-2026-31431 im AF_ALG-Subsystem des Kernels, bei dem ein unprivilegierter Containerprozess über algif_aead den nicht namespaced Page Cache manipulieren und im schlimmsten Fall auf Host-Root eskalieren konnte. Diese Anleitung setzt dort an, wo die reine Update-Empfehlung endet, und zeigt, wie AppArmor und SELinux als zusätzliche Verteidigungslinie konfiguriert werden.
Voraussetzungen: ein Linux-Host mit Docker Engine, root- oder sudo-Zugriff, sowie ein aktiviertes LSM (AppArmor auf Debian/Ubuntu-Derivaten, SELinux auf RHEL-basierten Systemen). Zielzustand: ein eigenes, restriktives AppArmor-Profil beziehungsweise passende SELinux-Kontexte für Container, die über das docker-default-Profil hinausgehen, sowie ein dokumentierter Pruef- und Rollback-Pfad. Grenzen: AppArmor und SELinux ersetzen keine Kernel-Patches und keine Seccomp-Filter, sie ergänzen diese. Fehlkonfigurierte Profile können legitime Workloads blockieren, deshalb gehört jeder Schritt in eine Testumgebung, bevor er produktiv gesetzt wird. Prüfung erfolgt über Statuskommandos und Audit-Logs, Rollback über das Entfernen des security_opt-Eintrags beziehungsweise das Zurücksetzen auf docker-default.
Ausgangslage: CVE-2026-31431 und die Engine-Antwort
Die Docker-Entwickler reagierten auf die Lücke in mehreren Stufen. Engine 29.4.2 blockierte AF_ALG und AF_VSOCK zunächst per Seccomp-Filter, was jedoch 32-Bit-Workloads brach und sich über den socketcall-Syscall umgehen ließ. Mit 29.4.3 wechselte der Schutz auf LSM-Ebene: Der Hook security_socket_create() wird nun über AppArmor oder SELinux durchgesetzt, was robuster ist als ein reiner Syscall-Filter. Engine 29.8.0 vom 3. September 2026 schließt zusätzlich die 32-Bit-Umgehung über socketcall für AF_VSOCK und liefert ein konfigurierbares AppArmor-Default-Profile-Template mit. Wichtig für die Einordnung: Zum Zeitpunkt des offiziellen Blogbeitrags hatten Debian und RHEL 9 bereits passende Kernel-Patches bereitgestellt, während der Stand für Ubuntu zu diesem historischen Zeitpunkt noch offen war. Wer seinen Update-Status noch nicht geprüft hat, sollte das vor den folgenden Schritten nachholen.
Status prüfen vor jeder Änderung
Vor jeder Haertungsmassnahme steht die Bestandsaufnahme. Diese Befehle sind rein lesend und verändern nichts am System:
docker versionzeigt Client- und Server-Version, damit klar ist, ob 29.8.0 oder neuer läuft.docker infolistet unter anderem das aktive Security-Backend (Seccomp, AppArmor, SELinux) im Abschnitt Security Options.aa-statusauf Debian/Ubuntu zeigt geladene AppArmor-Profile und deren Modus (enforce oder complain).getenforceauf RHEL-basierten Systemen zeigt, ob SELinux im Modus Enforcing, Permissive oder Disabled läuft.docker inspect <container> --format '{{.AppArmorProfile}}'zeigt, welches Profil ein laufender Container tatsächlich nutzt.
Erst wenn diese Ausgaben dokumentiert sind, folgt die eigentliche Härtung. Das Aktualisieren der Engine selbst erfolgt über den offiziellen Paketmanager der jeweils installierten Distribution, eine pauschale Anweisung ohne Bezug auf die konkrete Distribution ist hier bewusst nicht sinnvoll.
Eigenes AppArmor-Profil auf Basis von docker-default
Das mitgelieferte docker-default-Profil ist ein guter Ausgangspunkt, aber für sensible Workloads oft zu großzügig. Ein eigenes Profil wird typischerweise aus einer Kopie des Standardprofils abgeleitet und dann verschärft, etwa indem Netzwerk-Sockelfamilien wie alg oder vsock explizit verboten werden. Der Ablauf in der Praxis:
- Vorhandenes Profil als Vorlage sichern, zum Beispiel unter
/etc/apparmor.d/docker-hardened. - Regeln für den konkreten Anwendungsfall ergänzen, etwa Dateisystempfade auf das Notwendige beschränken.
- Profil zunächst im complain-Modus laden, damit Verstöße nur protokolliert, aber nicht blockiert werden.
- Profil mit
apparmor_parser -r /etc/apparmor.d/docker-hardenedneu laden. - Mit
aa-statusprüfen, dass das Profil als geladen erscheint. - Container testweise mit dem neuen Profil starten und die Anwendung durchtesten.
- Erst nach erfolgreichem Test in den enforce-Modus wechseln.
Ein Container wird über die Compose-Syntax an das Profil gebunden:
services:
app:
image: beispiel-app:latest
security_opt:
- apparmor=docker-hardened
Bei reinem docker run lautet die Option entsprechend --security-opt apparmor=docker-hardened. Weiterführende Hinweise zur sicheren Compose-Konfiguration insgesamt, inklusive Secrets und Healthchecks, finden sich in der separaten Anleitung zu Docker Compose absichern.
SELinux-Labels und die Optionen :Z und :z
Auf RHEL-basierten Systemen übernimmt SELinux die Rolle, die AppArmor auf Debian/Ubuntu spielt. Bind-Mounts erhalten dabei ein eigenes SELinux-Label, damit ein Container nur auf die Dateien zugreifen kann, die ihm explizit zugewiesen wurden. Zwei Suffixe steuern das Verhalten beim Mounten:
:z(kleines z) kennzeichnet den Mount als von mehreren Containern gemeinsam nutzbar und setzt ein gemeinsames Label.:Z(großes Z) kennzeichnet den Mount als exklusiv für genau einen Container und setzt ein privates Label.
Ein Beispiel: docker run -v /pfad/auf/host:/pfad/im/container:Z beispiel-image sorgt dafür, dass nur dieser Container Lesezugriff auf den gemounteten Pfad erhält. Wird das Suffix vergessen, verweigert SELinux im Enforcing-Modus häufig den Zugriff, was sich zunächst wie ein Berechtigungsfehler in der Anwendung darstellt, tatsächlich aber am fehlenden Label liegt. Wer stattdessen auf Rootless-Betrieb setzt, findet ergänzende Hinweise in der Anleitung zum Docker-Rootless-Modus, die eine weitere unabhängige Isolationsebene beschreibt.
AppArmor und SELinux im Vergleich
Beide Systeme setzen am selben LSM-Hook an, unterscheiden sich aber deutlich in Konfigurationsmodell und Fehlerbild:
| Merkmal | AppArmor | SELinux |
|---|---|---|
| Typische Distributionen | Debian, Ubuntu | RHEL, Fedora, CentOS-Nachfolger |
| Konfigurationsmodell | Pfadbasierte Profile pro Programm | Typenbasierte Labels und Kontexte |
| Statusbefehl | aa-status | getenforce / sestatus |
| Testmodus | complain (protokolliert, blockiert nicht) | Permissive (protokolliert, blockiert nicht) |
| Docker-Integration | security_opt apparmor=Profilname | Bind-Mount-Suffixe :z und :Z, security_opt label |
| Relevanz für CVE-2026-31431 | Blockiert security_socket_create() für AF_ALG/AF_VSOCK | Blockiert denselben Hook über SELinux-Policy |
Audit-Logs auswerten
Sowohl bei AppArmor als auch bei SELinux lohnt sich der Blick in die Protokolle, um Fehlalarme von echten Verstößen zu unterscheiden:
- AppArmor-Meldungen erscheinen im Systemjournal, durchsuchbar mit
journalctl -k | grep apparmor. - SELinux-Verstöße landen im Audit-Log unter
/var/log/audit/audit.logund lassen sich mit dem Werkzeugausearch -m avcgezielt filtern. - Wiederkehrende DENIED-Einträge im complain- beziehungsweise Permissive-Modus zeigen, welche Regel vor dem Wechsel in den erzwingenden Modus noch ergänzt werden muss.
Rollback bei Problemen
Bricht eine Anwendung nach der Umstellung, ist der Rückweg bewusst einfach gehalten:
- Den Eintrag
security_opt: apparmor=docker-hardenedaus der Compose-Datei entfernen oder aufapparmor=docker-defaultsetzen, danach den Container neu erstellen. - Ein SELinux-Profil lässt sich mit
semanage permissive -a container_ttemporär in den Permissive-Modus versetzen, um den Betrieb wiederherzustellen, während die Ursache analysiert wird. - Nach jedem Rollback erneut
docker infound die jeweiligen Statusbefehle prüfen, damit der tatsächliche Zustand dokumentiert ist und nicht nur der beabsichtigte.
Passende Anleitungen auf S-EDV
- Docker Engine Copy Fail CVE-2026-31431: Update und Container-Check
- Docker Compose absichern: Secrets, Healthchecks, Non-Root
- Docker-Rootless-Modus auf Debian und Ubuntu einrichten