Linux/SELinux/Praxis/5: Unterschied zwischen den Versionen
Die Seite wurde neu angelegt: „ == Grundlagen der PAM-Architektur == '''PAM (Pluggable Authentication Modules)''' ist ein modulares Subsystem, über das Anwendungen wie <code>login</code>, <code>sshd</code>, <code>su</code> und andere Vorgänge im Zusammenhang mit der Anmeldung an das System delegieren. Die PAM-Konfiguration befindet sich in der Regel unter <code>/etc/pam.d/</code>, wo für jeden Dienst ein eigener Modul-Stack definiert ist. === Grundlegende PAM-Gruppen === * <code>…“ |
Keine Bearbeitungszusammenfassung |
||
| Zeile 1: | Zeile 1: | ||
== Grundlagen der PAM-Architektur == | == Grundlagen der PAM-Architektur == | ||
'''PAM (Pluggable Authentication Modules)''' ist ein modulares Subsystem, über das Anwendungen wie | '''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 | 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 === | === 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 | 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 === | === pam_selinux.so === | ||
Ein Modul aus der Gruppe | 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 ( | 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 ==== | ==== open_session ==== | ||
Nachdem der Benutzer die Login-Prüfung erfolgreich durchlaufen hat, wechselt PAM in die Phase | 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 ===== | ===== Funktionsprinzip ===== | ||
* Zuordnung von Linux user zu SELinux user. Verwendet wird die Datei | * 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 | * 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_contexts sowie benutzerspezifische Einstellungen unter /etc/selinux/<POLICY>/contexts/users/. | ||
* | * pam_selinux.so konfiguriert 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. | * Danach startet das Login-Programm die Shell des Benutzers, und die Shell erscheint bereits mit dem korrekten SELinux-Kontext. | ||
==== close_session ==== | ==== close_session ==== | ||
Wenn der Benutzer seine Arbeit beendet und die Sitzung geschlossen wird, ruft PAM die Phase | Wenn der Benutzer seine Arbeit beendet und die Sitzung geschlossen wird, ruft PAM die Phase close_session auf. | ||
Das Modul | 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 == | == Erweiterte Isolation == | ||
| Zeile 38: | Zeile 37: | ||
=== pam_sepermit.so === | === 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 | 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 | '''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'''. | Das Modul wird eingesetzt, wenn eine Anmeldung '''nur dann erlaubt werden soll, wenn SELinux die Richtlinie tatsächlich erzwingt'''. | ||
==== Konfiguration ==== | ==== Konfiguration ==== | ||
Standardmäßig verwendet das Modul die Datei | 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 | In sepermit.conf enthält jede Zeile eine der folgenden Varianten: | ||
* einen konkreten Benutzernamen (zum Beispiel | * einen konkreten Benutzernamen (zum Beispiel alice) | ||
* eine Gruppe über | * eine Gruppe über @group (zum Beispiel @devops) | ||
* einen SELinux user über | * einen SELinux user über %seuser (zum Beispiel %user_u) | ||
Zusätzlich können die Optionen | Zusätzlich können die Optionen exclusive oder ignore angegeben werden. | ||
* | * exclusive beschränkt den Benutzer auf eine einzige Login-Sitzung und beendet seine Prozesse beim Abmelden. | ||
* | * ignore bewirkt, dass das Modul im Enforcing-Modus PAM_IGNORE und in den übrigen Modi PAM_AUTH_ERR zurückgibt. Die weitere Entscheidung trifft dann der restliche PAM-Stack. | ||
=== pam_namespace.so === | === pam_namespace.so === | ||
Das gemeinsame Verzeichnis | Das gemeinsame Verzeichnis /tmp ist in einem Mehrbenutzersystem traditionell eine Quelle verschiedener Risiken, etwa: | ||
* Manipulation temporärer Dateien | * Manipulation temporärer Dateien | ||
| Zeile 68: | Zeile 67: | ||
'''Dieses Modul richtet für die Benutzersitzung private Namensräume mit sogenannten ''polyinstantiated directories'' ein.''' | '''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 | 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 ==== | ==== Konfiguration ==== | ||
Die zentrale Konfigurationsdatei ist | 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 | * Format einer Regel in namespace.conf: | ||
polydir instance_prefix method list_of_uids | |||
* | * polydir — Zielverzeichnis | ||
* | * instance_prefix — Basispfad für die Instanzen | ||
* | * method — Trennungsmethode | ||
* | * list_of_uids — Ausnahmen, für die die Verzeichnisaufteilung nicht angewendet wird | ||
===== Methoden ===== | ===== Methoden ===== | ||
namespace.conf unterstützt mehrere Methoden: | |||
* | * user — Trennung nach Benutzername | ||
* | * level — Trennung nach MLS/MCS-Level und Benutzername | ||
* | * context — Trennung nach vollständigem Sicherheitskontext und Benutzername | ||
* | * tmpfs — die Instanz wird als separates tmpfs erzeugt | ||
* | * tmpdir — es wird ein temporäres Verzeichnis erstellt | ||
Für die Zugriffskontrolle mit SELinux sind die Methoden | Für die Zugriffskontrolle mit SELinux sind die Methoden context und level besonders nützlich. | ||
Wichtig: Für den korrekten Betrieb ... | Wichtig: Für den korrekten Betrieb ... | ||
=== pam_oddjob_mkhomedir.so === | === 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 | 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. | Dieses Modul ist nützlich, wenn ein lokales Home-Verzeichnis erst beim ersten tatsächlichen Login angelegt werden soll. | ||
=== Praxis zu | === Praxis zu pam_namespace.so === | ||
Isolation von | Isolation von /tmp unterschiedlicher Sitzungen mit Hilfe von pam_namespace.so | ||
Für | 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 | * Benutzer vorbereiten | ||
useradd -m alice | |||
useradd -m bob | useradd -m bob | ||
passwd alice | passwd alice | ||
passwd bob | passwd bob | ||
* Für diese Übung kann der Modus | * Für diese Übung kann der Modus permissive gesetzt 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 | * Boolean prüfen und aktivieren, damit diese Funktion in der Policy erlaubt wird | ||
setsebool -P allow_polyinstantiation 1 | |||
getsebool allow_polyinstantiation | getsebool allow_polyinstantiation | ||
* Verzeichnis für die | * Verzeichnis für die /tmp-Instanzen anlegen | ||
mkdir /tmp-inst --mode 000 | |||
* Nach der Erstellung muss dafür der erwartete SELinux-Kontext wiederhergestellt werden. | * Nach der Erstellung muss dafür der erwartete SELinux-Kontext wiederhergestellt werden. | ||
restorecon -Fv /tmp-inst | |||
* Prüfung | * Prüfung | ||
ls -ldZ /tmp-inst | |||
* Anschließend | * Anschließend namespace.conf konfigurieren. Zunächst eine Sicherungskopie anlegen. | ||
cp /etc/security/namespace.conf /etc/security/namespace.conf.bak | |||
* Danach muss in die Datei | * Danach muss in die Datei /etc/security/namespace.conf folgende Konfiguration eingetragen werden: | ||
/tmp /tmp-inst/ user root,adm | |||
* Diese Zeile bedeutet Folgendes: | * Diese Zeile bedeutet Folgendes: | ||
** | ** /tmp — das logische Verzeichnis, das isoliert werden soll | ||
** | ** /tmp-inst/ — der Basispfad, unter dem die realen Instanzen abgelegt werden | ||
** | ** user — Trennungsmethode nach Benutzername. Zur Veranschaulichung wird hier die Methode user verwendet. | ||
** | ** root,adm — Liste der Ausnahmen | ||
* Nun | * Nun pam_namespace.so für su aktivieren. Dazu muss in der Datei /etc/pam.d/su im Abschnitt session Folgendes ergänzt werden: | ||
session required pam_namespace.so unmnt_remnt | |||
Wie bereits erwähnt, gehört | 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 | * Damit ist die Konfiguration abgeschlossen. Nun kann aus zwei verschiedenen Terminals eine Anmeldung für die Benutzer alice und bob mit Hilfe von su initiiert werden. | ||
* Befehlssatz zur Prüfung für | * Befehlssatz zur Prüfung für alice: | ||
su - alice | |||
findmnt --mountpoint /tmp | findmnt --mountpoint /tmp | ||
touch /tmp/alice.test | touch /tmp/alice.test | ||
ls -la /tmp | ls -la /tmp | ||
* Zur Prüfung für | * Zur Prüfung für bob: | ||
su - bob | |||
findmnt --mountpoint /tmp | findmnt --mountpoint /tmp | ||
ls -la /tmp | ls -la /tmp | ||
touch /tmp/bob.test | touch /tmp/bob.test | ||
ls -la /tmp | ls -la /tmp | ||
Der Befehl | 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 ==== | ==== Rückbau ==== | ||
Nach Abschluss des Labors können die Änderungen manuell zurückgenommen werden. | Nach Abschluss des Labors können die Änderungen manuell zurückgenommen werden. | ||
* Aus | * Aus /etc/pam.d/su muss die Zeile | ||
session required pam_namespace.so unmnt_remnt | |||
entfernt werden. | entfernt werden. | ||
* Anschließend die ursprüngliche | * Anschließend die ursprüngliche namespace.conf wiederherstellen | ||
cp /etc/security/namespace.conf.bak /etc/security/namespace.conf | |||
* Danach den Boolean wieder deaktivieren | * Danach den Boolean wieder deaktivieren | ||
setsebool -P allow_polyinstantiation 0 | |||
* Abschließend das angelegte Verzeichnis und die Benutzer entfernen | * Abschließend das angelegte Verzeichnis und die Benutzer entfernen | ||
rm -rf /tmp-inst | |||
userdel bob | userdel bob | ||
userdel alice | userdel alice | ||
== Systemd == | == Systemd == | ||
Nahezu jeder Dienst in Linux erzeugt beim Start oder im laufenden Betrieb Hilfsobjekte: Verzeichnisse unter | 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 | 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 | 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. | # 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 | # 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 Basistyp var_run_t untersagt sein, sodass ein spezifischer Kontext erforderlich ist (zum Beispiel myapp_var_run_t). | ||
=== systemd-tmpfiles === | === systemd-tmpfiles === | ||
Zur Verwaltung temporärer Dateien und Verzeichnisse dient das Werkzeug | 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 ( | * 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 | * Dadurch wird das korrekte Label automatisch gesetzt, ohne dass nach jedem Neustart manuell restorecon ausgeführt werden muss. | ||
==== Regeln ==== | ==== Regeln ==== | ||
Regeln können unter folgenden Pfaden gefunden werden: | 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: | Die Regeln haben folgendes Format: | ||
Typ Pfad Modus Benutzer Gruppe Alter Argument | |||
* '''Typ:''' Gibt an, was getan werden soll. | * '''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 | * '''Pfad:''' Absoluter Pfad zum Objekt | ||
* '''Modus:''' Zugriffsrechte (zum Beispiel | * '''Modus:''' Zugriffsrechte (zum Beispiel 0755) | ||
* '''Benutzer/Gruppe (UID/GID):''' Eigentümer des Objekts | * '''Benutzer/Gruppe (UID/GID):''' Eigentümer des Objekts | ||
==== Regel anlegen ==== | ==== Regel anlegen ==== | ||
Hier wird der Prozess zur Vorbereitung einer Umgebung unter Verwendung des Typs | 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. | * 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 myapp erstellt werden. | |||
nano /etc/tmpfiles.d/myapp.conf | |||
Inhalt der Datei: | |||
Inhalt der Datei: | d /run/myapp 0755 root root - - | ||
z /run/myapp 0755 root root - - | |||
z /run/myapp 0755 root root - - | |||
* Erläuterung: | * Erläuterung: | ||
| Zeile 250: | Zeile 250: | ||
* systemd erzeugt die Objekte beim Systemstart selbstständig, der Vorgang kann jedoch auch manuell ausgelöst werden: | * 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 | * Ergebnis prüfen | ||
ls -Zld /run/myapp | |||
Ausgabe: | Ausgabe: | ||
# ls -Zld /run/myapp | |||
drwxr-xr-x. 2 root root system_u:object_r:httpd_runtime_t:s0 40 ... /run/myapp | drwxr-xr-x. 2 root root system_u:object_r:httpd_runtime_t:s0 40 ... /run/myapp | ||
'''Der Dienst''' | '''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 | 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. | |||
[[Kategorie:Linux/SELinux/Praxis]] | [[Kategorie:Linux/SELinux/Praxis]] | ||
Version vom 28. März 2026, 09:39 Uhr
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_contexts sowie benutzerspezifische Einstellungen unter /etc/selinux/<POLICY>/contexts/users/.
- pam_selinux.so konfiguriert 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.
- exclusive beschränkt den Benutzer auf eine einzige Login-Sitzung und beendet seine Prozesse beim Abmelden.
- ignore bewirkt, dass das Modul im Enforcing-Modus PAM_IGNORE und in den übrigen Modi PAM_AUTH_ERR zurü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 — Zielverzeichnis
- instance_prefix — Basispfad für die Instanzen
- method — Trennungsmethode
- list_of_uids — Ausnahmen, für die die Verzeichnisaufteilung nicht angewendet wird
Methoden
namespace.conf unterstützt mehrere Methoden:
- user — Trennung nach Benutzername
- level — Trennung nach MLS/MCS-Level und Benutzername
- context — Trennung nach vollständigem Sicherheitskontext und Benutzername
- tmpfs — die Instanz wird als separates tmpfs erzeugt
- tmpdir — 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 permissive gesetzt 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.conf konfigurieren. Zunächst eine Sicherungskopie anlegen.
cp /etc/security/namespace.conf /etc/security/namespace.conf.bak
- Danach muss in die Datei /etc/security/namespace.conf folgende 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 werden
- user — Trennungsmethode nach Benutzername. Zur Veranschaulichung wird hier die Methode user verwendet.
- root,adm — Liste der Ausnahmen
- Nun pam_namespace.so für su aktivieren. Dazu muss in der Datei /etc/pam.d/su im Abschnitt session Folgendes 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 alice und bob mit Hilfe von su initiiert 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/su muss die Zeile
session required pam_namespace.so unmnt_remnt
entfernt werden.
- Anschließend die ursprüngliche namespace.conf wiederherstellen
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 Basistyp var_run_t untersagt sein, sodass ein spezifischer Kontext erforderlich ist (zum Beispiel myapp_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 restorecon ausgefü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 myapp erstellt 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.