Rechte unter Linux beantworten die Frage „wer darf diese Datei lesen“. AppArmor beantwortet eine andere: „was darf dieses Programm überhaupt tun“. Der Unterschied zeigt sich bei einem Einbruch. Eine Web-Shell läuft unter dem Benutzer des Webservers und erbt dessen sämtliche Rechte — also Lesezugriff auf das halbe System. Ein AppArmor-Profil begrenzt den Prozess auf die Liste dessen, was er für seine Arbeit braucht, und ein Versuch, /etc/shadow zu lesen oder /bin/bash zu starten, endet mit einer Ablehnung, unabhängig von den Rechten des Benutzers.

Was bereits aktiv ist

sudo aa-status

Die Ausgabe beantwortet drei Fragen: wie viele Profile geladen sind, wie viele davon im enforce- und im complain-Modus laufen und welche Prozesse ganz ohne Profil arbeiten. Auf einem typischen Ubuntu finden sich einige Dutzend Profile, aber fast alle für Hilfsprogramme wie man und tcpdump. Die zentralen Dienste — nginx, Apache, PHP-FPM — fehlen in der Liste der begrenzten Prozesse üblicherweise.

Drei Modi sind auseinanderzuhalten:

  • enforce — die Regeln greifen, alles Überzählige wird verboten;
  • complain — Verstöße werden nur ins Journal geschrieben, nichts wird blockiert. Der Modus zum Einrichten;
  • unconfined — es gibt kein Profil, das Programm läuft ohne Einschränkungen.

Der nützlichste Teil der aa-status-Ausgabe ist der letzte: Prozesse, die am Netz lauschen und durch nichts begrenzt sind. Das ist die Liste, mit der man anfängt.

Die Werkzeuge

sudo apt install apparmor-utils

Ohne dieses Paket gibt es die Befehle aa-complain, aa-enforce und aa-logprof im System nicht, obwohl AppArmor selbst läuft.

Wie Sie ein Profil aktivieren, ohne den Dienst anzuhalten

Die Reihenfolge ist grundlegend. Ein Profil, das sofort auf enforce gesetzt wird, verbietet dem Dienst mit hoher Wahrscheinlichkeit etwas Notwendiges, und er hört auf zu arbeiten — meist nicht sofort, sondern bei einer seltenen Operation wie einem Datei-Upload oder dem Versand von Mail.

Die richtige Abfolge:

sudo aa-complain /etc/apparmor.d/usr.sbin.nginx

Eine Woche Betrieb in diesem Modus, einschließlich aller außergewöhnlichen Abläufe: eine Sicherung, ein Update, das Hochladen großer Dateien. Danach wird das Angesammelte durchgegangen:

sudo aa-logprof

Der Befehl geht die aufgezeichneten Verstöße durch und fragt zu jedem, ob er erlaubt werden soll. Hier ist Aufmerksamkeit gefragt: Erlauben Sie das, was wirklich zur Arbeit des Dienstes gehört, und nicht alles der Reihe nach — sonst entsteht ein Profil, das alles erlaubt, und der Sinn ist dahin.

Und erst dann:

sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx

Wo die Ablehnungen zu sehen sind

Alle Verstöße landen im Kernel-Journal:

sudo journalctl -k | grep -i apparmor
sudo grep 'apparmor="DENIED"' /var/log/audit/audit.log

Die zweite Datei existiert, wenn auditd installiert ist — mit ihm sind die Einträge merklich ausführlicher. Ein Ablehnungseintrag zeigt den Profilnamen, die angeforderte Operation und den angesprochenen Pfad; das genügt, um zu entscheiden, ob das Profil zu korrigieren ist oder ob man sich über das Auslösen freuen darf.

Ein Symptom lohnt sich zu merken: Ein Dienst verhält sich seltsam — liest keine Konfiguration, schreibt nicht in ein Verzeichnis, öffnet keinen Socket —, während in seinen eigenen Protokollen ein Fehler „Zugriff verweigert“ bei offensichtlich richtigen Rechten steht. Das ist fast immer AppArmor, und das Erste ist ein Blick ins Kernel-Journal.

Eine praktische, keine theoretische Maßnahme

Ein Profil für PHP-FPM oder nginx zahlt sich auf konkrete Weise aus. Ist der Prozess begrenzt, kann eine Web-Shell, die auf die Website gelangt ist, weder Systemdateien lesen noch eine Shell starten noch außerhalb der erlaubten Verzeichnisse schreiben. Eine gehackte Website bleibt eine gehackte Website, statt sich in Zugriff auf die gesamte Maschine zu verwandeln — und genau dieser Übergang macht den Großteil des Schadens aus.

Eine vernünftige Reihenfolge der Einführung: zuerst ein Profil für das, was ins Internet zeigt (Webserver, PHP-FPM), dann für die Datenbanken, danach nach Bedarf. Alles auf einmal zu aktivieren ist nicht nötig, und einen universellen fertigen Satz gibt es nicht: Ein Profil hängt davon ab, wo Ihre Dateien liegen.

Was regelmäßig zu prüfen ist

Profile fallen häufiger in den unbegrenzten Zustand zurück, als man denkt: Ein Paket-Update kann eine Profildatei ersetzen, manuelles Debuggen lässt einen Dienst in complain zurück, und ein neuer Dienst kommt ganz ohne Profil. Zwei Zahlen sind nützlich: wie viele Profile in enforce laufen und wie viele netzseitige Prozesse unbegrenzt sind. Eine Veränderung bei einer davon ist es wert, davon zu wissen. Wie das auf einer Seite zusammengeführt aussieht, zeigt die Demo unten.