40SELinux und AppArmor

SELinux und AppArmor sind Kernelerweiterungen, die laufende Prozesse überwachen und sicherstellen, dass diese bestimmte Regeln einhalten. SELinux kommt standardmäßig unter CentOS, Fedora und RHEL zum Einsatz, AppArmor unter SUSE- und Ubuntu-Distributionen.

Dieses Kapitel gibt eine Einführung in die Funktionsweise und Konfiguration von SELinux und AppArmor. Es zeigt auch, wie Sie Regelverstöße feststellen und wie Sie darauf reagieren können.

40.1SELinux

Unter Linux gilt normalerweise das traditionelle System zur Verwaltung von Zugriffsrechten: Jedes Programm läuft in einem Benutzer-Account. Dieser Account bestimmt, auf welche (Device-)Dateien das Programm zugreifen darf.

Gewöhnliche Programme verwenden den Account des Benutzers, der das Programm gestartet hat. Netzwerkdienste, Datenbank-Server etc. werden mit root-Rechten gestartet, wechseln aber aus Sicherheitsgründen zumeist unmittelbar nach dem Start in einen anderen Account mit eingeschränkten Rechten.

Das Unix-Rechtesystem ist zwar ausgesprochen einfach, bietet aber nur eingeschränkte Konfigurationsmöglichkeiten. Wenn es einem Angreifer gelingt, die Steuerung eines Programms zu übernehmen, kann er auf zahllose Dateien zugreifen, die das Programm normalerweise gar nicht benötigt. Besonders schlimm ist es, wenn der Angreifer die Kontrolle über ein Programm mit root-Rechten erhält bzw. wenn er über Umwege erreichen kann, dass eigener Code mit root-Rechten ausgeführt wird: Damit kann er den Rechner uneingeschränkt manipulieren, eigene Programme installieren und starten etc.

Vielleicht fragen Sie sich, wie ein Angreifer die Kontrolle über ein Programm erlangen kann. Fast immer werden dabei Fehler im Programmcode ausgenutzt.

Beispielsweise wird durch das Übersenden manipulierter Daten ein sogenannter Pufferüberlauf ausgelöst. Dieser Fehler wird wiederum dazu genutzt, um dem Programm eigenen Code unterzujubeln und diesen auszuführen. Natürlich gibt es auch andere Verfahren – aber immer geht es darum, Sicherheitslücken des Programms zu missbrauchen, um das Programm zweckentfremdet zu nutzen bzw. zu manipulieren.

Fehlerfreie Programme gibt es nicht und wird es wohl auch in Zukunft nie geben, wenn man einmal von winzigen Trivialprogrammen absieht. Deswegen wurden im Laufe der Zeit alle möglichen Verfahren entwickelt, um die durch Programmfehler verursachten Risiken zu minimieren: Zu den etablierten Sicherheitsmaßnahmen zählt, möglichst auf Dämonen mit root-Rechten zu verzichten, möglichst wenige Programme bzw. Scripts mit setuid-Bit zu installieren (siehe Abschnitt 13.7, »Spezialbits und die umask-Einstellung«) und die Ausführung von Code im Stack durch die von Red Hat entwickelte Kernelerweiterung Exec Shield zu verbieten.

Noch einen Schritt weiter geht die ursprünglich von der NSA als Open-Source-Code entwickelte Kernelerweiterung SELinux. Der Zweck dieser Erweiterung ist es, dass der Kernel die Ausführung von Programmen anhand von Regeln überwacht. Diese Vorgehensweise wird als Mandatory Access Control bezeichnet, kurz MAC. Wird eine Regel verletzt, verhindert SELinux die Operation oder protokolliert eine Warnung. Das regelverletzende Programm wird durch SELinux nicht beendet. Es hängt vom Programm ab, wie es darauf reagiert, dass es auf eine bestimmte Datei nicht zugreifen kann oder eine Netzwerkschnittstelle nicht nutzen kann.

MAC-Regeln ermöglichen eine sehr viel engmaschigere Sicherheitskontrolle als das Unix-Zugriffssystem. Mit ihnen kann man einem Programm unabhängig von Unix-Zugriffsrechten bzw. -Accounts den Zugriff auf bestimmte Verzeichnisse oder Netzwerkfunktionen generell verbieten. Da diese Regeln auf Kernelebene überwacht werden, gelten sie selbst dann noch, wenn das Programm aufgrund eines Fehlers bzw. Sicherheitsmangels außer Kontrolle gerät.

SELinux ist sauber, obwohl der Code von der NSA entwickelt wurde

Die National Security Agency ist ein Nachrichtendienst der USA, der zuletzt aufgrund der umfassenden Überwachung des gesamten Internetverkehrs eine Menge negative Presse auf sich zog. Obwohl SELinux also aus Geheimdienstkreisen stammt, besteht keine Gefahr, dass Linux auf diese Weise um Überwachungsfunktionen erweitert wurde: Der SELinux-Code ist öffentlich, wurde von vielen unabhängigen Experten kontrolliert und verbessert und ist Bestandteil des offiziellen Kernels. Wenn die NSA Sie und andere überwacht, dann sicher nicht durch eine Hintertür in SELinux.

Ohne entsprechende Regeln ist SELinux wirkungslos. Ob ein System durch SELinux sicherer wird, hängt somit vor allem von der Qualität der Regeln ab. Von den gängigen Distributoren hat bisher nur Red Hat intensiv Zeit und Mühe in die Entwicklung derartiger Regeln investiert. Dabei dient Fedora gewissermaßen als Testvehikel. Was sich dort bewährt, findet schließlich Eingang in die Red-Hat-Enterprise-Versionen (RHEL).

SELinux ist nicht unumstritten. Die zwei wichtigsten Kritikpunkte sind:

Die populärste Alternative zu SELinux ist das von SUSE und Ubuntu eingesetzte System AppArmor (siehe Abschnitt 40.2). Daneben gibt es mit »Smack« ein weiteres MAC-System im Kernel. Smack kommt primär in Embedded-Linux-Systemen zum Einsatz.

SELinux-Interna und -Praxis

SELinux steht auf zwei Fundamenten: Einerseits setzt es die richtige Kennzeichnung aller Dateien und Prozesse durch einen sogenannten Sicherheitskontext voraus, andererseits beruht es auf Regeln, die von den überwachten Prozessen eingehalten werden müssen.

SELinux basiert darauf, dass jedes Objekt (z.B. Dateien) und jedes Subjekt (z.B. Prozesse) mit einem Sicherheitskontext verbunden ist. Bei Dateien wird der Dateikontext in Form von erweiterten Attributen gespeichert. Die Sicherheitsinformationen sind damit unmittelbar mit der Datei verbunden und unabhängig vom Namen der Datei. Den Sicherheitskontext einer Datei ermitteln Sie am einfachsten mit ls -Z. Alternativ funktioniert auch getfattr -n security.selinux -d dateiname.

user$ ls -Z /usr/sbin/httpd ... system_u:object_r:httpd_exec_t:s0 /usr/sbin/httpd user$ ls -Z /etc/httpd/conf/httpd.conf ... system_u:object_r:httpd_config_t:s0 /etc/httpd/conf/httpd.conf user$ getfattr -n security.selinux -d /etc/httpd/conf/httpd.conf getfattr: Removing leading '/' from absolute path names # file: etc/httpd/conf/httpd.conf security.selinux="system_u:object_r:httpd_config_t:s0\000"

SELinux steht und fällt damit, dass zu allen Dateien der richtige Kontext gespeichert ist. Damit dies auch funktioniert, wenn Sie nach der Installation neue Dateien erzeugen, gibt es für viele Verzeichnisse SELinux-Regeln, die den darin erzeugten neuen Dateien automatisch den passenden Kontext zuweisen. Wenn dieser Automatismus versagt, z.B. beim Verschieben von Dateien aus einem anderen Verzeichnis, können Sie den Kontext korrigieren bzw. neu einstellen.

Sofern sich Ihre Dateien in den von SELinux vorgesehenen Verzeichnissen befinden, führt restorecon am schnellsten zum Ziel. Durch das folgende Kommando wird der Kontext aller im DocumentRoot-Verzeichnis von Apache gespeicherten Dateien richtig eingestellt:

root# restorecon -R -v /var/www/html/*

Wenn Sie Dateien an einem anderen Ort gespeichert haben, z.B. HTML-Dateien im Verzeichnis /var/myotherserver, müssen Sie hingegen mit chcon den richtigen Kontext einstellen:

root# chcon -R system_u:object_r:httpd_sys_content_t:s0 /var/myotherserver

Jetzt bleibt noch eine Frage offen: Woher wissen Sie, welcher Kontext erforderlich ist? Die Antwort geben man-Seiten, die die SELinux-Regeln für diverse Programme dokumentieren. man apache_selinux beschreibt beispielsweise die Regeln und vorgesehenen Kontexte für Apache. Eine lange Liste aller derartigen man-Seiten liefert das folgende Kommando:

root# rpm -qd selinux-policy-devel

Bei Prozessen wird der Kontext oft als »Domäne« bezeichnet. Den Sicherheitskontext eines Prozesses (einer Domäne) ermitteln Sie mit ps axZ. Im Regelfall übernimmt ein Prozess den Kontext des Accounts, aus dem er gestartet wird. Der Kontext kann aber auch automatisch nach dem Start durch eine SELinux-Regel verändert werden. Das ist notwendig, wenn ein bestimmtes Programm (z.B. Firefox) unabhängig davon, von wem bzw. wie es gestartet wird, einen bestimmten Kontext erhalten soll.

user$ ps axZ | grep httpd unconfined_u:system_r:httpd_t:s0 2373 ? Ss 0:00 /usr/sbin/httpd unconfined_u:system_r:httpd_t:s0 2376 ? S 0:00 /usr/sbin/httpd ...

Der Sicherheitskontext besteht aus drei oder vier Teilen, die durch Doppelpunkte getrennt sind:

benutzer:rolle:typ:mls-komponente

Am wichtigsten ist der dritte Teil, der den Typ der Datei bzw. des Prozesses angibt. Die meisten SELinux-Regeln werten diese Information aus. Eine detaillierte Beschreibung aller vier Teile des Sicherheitskontexts finden Sie hier:

https://fedoraproject.org/wiki/Security_context

Die allgemeine Syntax einer typischen SELinux-Regel sieht so aus:

allow type1_t type2_t:class { operations };

Dazu ein konkretes Beispiel: Die folgende Regel erlaubt es Prozessen, deren Kontexttyp httpd_t lautet, in Verzeichnissen mit dem Kontexttyp httpd_log_t neue Dateien zu erzeugen:

allow httpd_t httpd_log_t:dir create;

Ein typisches SELinux-Regelwerk besteht aus Zehntausenden solcher Regeln! Aus Geschwindigkeitsgründen erwartet SELinux die Regeln nicht als Text, sondern in einem binären Format. In einer Analogie zum Programmieren kann man dabei auch von einem Kompilat sprechen. Unter aktuellen Fedora- und RHEL-Versionen kommt standardmäßig das Regelwerk targeted zum Einsatz (Paket selinux-policy-targeted). Es überwacht ausgewählte Programme und Server-Dienste und ist in den unzähligen man-Seiten des Pakets selinux-policy-devel dokumentiert.

Alternativ kann das speziell für Server konzipierte Regelwerk MLS (Multilevel Security) installiert werden. Es befindet sich im Paket selinux-policy-mls. Das Ziel dieses Regelwerks ist es, mit RHEL eine Zertifizierung der Klasse EAL 4 zu erreichen. Diese Zertifizierung wird in den USA für bestimmte, oft militärische Anwendungen verlangt.

Mittlerweile ist Ihnen wahrscheinlich klar, dass Änderungen am Regelwerk schwierig sind. Um ein gewisses Maß der Anpassung auch ohne Regeländerungen zu ermöglichen, enthält das Regelwerk targeted diverse boolesche Parameter, die Sie im laufenden Betrieb verändern können. Unter CentOS/Fedora/RHEL verwenden Sie dazu am einfachsten die grafische Benutzeroberfläche system-config-selinux, die im Paket policycoreutils-gui versteckt ist. Dieses Paket ist standardmäßig nicht installiert.

SELinux-Boolean-Parameter
  ändern

Abbildung 40.1SELinux-Boolean-Parameter ändern

Auch mit getsebool können Sie den Wert boolescher Konfigurationsparameter auslesen. setsebool verändert derartige Parameter und erlaubt im folgenden Beispiel, dass Apache CGI-Scripts ausführen darf:

root# setsebool -P httpd_enable_cgi 1

Eine Liste aller booleschen Konfigurationsparameter ermitteln Sie mit getsebool -a. Als ich das zuletzt unter Fedora 23 getestet habe, waren es mehr als 300!

root# getsebool -a abrt_anon_write --> off abrt_handle_event --> off abrt_upload_watch_anon_write --> on antivirus_can_scan_system --> off ...

Die Regeln und booleschen Parameter für diverse Netzwerkdienste sind jeweils in eigenen man-Seiten dokumentiert, die aber extra installiert werden müssen:

root# dnf/yum install selinux-policy-doc

Anschließend können Sie die Dokumentation mit man dienst_selinux lesen, wobei Sie dienst durch den jeweiligen Dienstnamen ersetzen. man httdp_selinux liefert also Informationen zu den SELinux-Regeln, die für den Webserver Apache gelten, man sshd_selinux beschreibt die Regeln für den SSH-Dämon etc. Eine gute Zusammenfassung zur Bedeutung vieler boolescher Parameter gibt diese Seite:

https://wiki.centos.org/TipsAndTricks/SelinuxBooleans

SELinux ist als Teil des Kernels implementiert. Ein expliziter Start durch das Init-System ist daher nicht erforderlich. Ebenso wenig gibt es einen SELinux-Dämon oder andere Hintergrundprozesse.

Die Konfiguration erfolgt durch die Dateien im Verzeichnis /etc/selinux. Von zentraler Bedeutung ist /etc/selinux/config. Die Datei gibt an, in welchem Modus SELinux läuft (Enforcing, Permissive oder Disabled) und welches Regelwerk gilt. Änderungen an dieser Datei werden allerdings nur durch einen Neustart wirksam.

# /etc/selinux/config SELINUX=enforcing SELINUXTYPE=targeted

sestatus ermittelt den aktuellen Status von SELinux. Auf dem Testrechner ist SELinux mit dem Regelwerk Targeted aktiv:

root# sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: targeted Current mode: enforcing ...

Grundsätzlich bestehen die folgenden Möglichkeiten, auf SELinux-Regelverstöße zu reagieren:

Nicht immer sind durch SELinux verursachte Probleme auf den ersten Blick zu erkennen. Wenn Sie beispielsweise einen Verzeichnisbaum mit HTML-Dateien mit cp -a in das Verzeichnis /var/www/html kopieren, können die HTML-Dateien anschließend nicht von Apache gelesen werden. Der Grund: Die cp-Option -a bewirkt, dass auch die Extended Attributes und damit die SELinux-Kontextinformationen mitkopiert werden. Dieser Umstand verhindert, dass die kopierten Dateien in /var/www/html durch eine SELinux-Regel automatisch die richtigen Kontextinformationen erhalten. Diese Probleme vermeiden Sie, wenn Sie statt cp -a die Variante cp -r einsetzen.

Apache selbst weiß nichts von SELinux. Das Programm bemerkt nur, dass es nicht auf die Dateien zugreifen kann, und liefert die in die Irre führende Fehlermeldung You don't have permission to access <filename>. Erst ein Blick in /var/log/messages macht klar, dass die Zugriffsprobleme von SELinux verursacht wurden:

root# less /var/log/messages ... Aug 31 12:45:45 fedora setroubleshoot: SELinux is preventing /usr/sbin/httpd from read access on the file tst. For complete SELinux messages run sealert -l dccb472d-6dd8-49d2-b7d7-2658e082c805

Wenn Sie nun, wie in der Protokolldatei angegeben, sealert ausführen, erhalten Sie einen fast 100-zeiligen Text, aus dem die wichtigsten Passagen hier wiedergegeben sind. Die Mischung von Deutsch und Englisch ist wahrlich lesenswert!

root# sealert -l dccb472d-6dd8-49d2-b7d7-2658e082c805 SELinux is preventing /usr/sbin/httpd from read access on the file index.html. ***** Plugin catchall_boolean (89.3 confidence) suggests ******************* If sie möchten allow httpd to read user content Then you must tell SELinux about this by enabling the 'httpd_read_user_content' boolean. You can read 'user_selinux' man page for more details. Do setsebool -P httpd_read_user_content 1 ***** Plugin catchall (11.6 confidence) suggests *************************** If sie denken, dass httpd standardmässig erlaubt sein sollte, read Zugriff auf index.html file zu erhalten. Then sie sollten dies als Fehler melden. Um diesen Zugriff zu erlauben, können Sie ein lokales Richtlinien-Modul erstellen. Do zugriff jetzt erlauben, indem Sie die nachfolgenden Befehle ausführen: # grep httpd /var/log/audit/audit.log | audit2allow -M mypol # semodule -i mypol.pp ...

Nicht nur die sprachliche Qualität ist abenteuerlich, auch der Inhalt der Lösungsvorschläge ist unbrauchbar. Um das Problem tatsächlich zu beheben, müssen Sie die Kontextinformationen der betroffenen Dateien mit restorecon richtig einstellen:

root# restorecon -R -v /var/www/html/*

Um SELinux vorübergehend zu aktivieren, starten Sie system-config-selinux und aktivieren den Modus Permissive. Damit läuft SELinux weiter und protokolliert Regelverstöße in /var/log/messages. SELinux lässt den Regelverstoß aber zu und blockiert das betroffene Programm nicht. Dieselbe Wirkung hat auch das Kommando setenforce 0.

Natürlich können Sie SELinux in system-config-selinux auch ganz abschalten (Einstellung Disabled). Das ist aber nur empfehlenswert, wenn Sie SELinux auch in Zukunft nicht mehr nutzen möchten. Der Grund: Wenn SELinux deaktiviert wird, sind auch alle Regeln außer Kraft, die neuen Dateien die SELinux-Kontextinformationen zuordnen. Wird SELinux später wieder aktiviert, verursachen die Dateien mit fehlenden Kontextinformationen Probleme. Bei der späteren Richtigstellung der Kontextdaten hilft das Kommando restorecon, der Prozess ist aber mühsam und fehleranfällig.

Sollte SELinux bereits während des Systemstarts Probleme verursachen, verhindert der Kernelparameter selinux=0, dass das SELinux-System gestartet wird. Eine Reaktivierung ist dann aber erst beim nächsten Neustart möglich. Alternativ bewirkt der Parameter enforcing=0, dass SELinux zwar gestartet wird, Regelübertritte aber nur protokolliert.