Linux/SELinux/Praxis/5
Grundlagen der PAM-Architektur
PAM (Pluggable Authentication Modules) ist ein modulares Subsystem, über das Anwendungen wie login, sshd, su und andere Vorgänge im Zusammenhang mit der Anmeldung an das System delegieren.
Die PAM-Konfiguration befindet sich in der Regel unter /etc/pam.d/, wo für jeden Dienst ein eigener Modul-Stack definiert ist.
Grundlegende PAM-Gruppen
auth— Bestätigung der Identität des Benutzers und initiale Vergabe von Credentials;account— Prüfung, ob der Zugriff auf den Dienst als solcher erlaubt ist;password— Änderung des Authentifizierungs-Tokens;session— Aktionen, die vor der Bereitstellung einer Sitzung und nach deren Beendigung ausgeführt werden müssen.
Für SELinux ist insbesondere die Gruppe session kritisch, da die Zuweisung des SELinux-Kontexts eines Benutzers zur Vorbereitung der Laufzeitumgebung für die zukünftige Sitzung gehört.
pam_selinux.so
Ein Modul aus der Gruppe session.
Seine Aufgabe besteht darin, den Sicherheitskontext für den als Nächstes gestarteten Prozess festzulegen. Während des Ablaufs eines Login-Programms (login, sshd usw.) bereitet das Modul den SELinux-Kontext für den nächsten zu startenden Prozess vor.
open_session
Nachdem der Benutzer die Login-Prüfung erfolgreich durchlaufen hat, wechselt PAM in die Phase open_session. In diesem Moment bereitet pam_selinux.so den SELinux-Kontext für die Benutzersitzung vor.
Funktionsprinzip
- Zuordnung von Linux user zu SELinux user. Verwendet wird die Datei
seusers. - Nachdem der SELinux user ermittelt wurde, muss das Modul bestimmen, welcher Login-Kontext für diese Sitzung gewählt werden kann und soll. Verwendet werden die Datei
default_contextssowie benutzerspezifische Einstellungen unter/etc/selinux/<POLICY>/contexts/users/. pam_selinux.sokonfiguriert das System so, dass der als Nächstes gestartete Prozess bereits in diesem Kontext startet.- Danach startet das Login-Programm die Shell des Benutzers, und die Shell erscheint bereits mit dem korrekten SELinux-Kontext.
close_session
Wenn der Benutzer seine Arbeit beendet und die Sitzung geschlossen wird, ruft PAM die Phase close_session auf.
Das Modul pam_selinux.so entfernt die temporären Einstellungen, die mit der geöffneten Sitzung verbunden sind, und stellt den vorherigen Zustand wieder her.
Erweiterte Isolation
Hier werden noch einige weitere Module behandelt.
pam_sepermit.so
Dieses Modul erlaubt oder verweigert die Anmeldung am System abhängig davon, ob SELinux im Modus Enforcing arbeitet. Es stellt die Gruppen auth und account bereit, beteiligt sich also unmittelbar an der Entscheidung, ob ein Login in der Kette weiter zugelassen wird.
Wenn ein Benutzer oder eine Gruppe auf eine Regel aus der Konfiguration passt, wird die Anmeldung nur im Enforcing-Modus erlaubt. Im Modus permissive oder disabled gibt das Modul einen Zugriffsfehler zurück. Für Benutzer, die zu keinem Eintrag passen, wird die Entscheidung an andere PAM-Module weitergereicht.
Das Modul wird eingesetzt, wenn eine Anmeldung nur dann erlaubt werden soll, wenn SELinux die Richtlinie tatsächlich erzwingt.
Konfiguration
Standardmäßig verwendet das Modul die Datei /etc/security/sepermit.conf. Falls diese Datei nicht vorhanden ist, wird die Vendor-Datei aus /usr/share/pam/security/sepermit.conf verwendet.
In sepermit.conf enthält jede Zeile eine der folgenden Varianten:
- einen konkreten Benutzernamen (zum Beispiel
alice) - eine Gruppe über
@group(zum Beispiel@devops) - einen SELinux user über
%seuser(zum Beispiel%user_u)
Zusätzlich können die Optionen exclusive oder ignore angegeben werden.
exclusivebeschränkt den Benutzer auf eine einzige Login-Sitzung und beendet seine Prozesse beim Abmelden.ignorebewirkt, dass das Modul im Enforcing-ModusPAM_IGNOREund in den übrigen ModiPAM_AUTH_ERRzurückgibt. Die weitere Entscheidung trifft dann der restliche PAM-Stack.
pam_namespace.so
Das gemeinsame Verzeichnis /tmp ist in einem Mehrbenutzersystem traditionell eine Quelle verschiedener Risiken, etwa:
- Manipulation temporärer Dateien
- Race Conditions
- unerwünschte Überschneidung von Arbeitsdaten zwischen Benutzern
- Ansammlung von Artefakten, die das Verhalten von Anwendungen in einer anderen Sitzung beeinflussen
Dieses Modul richtet für die Benutzersitzung private Namensräume mit sogenannten polyinstantiated directories ein.
Die Idee der polyinstantiated directories besteht darin, dass dasselbe logische Verzeichnis, zum Beispiel /tmp, unterschiedliche physische Instanzen für verschiedene Benutzer oder — in SELinux-Szenarien — für unterschiedliche Sicherheitskontexte und Levels besitzen kann.
pam_namespace.so wird als letzte Zeile der Gruppe session in der PAM-Konfiguration des jeweiligen Dienstes eingebunden. Entsprechend wird es erst nach pam_selinux.so aktiv und arbeitet somit mit einem bereits bestimmten Kontext.
Konfiguration
Die zentrale Konfigurationsdatei ist /etc/security/namespace.conf. Falls sie nicht vorhanden ist, wird /usr/share/pam/security/namespace.conf verwendet. Zusätzlich werden .conf-Dateien aus den Verzeichnissen /etc/security/namespace.d/ und /usr/share/pam/security/namespace.d/ eingelesen.
- Format einer Regel in
namespace.conf:
polydir instance_prefix method list_of_uids
polydir— Zielverzeichnisinstance_prefix— Basispfad für die Instanzenmethod— Trennungsmethodelist_of_uids— Ausnahmen, für die die Verzeichnisaufteilung nicht angewendet wird
Methoden
namespace.conf unterstützt mehrere Methoden:
user— Trennung nach Benutzernamelevel— Trennung nach MLS/MCS-Level und Benutzernamecontext— Trennung nach vollständigem Sicherheitskontext und Benutzernametmpfs— die Instanz wird als separatestmpfserzeugttmpdir— es wird ein temporäres Verzeichnis erstellt
Für die Zugriffskontrolle mit SELinux sind die Methoden context und level besonders nützlich.
Wichtig: Für den korrekten Betrieb ...
pam_oddjob_mkhomedir.so
pam_oddjob_mkhomedir.so arbeitet in der Gruppe session. Es prüft, ob das Home-Verzeichnis des Benutzers existiert. Falls das Verzeichnis nicht existiert, initiiert das Modul dessen Erstellung. Im Unterschied zum Standardmodul pam_mkhomedir.so kann dieses Modul Home-Verzeichnisse mit korrekten SELinux-Labels anlegen.
Für den Betrieb dieses Moduls werden das Paket oddjob-mkhomedir, der laufende Dienst oddjobd sowie die zugehörige D-Bus- und oddjobd-Konfiguration benötigt. Außerdem müssen die entsprechenden Dateipräfixe in der aktiven Policy vorhanden sein.
Dieses Modul ist nützlich, wenn ein lokales Home-Verzeichnis erst beim ersten tatsächlichen Login angelegt werden soll.
Praxis zu pam_namespace.so
Isolation von /tmp unterschiedlicher Sitzungen mit Hilfe von pam_namespace.so
Für su wird die Option unmnt_remnt empfohlen, da bei solchen Programmen die Polyinstanziierung möglicherweise bereits für die ursprüngliche Login-Sitzung eingerichtet ist und vor einer neuen Einrichtung sauber zerlegt und erneut aufgebaut werden muss.
- Benutzer vorbereiten
useradd -m alice
useradd -m bob
passwd alice
passwd bob
- Für diese Übung kann der Modus
permissivegesetzt werden, da hier keine Blockierungen benötigt werden; wichtig ist lediglich, dass SELinux aktiviert ist.
setenforce 0
- Boolean prüfen und aktivieren, damit diese Funktion in der Policy erlaubt wird
setsebool -P allow_polyinstantiation 1
getsebool allow_polyinstantiation
- Verzeichnis für die
/tmp-Instanzen anlegen
mkdir /tmp-inst --mode 000
- Nach der Erstellung muss dafür der erwartete SELinux-Kontext wiederhergestellt werden.
restorecon -Fv /tmp-inst
- Prüfung
ls -ldZ /tmp-inst
- Anschließend
namespace.confkonfigurieren. Zunächst eine Sicherungskopie anlegen.
cp /etc/security/namespace.conf /etc/security/namespace.conf.bak
- Danach muss in die Datei
/etc/security/namespace.conffolgende Konfiguration eingetragen werden:
/tmp /tmp-inst/ user root,adm
- Diese Zeile bedeutet Folgendes:
/tmp— das logische Verzeichnis, das isoliert werden soll/tmp-inst/— der Basispfad, unter dem die realen Instanzen abgelegt werdenuser— Trennungsmethode nach Benutzername. Zur Veranschaulichung wird hier die Methodeuserverwendet.root,adm— Liste der Ausnahmen
- Nun
pam_namespace.sofürsuaktivieren. Dazu muss in der Datei/etc/pam.d/suim AbschnittsessionFolgendes ergänzt werden:
session required pam_namespace.so unmnt_remnt
Wie bereits erwähnt, gehört pam_namespace.so zum Typ session, da es weder die Passwortprüfung noch das eigentliche Zugangsrecht behandelt, sondern die Laufzeitumgebung für eine neue Benutzersitzung vorbereitet.
- Damit ist die Konfiguration abgeschlossen. Nun kann aus zwei verschiedenen Terminals eine Anmeldung für die Benutzer
aliceundbobmit Hilfe vonsuinitiiert werden. - Befehlssatz zur Prüfung für
alice:
su - alice
findmnt --mountpoint /tmp
touch /tmp/alice.test
ls -la /tmp
- Zur Prüfung für
bob:
su - bob
findmnt --mountpoint /tmp
ls -la /tmp
touch /tmp/bob.test
ls -la /tmp
Der Befehl findmnt --mountpoint /tmp zeigt, dass /tmp innerhalb der Sitzung nicht mehr einfach das gemeinsame Systemverzeichnis ist, sondern aus einer separaten Instanz eingebunden wird, die auf Grundlage von /tmp-inst/ aufgebaut wurde.
Rückbau
Nach Abschluss des Labors können die Änderungen manuell zurückgenommen werden.
- Aus
/etc/pam.d/sumuss die Zeile
session required pam_namespace.so unmnt_remnt
entfernt werden.
- Anschließend die ursprüngliche
namespace.confwiederherstellen
cp /etc/security/namespace.conf.bak /etc/security/namespace.conf
- Danach den Boolean wieder deaktivieren
setsebool -P allow_polyinstantiation 0
- Abschließend das angelegte Verzeichnis und die Benutzer entfernen
rm -rf /tmp-inst
userdel bob
userdel alice
Systemd
Nahezu jeder Dienst in Linux erzeugt beim Start oder im laufenden Betrieb Hilfsobjekte: Verzeichnisse unter /run, PID-Dateien, UNIX-Sockets, Journal-Verzeichnisse, temporäre Dateien, Caches und andere Betriebsdaten.
Verzeichnisse wie /run oder /tmp können als temporäre Dateisysteme (tmpfs) eingehängt sein. Das bedeutet, dass ihr Inhalt bei jedem Neustart des Servers vollständig gelöscht wird.
Wenn ein Dienst (zum Beispiel ein Webserver oder ein DBMS) für seinen Betrieb ein eigenes Verzeichnis unter /run benötigt (zum Beispiel /run/myapp/), entstehen zwei Probleme:
- Das Verzeichnis muss bei jedem Systemstart erneut angelegt werden, bevor der Dienst versucht, darauf zuzugreifen.
- Wenn der Dienst das Verzeichnis selbst anlegt, kann es den Standardkontext des Elternverzeichnisses erben (zum Beispiel
var_run_t). In einer strikten SELinux-Policy kann dem Dienst die Arbeit mit dem Basistypvar_run_tuntersagt sein, sodass ein spezifischer Kontext erforderlich ist (zum Beispielmyapp_var_run_t).
systemd-tmpfiles
Zur Verwaltung temporärer Dateien und Verzeichnisse dient das Werkzeug systemd-tmpfiles. Beim Systemstart (oder per Timer) liest es Konfigurationsdateien aus den Verzeichnissen /etc/tmpfiles.d/, /run/tmpfiles.d/ und /usr/lib/tmpfiles.d/ und erstellt, entfernt oder bereinigt Dateien und Verzeichnisse entsprechend den Regeln.
systemd-tmpfiles ist eng mit SELinux integriert:
- Beim Erzeugen eines beliebigen Objekts greift das Werkzeug automatisch auf die SELinux-Kontextdatenbank (
file_contexts) zu. - Dadurch wird das korrekte Label automatisch gesetzt, ohne dass nach jedem Neustart manuell
restoreconausgeführt werden muss.
Regeln
Regeln können unter folgenden Pfaden gefunden werden:
/usr/lib/tmpfiles.d/— vordefinierte Regeln/run/tmpfiles.d/— Runtime-Regeln/etc/tmpfiles.d/— lokale und administrative Regeln
Die Regeln haben folgendes Format:
Typ Pfad Modus Benutzer Gruppe Alter Argument
- Typ: Gibt an, was getan werden soll.
d(Verzeichnis anlegen, falls es nicht existiert)f(Datei anlegen)z(SELinux-Kontext und Rechte wiederherstellen, ohne das Objekt zu erzeugen)Z(SELinux-Kontext rekursiv wiederherstellen)
- Pfad: Absoluter Pfad zum Objekt
- Modus: Zugriffsrechte (zum Beispiel
0755) - Benutzer/Gruppe (UID/GID): Eigentümer des Objekts
Regel anlegen
Hier wird der Prozess zur Vorbereitung einer Umgebung unter Verwendung des Typs httpd_runtime_t für einen neuen Dienst myapp demonstriert, der eine PID-Datei im Verzeichnis /run/myapp benötigt.
- Zunächst muss eine File-Context-Regel in die SELinux-Policy-Datenbank eingetragen werden, damit das System weiß, welcher Kontext für den benötigten Pfad erwartet wird.
semanage fcontext -a -t httpd_runtime_t "/run/myapp(/.*)?"
- Danach muss eine Konfigurationsdatei für den Dienst
myapperstellt werden.
nano /etc/tmpfiles.d/myapp.conf
Inhalt der Datei:
d /run/myapp 0755 root root - -
z /run/myapp 0755 root root - -
- Erläuterung:
- Die erste Zeile legt das Verzeichnis an, falls es noch nicht existiert.
- Die zweite Zeile bringt das Verzeichnis explizit in den erwarteten Zustand zurück und stellt den SELinux-Kontext dafür wieder her.
- systemd erzeugt die Objekte beim Systemstart selbstständig, der Vorgang kann jedoch auch manuell ausgelöst werden:
systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf
- Ergebnis prüfen
ls -Zld /run/myapp
Ausgabe:
# ls -Zld /run/myapp
drwxr-xr-x. 2 root root system_u:object_r:httpd_runtime_t:s0 40 ... /run/myapp
Der Dienst systemd-tmpfiles hat das Verzeichnis erfolgreich mit dem erforderlichen Kontext vorbereitet.
In modernen systemd-Versionen werden für einfache Aufgaben häufig Direktiven wie RuntimeDirectory= direkt in der Unit-Datei eines Dienstes (zum Beispiel in myapp.service) verwendet. Diese Direktive arbeitet nach einem ähnlichen Prinzip: systemd erstellt das Verzeichnis vor dem Start des Dienstes und wendet darauf automatisch die Kontextregeln aus der SELinux-Datenbank an.
tmpfiles.d bleibt jedoch für komplexere Szenarien, die Bereinigung alter Dateien und die Konfiguration gemeinsam genutzter Ressourcen unverzichtbar.