Zum Inhalt

Mandatory Access Control: AppArmor & SELinux Enterprise-Praxis

Erstellt: 10.11.2026 Aktualisiert: 10.11.2026

Management Summary: Traditionelle Linux-Rechtevergabe über Discretionary Access Control (DAC) scheitert in dem Moment, in dem ein Dienst mit Root-Rechten kompromittiert wird: Der Superuser root darf prinzipbedingt jede Datei lesen, modifizieren oder löschen. Mandatory Access Control (MAC) etabliert über die Linux Security Module (LSM) Schnittstelle eine unumgehbare zweite Sicherheitsinstanz direkt im Kernel. Selbst wenn ein Angreifer volle Root-Rechte (UID 0) in einem Webserver oder Daemon erlangt, sperrt das Sicherheitsmodul ihn in ein unverletzbares Gefängnis ein. Dieser praxisnahe Leitfaden dekonstruiert die beiden marktführenden Enterprise-Systeme: AppArmor (pfadbasiert, Standard unter Debian und Ubuntu) und SELinux (labelbasiert, Standard unter RHEL und Fedora): Von der LSM-Kernel-Architektur über die Profil-Erstellung (aa-genprof, aa-logprof), SELinux Type Enforcement, Booleans und Port-Labels bis hin zur systematischen AVC-Denial-Forensik mit ausearch und audit2why.

  • DAC vs. MAC Architektur


    Verstehe den fundamentalen Unterschied zwischen benutzergesteuerten Dateirechten (DAC) und kernel-erzwungenen LSM-Sicherheitsrichtlinien (MAC).

  • AppArmor Profil-Lifecycle


    Vom complain-Überwachungsmodus zum strikten enforce-Schutz: Profile für Daemons definieren, testen und atomar aktivieren.

  • AppArmor CLI-Toolchain


    Effizientes Erstellen und Anpassen von Profilen mit aa-genprof, aa-logprof, aa-complain, aa-enforce und dem Status-Dashboard aa-status.

  • SELinux Typ-Erzwingung


    Labels, Extended Attributes (security.selinux), Sicherheitskontexte (user:role:type:level) und Domain Transitions im Linux-Kernel.

  • SELinux Booleans & Ports


    Verhalten von Diensten dynamisch steuern mit setsebool -P und benutzerdefinierte Netzwerkports via semanage port zuweisen.

  • AVC-Denials & Audit-Forensik


    Zugriffsblockaden zielsicher identifizieren mit ausearch -m avc, Fehlermeldungen übersetzen via audit2why und Richtlinien mit audit2allow härten.


1. DAC vs. MAC: Warum Discretionary Access Control unzureichend ist

Unter der traditionellen Discretionary Access Control (DAC) entscheidet der Dateieigentümer über Lese-, Schreib- und Ausführungsrechte (chmod, chown). Wenn ein Daemon (wie Nginx, Apache oder Bind) mit Root-Rechten läuft oder ein Angreifer eine Schwachstelle zur lokalen Rechteausweitung (Privilege Escalation) ausnutzt, besitzt er unmittelbar unbegrenzten Zugriff auf das gesamte Dateisystem.

Mandatory Access Control (MAC) schaltet sich über die Linux Security Module (LSM) Schnittstelle als zweite, unumgängliche Prüfinstanz direkt in den Ausführungspfad des Kernels. Jeder Systemaufruf muss erst die DAC-Prüfung und unmittelbar danach die MAC-Richtlinie erfolgreich durchlaufen:

%%{init: {'flowchart': {'wrappingWidth': 350}}}%%
flowchart TB
    Process["Prozess<br/>(z. B. Webserver UID 0)"] ==> SysCall["Systemaufruf<br/>(openat, execve, socket)"]
    SysCall --> DAC_Check{"1. DAC-Prüfung<br/>(UID / GID / Mode)"}
    DAC_Check -->|"Verweigert"| Access_Denied_DAC["Zugriff blockiert<br/>(EACCES)"]
    DAC_Check -->|"Erlaubt"| LSM_Check{"2. LSM / MAC-Prüfung<br/>(AppArmor / SELinux)"}
    LSM_Check -->|"Profil gestattet Zugriff"| Access_Granted["Kernel gewährt Ressource"]
    LSM_Check -->|"Keine Regel im Profil"| Access_Denied_MAC["Zugriff blockiert & auditiert<br/>(EPERM / AVC Denial)"]

Der entscheidende Sicherheitsgewinn

Selbst wenn ein Angreifer über eine Remote Code Execution (RCE) im Webserver vollwertigen Root-Zugriff erlangt, verbietet das MAC-Profil den Zugriff auf /etc/shadow, das Ausführen von Bash-Shells oder das Binden unautorisierter Netzwerk-Sockets. Der Exploit bleibt im Sandkasten isoliert.


2. AppArmor Tiefenarchitektur & Profil-Syntax (Debian/Ubuntu)

AppArmor verknüpft Sicherheitsrichtlinien direkt mit dem absoluten Pfad einer Binärdatei. Dadurch ist die Konfiguration extrem lesbar, deklarativ und wartungsarm.

Ein Profil liegt als Textdatei unter /etc/apparmor.d/ (z. B. /etc/apparmor.d/usr.sbin.nginx).

Profil-Modi: complain vs. enforce

  1. Complain-Modus (complain): Richtlinienverstöße werden im Systemprotokoll dokumentiert, der Zugriff wird jedoch nicht blockiert (ideal für Entwicklung, Staging und Profil-Lernen).
  2. Enforce-Modus (enforce): Jeder Zugriff, der nicht explizit gestattet ist, wird vom Kernel unverzüglich mit EPERM blockiert und im Audit-Log dokumentiert.

Die AppArmor-Berechtigungsflags

Innerhalb eines Profils steuern präzise Flags den Zugriff auf Pfade:

Flag Bedeutung Sicherheitswirkung
r Read Erlaubt das Lesen von Dateien.
w Write Erlaubt das Schreiben/Erstellen von Dateien.
m Memory Map Executable Erlaubt das Laden von Binärcode in den Speicher (Shared Libraries).
k Lock Erlaubt das Setzen von Dateisperren (flock).
ix Inherit Execute Führt Unterprogramme im aktuellen Profil weiter aus.
px Profile Execute Wechselt beim Starten des Programms in ein anderes, dediziertes Profil.
cx Child Execute Führt das Programm in einem untergeordneten Kindprofil aus.

Vollständiges Produktions-Profil für einen API-Dienst

Hier ist ein praxistaugliches AppArmor-Profil für einen Daemon (/usr/local/bin/api-daemon):

# /etc/apparmor.d/usr.local.bin.api-daemon
#include <tunables/global>

/usr/local/bin/api-daemon {
  #include <abstractions/base>
  #include <abstractions/nameservice>

  # Nur IPv4/IPv6 TCP-Sockets erlauben
  network inet stream,
  network inet6 stream,

  # Erlaube das Binden an privilegierte Ports (80/443)
  capability net_bind_service,
  capability setuid,
  capability setgid,

  # Binärdatei selbst ausführen und Bibliotheken mappen
  /usr/local/bin/api-daemon mr,
  /lib{,32,64}/** mr,
  /usr/lib{,32,64}/** mr,

  # Konfiguration strikt nur lesend erlauben
  /etc/api-daemon/** r,
  /etc/ssl/certs/** r,

  # Datenverzeichnis: Lesen, Schreiben und Sperren
  /var/lib/api-daemon/** rwk,
  /var/log/api-daemon/** w,

  # Temporäre Dateien im RAM erlauben
  /tmp/api-daemon* rwk,

  # Explizites Verbot sensibler Pfade (Deny überschreibt Allow!)
  deny /etc/shadow r,
  deny /etc/passwd w,
  deny /root/** rwx,
}

3. AppArmor Profil-Lifecycle in Produktion

Das Erstellen robuster Profile erfolgt strukturiert über die AppArmor-Toolchain:

# Installiere die AppArmor-Administrationstools
sudo apt-get install apparmor-utils apparmor-profiles

1. Profil-Status überwachen mit aa-status

# Zeige alle aktiven Profile und deren Ausführungsmodus an
sudo aa-status

2. Interaktives Profil-Lernen mit aa-genprof

aa-genprof generiert ein Basisskelett, schaltet das Profil in den complain-Modus und lauscht auf Systemereignisse:

# Starte das Profiling für den Dienst
sudo aa-genprof /usr/local/bin/api-daemon

Führe nun in einem separaten Terminal alle regulären Funktionen des Dienstes aus (Workload-Test, API-Aufrufe, Log-Rotation, Reload).

3. Log-Parsing mit aa-logprof

Wechsle zurück zu aa-genprof (oder führe separat aa-logprof aus). Das Tool analysiert die protokollierten Zugriffe in /var/log/audit/audit.log (oder /var/log/syslog) und fragt interaktiv für jeden Zugriff:

  • (A)llow: Erlaubt den Zugriff dauerhaft.
  • (D)eny: Verbietet den Zugriff explizit.
  • (G)lob: Erlaubt Zugriff auf das gesamte Verzeichnis via Wildcard (/*).

4. Profil scharfschalten (enforce)

# Profil in den strikten Enforcing-Modus überführen
sudo aa-enforce /etc/apparmor.d/usr.local.bin.api-daemon

# Profil im laufenden Betrieb neu laden
sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.api-daemon

4. SELinux Interna & Typ-Erzwingung (Type Enforcement)

Während AppArmor mit Pfaden arbeitet, verknüpft SELinux Sicherheitsattribute direkt mit Dateisystem-Inodes über Extended Attributes (xattr). Benennt man eine Datei um oder verschiebt sie, behält sie unter SELinux ihr Label!

Der 4-teilige Sicherheitskontext

Jeder Prozess und jede Datei besitzt ein Label nach folgendem Format:

user:role:type:level
system_u:object_r:httpd_sys_content_t:s0
  1. User (system_u): Die SELinux-Benutzeridentität (nicht identisch mit der Linux-UID).
  2. Role (object_r): Die Rolle für Role-Based Access Control (RBAC). Für Dateien immer object_r.
  3. Type (httpd_sys_content_t): Das Herzstück von SELinux – das Type Enforcement. Prozesse und Dateien mit kompatiblen Typen dürfen interagieren.
  4. Level (s0): Multi-Level / Multi-Category Security (MLS/MCS) zur Kapselung (z. B. von Containern).

Sicherheitskontexte inspizieren

# Zeige SELinux-Kontexte von Dateien an (-Z Flag)
ls -laZ /var/www/html/

# Zeige SELinux-Kontexte laufender Prozesse an
ps -eZ | grep httpd

5. SELinux Booleans, Port-Labels & Dateikontexte

SELinux liefert vorkonfigurierte Richtlinien für hunderte Daemons mit. Anstatt Profile neu zu schreiben, passt man das Verhalten über Booleans und Port-Labels an.

1. Booleans steuern mit getsebool und setsebool

Ein Boolean ist ein Ein/Aus-Schalter für bestimmte Dienstprivilegien:

# Prüfe, ob der Webserver ausgehende Netzwerkverbindungen aufbauen darf
getsebool httpd_can_network_connect

# Erlaube ausgehende Verbindungen persistent über Reboots hinweg (-P Flag Pflicht!)
sudo setsebool -P httpd_can_network_connect 1

# Erlaube dem Webserver das Senden von E-Mails
sudo setsebool -P httpd_can_sendmail 1

2. Benutzerdefinierte Netzwerkports zuweisen

Lauscht ein Webserver auf einem Nicht-Standard-Port (z. B. 8080 statt 80), blockiert SELinux den bind()-Syscall sofort. Weise dem Port den korrekten Typ zu:

# Zeige alle autorisierten HTTP-Ports an
sudo semanage port -l | grep http_port_t

# Füge Port 8080/TCP zum HTTP-Port-Typ hinzu
sudo semanage port -a -t http_port_t -p tcp 8080

3. Dateikontexte reparieren: restorecon vs. chcon

Produktionsverbot für chcon

Verwende in der Produktion niemals chcon, um Dateikontexte zu ändern! chcon setzt Labels nur flüchtig. Beim nächsten Relabeling des Systems (touch /.autorelabel) oder nach Dateisystem-Wartungen werden alle flüchtigen Labels unwiderruflich gelöscht.

Verwende stattdessen immer semanage fcontext gepaart mit restorecon:

# Definiere eine permanente Richtlinie für ein benutzerdefiniertes Web-Verzeichnis
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/webdata(/.*)?"

# Wende das permanente Label rekursiv auf das Dateisystem an
sudo restorecon -Rv /srv/webdata

6. AVC-Denial-Forensik & Troubleshooting Runbook

Wird ein Zugriff durch SELinux blockiert, schreibt der Kernel ein AVC (Access Vector Cache) Denial in das Audit-Log (/var/log/audit/audit.log).

1. AVC-Denials aufspüren mit ausearch

# Suche nach allen AVC-Blockaden der letzten 10 Minuten
sudo ausearch -m avc -ts recent

# Detaillierte Ursachenanalyse mit Lösungsvorschlägen via audit2why
sudo ausearch -m avc -ts recent | audit2why

audit2why übersetzt kryptische Kernel-Dumps in verständliches Klartext-Feedback (z. B.: „Missing boolean httpd_can_network_connect“).

2. Eigene Richtlinienmodule mit audit2allow kompilieren

Wenn eine legitime Anwendung Zugriffe benötigt, die von keiner Standard-Richtlinie abgedeckt werden, generiert man ein Type-Enforcement-Modul:

# Generiere aus den jüngsten Denials eine lesbare TE-Datei und ein kompilierbares PP-Modul
sudo ausearch -m avc -ts recent | audit2allow -M custom_app_policy

# Prüfe die generierte Typendatei vor der Aktivierung sorgfältig!
cat custom_app_policy.te

# Installiere das kompilierte Sicherheitsmodul im laufenden Kernel
sudo semodule -i custom_app_policy.pp

Vorsicht vor blindem audit2allow

Führe niemals blind audit2allow -a -M ... aus! Wenn ein Angreifer gerade versucht hat, /etc/shadow zu lesen, und du audit2allow ausführst, generierst du eine Regel, die dem Angreifer künftig das Auslesen der Passwort-Hashes ausdrücklich erlaubt!

Enterprise Troubleshooting-Tabelle

Problem / Symptom Ursache Lösungsweg
AppArmor blockiert Datei Fehlender Pfad im Profil sudo aa-logprof ausführen oder Pfad mit r/w ergänzen.
AppArmor Daemon startet nicht Profil-Syntaxfehler sudo apparmor_parser -r /etc/apparmor.d/<profil> (zeigt Zeilennummer).
SELinux blockiert Webroot Falscher Dateikontext sudo restorecon -Rv /pfad ausführen.
SELinux blockiert Port Port nicht im Label-Set sudo semanage port -a -t <typ> -p tcp <port>.
SELinux Notfall-Entstörung Unklarer Produktions-Block sudo setenforce 0 (schaltet temporär auf Permissive für Tests).

Mit Mandatory Access Control erhält dein Linux-Server die stärkste verfügbare In-Kernel-Barriere: Prozesse agieren streng nach dem Least-Privilege-Prinzip, und ein kompromittierter Dienst kann niemals die Herrschaft über das Gesamtsystem erlangen.