ADMIN

2021

10

2021-10-01T12:00:00

Endpoint Security

SCHWERPUNKT

088

Sicherheit

Linux

SELinux richtig nutzen

Sicherheit geht vor

von Andreas Stolzenberger

Veröffentlicht in Ausgabe 10/2021 - SCHWERPUNKT

Viele Linux-Tutorials im Internet beginnen mit dem Satz "Schalten Sie SELinux aus" – doch genau das sollten Administratoren auf produktiven Systemen besser nicht. Wir stellen das Linux-Security-Framework vor und verraten Ihnen, wie Ihre Anwendungen gesichert und zuverlässig mit aktiviertem SELinux laufen.

Zugegeben, es kann einem ganz schön auf den Geist gehen, wenn ein frisch konfigurierter Dienst nicht so läuft, wie er es sollte, und sich erst nach langer Suche herausstellt, dass ein Fehler in der SELinux-Konfiguration dafür verantwortlich war. Viele Administratoren greifen daher gleich von Vornherein zum eigentlich letzten Mittel: SELinux ausschalten. Immer wieder stellen sie die Frage: Wozu braucht es das überhaupt?
Wenn UGO nicht mehr genügt
Das grundlegende Sicherheitssystem von Linux weist jeder Datei, jedem Verzeichnis und allen Geräten gewisse Basisattribute zu: Wem gehört die Entität und wie dürfen andere Nutzer darauf zugreifen? Für "User", "Group" und "Other" kann der Eigentümer die Attribute "Read", "Write" und "Execute" vergeben. Nur Dateien mit dem Execute-Flag dürfen als Programme ausgeführt werden. Zudem gibt es die Sonderregel: Nutzer können nur in ein Verzeichnis mit "Execute"-Flag wechseln. Wer kein "X" am Directory sieht, kommt nicht rein. Zudem gibt es weitere Sonder-attribute wie das "SUDO"-Flag, das ausgewählten Nutzern oder Gruppenmitgliedern erlaubt, einen "S"-markierten Dienst mit Root-Rechten auszuführen.
Das simple, alte Sicherheitssystem alleine reicht schon lange nicht mehr für komplexere Aufgaben. Wenn mehr als nur eine Gruppe auf eine Datei zugreifen sollen, verwenden Linux-Dateisysteme sogenannte "Extended Attributes". Mit deren Hilfe können Administratoren Dateien und Verzeichnisse mehreren Usern oder Gruppen zuweisen. Ein Beispiel:
Zugegeben, es kann einem ganz schön auf den Geist gehen, wenn ein frisch konfigurierter Dienst nicht so läuft, wie er es sollte, und sich erst nach langer Suche herausstellt, dass ein Fehler in der SELinux-Konfiguration dafür verantwortlich war. Viele Administratoren greifen daher gleich von Vornherein zum eigentlich letzten Mittel: SELinux ausschalten. Immer wieder stellen sie die Frage: Wozu braucht es das überhaupt?
Wenn UGO nicht mehr genügt
Das grundlegende Sicherheitssystem von Linux weist jeder Datei, jedem Verzeichnis und allen Geräten gewisse Basisattribute zu: Wem gehört die Entität und wie dürfen andere Nutzer darauf zugreifen? Für "User", "Group" und "Other" kann der Eigentümer die Attribute "Read", "Write" und "Execute" vergeben. Nur Dateien mit dem Execute-Flag dürfen als Programme ausgeführt werden. Zudem gibt es die Sonderregel: Nutzer können nur in ein Verzeichnis mit "Execute"-Flag wechseln. Wer kein "X" am Directory sieht, kommt nicht rein. Zudem gibt es weitere Sonder-attribute wie das "SUDO"-Flag, das ausgewählten Nutzern oder Gruppenmitgliedern erlaubt, einen "S"-markierten Dienst mit Root-Rechten auszuführen.
Das simple, alte Sicherheitssystem alleine reicht schon lange nicht mehr für komplexere Aufgaben. Wenn mehr als nur eine Gruppe auf eine Datei zugreifen sollen, verwenden Linux-Dateisysteme sogenannte "Extended Attributes". Mit deren Hilfe können Administratoren Dateien und Verzeichnisse mehreren Usern oder Gruppen zuweisen. Ein Beispiel:
touch test1.txt
getfacl test1.txt
# file: test1.txt
# owner: ast
# group: ast
user::rw-
group::rw-
other::r--
Über die erweiterten Attribute kann der Owner einen weiteren Nutzer hinzufügen, wie nachfolgend dargestellt:
setfacl -m u:mysql:rw test1.txt
getfacl test1.txt
# file: test1.txt
# owner: ast
# group: ast
user::rw-
user:mysql:rw-
group::rw-
mask::rw-
other::r--
Wichtig dabei ist, dass erweiterte Attribute nur auf einem Dateisystem funktionieren, das diese auch unterstützt. Bei NFS ist das beispielsweise erst ab v4 enthalten. In diesen erweiterten Attributen lassen sich auch Zugriffsregeln jenseits von "RWX" festlegen. Der Verwalter kann eine Datei beispielsweise als "I", also "Immutable", markieren und sie damit vor Änderungen und dem Löschen schützen. Eine Immutable-Datei darf nicht einmal mehr "root" löschen. Innerhalb der erweiterten Attribute einer Datei, eines Verzeichnisses oder Devices lassen sich aber auch andere Informationen ablegen, was SELinux wiederum intensiv nutzt.
Linux mit Sicherheitserweiterung
Die Architektur und die ersten Implementierungen von SELinux stammen von der NSA. Obwohl der Dienst eher für Geheimhaltung bekannt ist, veröffentlichte die NSA bereits Anfang der 2000er-Jahre die SELinux-Architektur und übergab sie der Open-Source-Community. Wie üblich gilt auch hier: Nur eine Sicherheitstechnologie, die mit offenen Quellen sicher bleibt, ist eine gute Sicherheitstechnologie. SELinux setzt sich dabei aus einer Reihe von Komponenten zusammen, die wir nachfolgend aufzeigen.
SELinux-Label
Jedem Gerät, Port, Datei, Prozess, Verzeichnis eines Linux-Systems wird ein SELinux-Label zugewiesen. Die Information des Labels lagert in den erweiterten Attributen. Hat eine Datei beispielsweise keine individuellen Labels oder nur Teile davon, erbt sie den Rest vom Verzeichnis, in dem sie liegt. Das ist ein ganz wichtiger Punkt, denn ein Großteil der SELinux-Probleme ergibt sich aus dieser Vererbung – oder eben einer fehlerhaften Vererbung.
Ein Label setzt sich aus vier Informationen zusammen: "user:role:type:level", wobei der "level" optional ist. Dieser kommt nur bei Systemen mit extrem hohen Sicherheitsanforderungen im MLS-Modus (Multi Level Security) zum Einsatz. Auf diesen MLS-Betrieb gehen wir in diesem Artikel jedoch nicht ein. Ein Beispiel für die Labels sieht so aus, wobei der Operator "Z" immer die SELinux-Informationen anzeigt:
cd /var/www/html
ls -lhZ
drwxr-xr-x. 2 root root system_u: object_r:httpd_sys_content_t:s0 6 2. Jun 14:42 .
...
Das Web-Admin-Tool "Cockpit" zeigt SELinux-Fehler an und offeriert Vorschläge, um diese zu beheben.
Zentrale Komponente: Policy
Das Herzstück von SELinux ist die Policy. Dabei handelt es sich um Regelwerk, das genau feslegt, was wer überhaupt darf und was nicht. Policy-Regeln überschreiben dabei die UGO-Richtlinien. Mit der passenden Policy ließe sich beispielsweise der User "root" in seinen Rechten völlig beschneiden. Die Hersteller von Linux-Distributionen liefern eigene Policies passend zur Distribution. Da diese von der Distribution und Version abhängen, kann es beispielsweise auf CentOS-Systemen zu SELinux-Problemen kommen, die bei Debian nicht auftauchen und umgekehrt. Wer sich tiefer mit der Materie auseinandersetzt, kann auch eigene Regeln schreiben und die Standard-Policy mit diesen erweitern.
Ein praktisches Beispiel: Hacker greifen gerne Webserver an und versuchen, mit kuriosen URLs diesen oder ein CGI-Programm des Webservers zum Absturz zu bringen. Verschiedene Attacken können mit dem Hack auch ausführbaren Code auf dem Zielsystem einschleusen und diesen dann im Security-Kontext des Webservers zum Laufen bringen. Dabei gibt es auch Angriffe, deren Schadcode weitere IP-Ports öffnet und darüber entweder auf Anweisungen des Hackers lauscht oder den regulären Verkehr der Webseite über den Schadcode umleitet und Benutzereingaben abgreift.
SELinux-Policies können diese Hacks an mehreren Stellen verhindern. Über den Webserver hochgeladene Daten landen zunächst im Temporärverzeichnis "/var/tmp". Vergleichen wir den SELinux-Typ des Webserver-Directories "httpd_sys_content_t" mit dem des tmp-Directories "tmp_t", fallen sofort die unterschiedlichen Labels auf. Passend dazu gibt es eine Policy, die dem Webserver Code-Auführungen im Kontext "tmp_t" untersagt.
Selbst wenn die Dateien in "/var/tmp" mit einem "X"-Flag versehen sind, lassen sie sich dort nicht ausführen. Zudem kennt SELinux Regeln, die unabhängig von Labels und Kontexten gelten. Beispielsweise gibt es eine Regel, die dem Webserver verbietet Zugriffe auf Nicht-Standard-Ports umzuleiten. Diese Regel übersehen Anwender gerne, wenn sie Reverse-Proxies einrichten.
Dienst zur Überprüfung
Damit SELinux funktioniert, gibt es im Linux-Kernel seit der Version 2.4 den passenden Dienst, der alle Ausführungen gegen die Policy prüft. Dieser verwendet dabei den so gennanten AVC (Access Vector Cache), der Regeln puffert. Findet SE­Linux keine passende Regel im Puffer, schlägt der Prozess erst mal in der Policy-Datenbank nach, cached dann aber das Regelwerk für weitere Ausführungen. Mit dem Cache soll SELinux so wenig CPU-Zeit für Sicherheitschecks wie möglich aufwenden. SELinux kostet etwas Performance. Die CPU-Zeit braucht der Dienst, um Policies zu prüfen und um die Labels auf dem aktuellen Stand zu halten.
Keine Container ohne SELinux
Neue Popularität genießt SELinux seit dem Siegeszug von Docker, Podman und Kubernetes. Monolithische Anwendungen wandern in Container, die skalierend und voneinander isoliert auf dem selben Linux-Kernel arbeiten. Ein Container ist eigentlich ein potentielles Sicherheitsrisiko. Anders als eine virtuelle Maschine mit einem eigenen OS teilt sich der Container die OS-Runtime mit dem Host und anderen Containern. Dabei könnten bösartige Applikationen versuchen, aus den Grenzen ihres Container-Gefängnisses auszubrechen und auf den Speicher des Hosts oder anderer Container zuzugreifen. Das funktioniert jedoch nicht, wenn SELinux die Container in getrennte Kontexte zwingt. Denn auch einzelne Prozesse des Systems ordnet SELinux einem Kontext zu. Das ermöglicht dann auch Zugriffsbeschränkungen einzelner Prozesse (Subjekte) auf Dateien oder Ports (Objekte). Bei einem Dnsmasq-Nameserver sieht das beispielsweise so aus:
ps -C dnsmasq -Z
system_u:system_r:dnsmasq_t:s0 1964023 ? 00:00:09 dnsmasq
 
ls -Z /etc/dnsmasq.conf
system_u:object_r:dnsmasq_etc_t:s0 /etc/dnsmasq.conf
 
netstat -plntZ | grep dnsmasq
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 1964023/dnsmasq system_u:system_r:dnsmasq_t:s0
Mit einer strengen Policy könnte der Administrator so verhindern, dass der Prozess "dnsmasq" auf andere Dateien außer seiner eigenen Konfigurationsdatei zugreift oder auf anderen Ports außer 53 lauscht.
Einschränken, beobachten oder ausschalten
SELinux kennt drei Betriebsmodi: "Enforcing", "Permissive" und "Disabled". Im bevorzugten Enforcing-Modus setzt der Dienst rigoros die Policy um. Disabled schaltet SELinux komplett ab, was aber auch bedeutet, dass keine Labels mehr geschrieben und aktualisiert werden. Für Administratoren ist neben dem Enforcing- vor allem der Permissive-Modus zur Fehlersuche sehr wichtig. Hierbei läuft SE­Linux zwar, greift aber nicht aktiv in den Betrieb ein. Alle Policy-Verstöße schreibt der Dienst dabei akribisch in das System-Log, wodurch sich diese Vorgänge nachvollziehen lassen. Zudem hält SELinux die Tags in den Attributen aktuell.
Installieren Sie einen neuen Dienst auf Ihrem System, der möglicherweise mit SELinux in Konflikt gerät, gehen Sie einfach wie folgt vor: Schalten Sie SELinux (nicht permanent) auf "Permissive", richten Sie den Dienst ein, starten Sie ihn und führen Sie Funktionstests durch. Prüfen Sie die Audit-Logs auf SELinux-Meldungen, die im Zusammenhang mit dem neuen Dienst entstanden sind:
grep avc /var/log/audit/audit.log
Korrigieren Sie die Konfiguration entsprechend, bis keine Fehler mehr im Audit auftauchen, und schalten Sie dann SELinux zurück auf "enforcing". Zwischen "enforcing" und "permissive" können Sie jederzeit problemlos mit dem "setenforce"-Kommando im laufenden Betrieb hin- und herschalten. Der gewünschte dauerhafte Betriebsmodus steht in der Datei "/etc/selinux/config".
SELinux wiederbeleben
Lief ein System längere Zeit im Modus "disabled", dürfen Sie SELinux nicht einfach wieder einschalten, da die Kontexte von Dateien und Verzeichnissen eventuell nicht mehr stimmen. In diesem Fall müssen Sie die erweiterten Attribute prüfen und korrigieren. Das übernimmt der task "Relabel". Um ein "disabled"-System wieder zu "enforced" oder "permissve" zu machen, tragen Sie zuerst in "/etc/selinux/config" den gewünschten Modus ein, sodass dieser beim nächsten Neustart gilt. Dann erzeugen Sie die Semaphore ".autorelabel" im Root-Directory:touch /.autorelabel Falls Sie mehrere Platten an verschiedenen Stellen mounten, müssen Sie die Semaphore auch in den jeweiligen Mount-Verzeichnissen anlegen. Verschiedene Distributionen liefern ein Shell-Skript namens "fixfiles" mit, das die Semaphore automatisch in allen benötigten Verzeichnissen erstellt: fixfiles -F onboot der nächste Neustart des Systems nimmt dann ein paar Minuten länger in Anspruch. SELinux prüft alle Kontexte und passt die erweiterten Atrribute an. Nicht vergessen: Der Relabel-Prozess überschreibt alle Kontexte gemäß der aktiven Policy, wodurch sich direkte Kontextänderungen vom Benutzer entsprechend ändern.
SELinux steuern
Es gibt eine Vielzahl von Tools, mit denen Sie SELinux-Einstellungen anpassen und mögliche Konflikte beheben können. Aber auch hier gibt es in Internetanleitungen gerne falsche Hinweise zum Thema SELinux-Werkzeuge. Da ist dann gerne mal vom Tool "chcon" die Rede, das den Kontext einzelner Dateien und Verzeichnisse anpasst. Nehmen Sie einfach zur Kenntnis, dass es das Tool "chcon" gibt und ignorieren Sie es künftig.
Chcon ändert den Kontext einer Datei oder eines Verzeichnisses. Das funktioniert aber nur temporär, denn ein Relabel, der beispielsweise auch bei einem Update der Policy läuft, setzt alle durch chcon durchgeführten Änderungen wieder auf den Zustand der Policy zurück. Wer mit chcon arbeitet, muss also davon ausgehen, dass sein System nach dem nächsten yum update nicht mehr funktioniert.
Möchten Sie den Kontext einer Datei oder eines Verzeichnisses ändern, dann tragen Sie diese Änderung in die Policy-Datenbank ein. Dazu gibt es das Tool "semanage". Laut Standard-Policy liegen die Dateien des Webservers beispielsweise unter "/var/www/html". Alle Dateien innerhalb dieses Verzeichnisses bekommen bei einem Relabel den Kontexttyp "httpd_sys_content_t" zugewiesen. Möchten Sie eine Webanwendung aus einem anderen Verzeichnis namens "/webserver/" heraus betreiben, benötigt dieses und alles, was darin liegt, denselben Kontext:
semanage fcontext -a -t httpd_sys_content_t "/webserver(/.*)?"
Mit "fcontext" ändern Sie einen "File (or Directory) context". Der Parameter "-a" steht für "Add" und fügt den Eintrag der Policy-Datenbank hinzu. Das "-t" legt den "Type" fest, während die Wildcard-Formel "(/.*)?" angibt, dass der Kontext für das Verzeichnis selbst als auch für alle darin befindlichen Dateien und Unterverzeichnisse nebst "hidden" Files gilt. Die SELinux-Policy selbst liegt übrigens in "/etc/selinux/targeted" und ihre eigenen Erweiterungen am File-Kontext stehen in der Datei "/etc/selinux/targeted/contexts/files/file_contexts.local". Semanage ändert dabei nur die Datenbank. Die Dateien, die bereits in "/webserver/" liegen, behalten vorerst die alten Labels. Daher müssen Sie diese direkt nach dem Semanage-Kommando auffrischen:
restorecon -R /webserver
Das Kommando restorecon führt ein Relabeling aus, jedoch nur für ein Teilverzeichnis des Systems, in unserem Fall also "/webserver" samt Unterverzeichnissen dank "-R". Wenn Sie wissen möchten, welche Kontexte für welche Verzeichnisse in der Policy Ihres Systems stehen, können Sie diese auflisten mit
semanage fcontext -l
Über das Semanage-Tool konfigurieren Sie aber auch Ports. Möchten Sie, dass Ihr Webserver auch auf Port 81 und nicht nur auf Port 80/443 lauscht, müssen Sie das ebenfalls als SELinux-Policy einrichten, denn mit der Default-Policy dürfen Nginx oder Apache nicht auf Port 81 zugreifen:
semanage port -a -t http_port_t -p tcp 81
Boleans regeln simple Ja/Nein-Einstellungen in der Policy. Dazu wieder ein paar Beispiele, die einen Webserver betreffen. Möchten Sie wie früher üblich, dass alle Nutzer in ihrem Home-Verzeichnis eine Website betreiben dürfen ("/home/<user>/public_html") und über den systemweiten Apache-Server veröffentlichen ("http://<system>/~<user>/"), muss SELinux das zulassen:
setsebool httpd_enable_homedirs 1
Wobei "setsebool" ein einfacheres Tool für den Umgang mit SELinux-Booleans ist. Ähnliche Regeln gibt es auch für den Reverse-Proxy-Betrieb. Per Default darf ein Apache- oder Nginx-Server nicht einfach Anfragen auf Non-Standard-Ports weiterleiten. Diese Funktion möchte der Administrator aber nutzen, beispielsweise mit Applikationen wie Grafana auf Port 3000 oder Kibana auf Port 5601. Der passende Schalter lautet
setesbol httpd_can_network_connect 1
Sonst funktioniert der Reverse-Proxy nicht. Wenn Sie wissen wollen, welche Schalter es in der Policy Ihres Systems gibt, können Sie diese samt dem aktuellen Status auflisten:
getsebool -a
Copy statt Move
Wo wir gerade beim Problem des falschen Dateikontexts sind, hier ein sehr wichtiger Hinweis. Besonders bei der Installation neuer Dienste und Programme kommt es gerne zu Kontextfehlern. Das liegt an der Art und Weise, wie Linux Dateien in einem Dateisystem kopiert oder verschiebt. Wenn Sie Dateien kopieren (cp, rsync et cetera), ändert sich der Kontext dieser Dateien passend zum Zielverzeichnis.
Entpacken Sie also eine Webapplikation in das temporäre Verzeichnis "/tmp" und kopieren die extrahierten Dateien danach nach "/var/www/html", erben diese den "httpd_sys_content_t"-Kontext und Ihre Webapplikation läuft ohne SELinux-Fehler. Verschieben Sie die entpackten Dateien aber (mv), behalten diese den Kontext des temporären Verzeichnisses "tmp_t" und Ihr Webserver darf nicht darauf zugreifen, selbst wenn die Daten dann unter "/var/ www/html" liegen. Nutzen Sie also "mv", müssen Sie im Anschluss via restorecon -R /var/www/html die Kontexte der neuen Dateien korrigieren.
Populäre Fehler
Der Großteil aller Probleme mit SELinux stammt übrigens von Kontextfehlern – nicht zuletzt wegen der bereits angesprochenen "cp" vs "mv" Problematik. SELinux regelt relativ klar, wo welche Dateien liegen sollten, doch viele Administratoren setzen auf eigene Unterverzeichnisstrukturen. Das ist auch problemlos möglich – vorausgesetzt, Sie fügen den Verzeichnissen den korrekten Kontext hinzu. In einigen Fällen gibt es aber gar kein Default-Directory, wie beispielsweise bei Samba-Freigaben. Hier müssen Sie auf jeden Fall Ihren geteilten Verzeichnissen den Kontexttyp "samba_share_t" zuweisen.
Behalten Sie dabei auch im Hinterkopf, dass Kontextfehler gerne zu indirekten Problemen führen, die nicht sofort als SELinux-Problem zu erkennen sind. Verschieben Sie zum Beispiel ein Zertifikat per mv in Ihr "/home/user/.cert"-Verzeichnis, bekommt es nicht den "home_cert_t"-Kontext. Das fällt aber erst dann auf, wenn Sie versuchen, eine VPN-Verbindung aufzubauen und Ihr VPN-Client den Fehler "Kann Zertifikat XYZ nicht finden" ausgibt. Leider lautet der Fehler hier nicht "Datei hat falschen Kontext". Da der Kernel dem Dienst nicht verrät, warum sein "Read-Access" abgelehnt wurde, meldet dieser "Datei nicht gefunden" oder "Zugriff auf Datei verweigert". Somit weißt der Admin nicht sofort, dass er es mit einem SELinux-Problem zu tun hat. Diese Information findet er erst im Alert-Log.
Ab und zu möchten Administratoren zudem Dateien und Verzeichnisse gleichzeitig für mehrere Dienste nutzen, wie zum Beispiel mit Web- und Samba-Servern. Für Dateien und Verzeichnisse gilt aber stets nur ein Typ, also Samba oder HTTP, aber nie beide. Für solche Fälle existiert ein eigener Kontexttyp namens "public_content_rw_t", auf den beide Dienste zugreifen dürfen. Sollten beide Dienste auch schreiben dürfen, bedarf es der weiteren Booleans "allow_smbd_anon_write" und "allow_httpd_anon_write".
Die Booleans sind nach den Kontexttypen die zweithäufigste Fehlerquelle. Die Liste der Schalter ist mit neuen Policies recht ausführlich geworden und oftmals erschließt sich dem Anwender nicht sofort, warum ein SELinux-Boolean die eine oder andere gewünschte Funktion per Default verhindert. Sehen Sie sich die "getsebool -a" Liste einmal an, möglichst bevor Sie an der Konfiguration Ihres VPN-Servers verzweifeln, weil Sie vielleicht schlicht und ergreifend den Schalter "openvpn_can_network_connect" übersehen haben.
Fazit
SELinux ist ein wichtiges Werkzeug, um produktive Server, speziell wenn sie eine direkte Internetverbindung nutzen, vor Missbrauch zu schützen. In Umgebungen mit Containern sollte SELinux zu den vorgeschriebenen Sicherheitsfunktionen jeder Maschine gehören. Es gibt nur wenige Einsatzgebiete, die rechtfertigen, dass Administratoren SELinux gänzlich abschalten. Häufig geht dann eine ausgereifte Sicherheitsfunktion über Bord, nur weil ein paar zusätzliche Minuten für die Suche möglicher SELinux-Konflikte zuviel verlangt scheinen. Wer nach dem oben genannten Schema "Permissive, Audit-Log, semanage/setsebol, Enforcing" vorgeht, deckt relativ zügig mögliche SELinux-Fehler auf.
(dr)