Probleme mit SELinux finden und lösen

chidsey , sxc.hu

Unter der Lupe

Verhindert der Einsatz von SELinux, dass ein Programm richtig funktioniert, wird oft geraten, die Zugriffskontrolle einfach abzuschalten. Für derart leichtsinnigen Aktionismus besteht aber kein Grund, denn Probleme in der Konfiguration lassen sich mit den folgenden Tipps schnell finden und beheben.

Tritt ein Fehler in der SELinux-Konfiguration eines Servers auf, fehlt vielen Admins oft die Zeit, dem eigentlichen Problem auf den Grund zu gehen. Kurzerhand lassen sie die Maschine ohne aktivierten SELinux-Schutz weiterlaufen und verschieben die Problemlösung auf später. Dieser Artikel zeigt, dass es auch anders geht: Mit dem nötigen Know-how und einigen kleinen Tricks läuft jede Anwendung auch mit aktivem Schutzschild.

Kurzer Rückblick

SELinux ist ein Security-Framework auf Basis der Mandatory Access Control, das Framework basiert auf dem Flask-Forschungsprojekt der amerikanischen NSA-Behörde [1]. Im Standardkernel ist es über das Linux-Security-Module-API (LSM) integriert. Alle Interaktionen zwischen so genannten Subjekten und Objekten sind durch eine gesonderte Security-Policy zu autorisieren.

Die Anweisungen enthalten dabei jedoch keine Datei-, Prozess- oder Benutzernamen, stattdessen kommt ein abstrahiertes Model mit Security-Labels zum Einsatz. Prozesse und Benutzer bekommen diese dynamisch zugewiesen, Dateien speichern das Label in den erweiterten Attributen. Es ist möglich, diese Policy zur Laufzeit des Systems zu ändern. Hierbei findet aber eine strikte Trennung von Policy und deren Durchsetzung statt.

Für das Enforcement sind diverse Hooks im Linux-Kernel zuständig. Sie erweitern die klassischen Zugriffsrechte der Discretionary Access Control (DAC) um die entsprechende MAC-Funktionalität. Über eine binäre Policy-Datei gelangen die eigentlichen Regelwerke in den Security-Server des Linux-Kernels.

SELinux kennt drei Modi: Im Enforcing-Mode ist jeder einzelne Zugriff einer Kontrolle durch die SELinux-Policy ausgesetzt. Jeder Zugriff wird ausgewertet und gegebenenfalls untersagt, wenn es keine Regel gibt, die diesen Zugriff erlaubt. Im Permissive Mode wird ebenfalls jeder Zugriff überwacht, allerdings kommt es nicht zur Durchsetzung der Regeln. Das bedeutet, dass ein Zugriff selbst dann stattfindet, wenn keine Regel den Zugriff explizit erlaubt.

SELinux schreibt für jeden nicht durch eine Regel erlaubten Zugriff einen Logeintrag, allerdings nur beim ersten Mal. Alle weiteren Zugriffe unterdrückt das System stillschweigend. Im Disabled Mode ist SELinux überhaupt nicht aktiv. Es kommen nur Zugriffsentscheidungen auf Basis der DAC zum Einsatz. Dabei muss der Administrator daran denken, dass Dateien, die im Disabled-Modus erzeugt wurden, auch kein Security-Label bekommen.

Type Enforcement

Zur Erweiterung des klassischen Discretionary-Access-Control-Modells stellt SELinux verschiedene Implementierungen zur Verfügung:

  • Type Enforcement (TE)
  • Role-based Access Control (RBAC)
  • Multi Level Security (MLS)
  • Multi Category Security (MCS)

Die wichtigste Implementierung ist hierbei das Type Enforcement. Es regelt den Zugriff von einem Subjekt, etwa einem Prozess, auf die diversen Objekte, beispielsweise Dateien oder Verzeichnisse. Allerdings gibt es eine Vielzahl unterschiedlicher Objekte. Zu diesen zählen neben Dateien und Verzeichnissen beispielsweise auch Netzwerkports. Die den Subjekten und Objekten zugewiesenen Security-Label sind auch unter dem Namen Domäne oder Typ bekannt. Allgemein ausgedrückt regelt das Type Enforcement, welche Domäne auf welchen Typ zugreifen darf.

Genau hier liegt oft das Problem. Besitzt ein Objekt nicht den richtigen Typ, ist der Zugriff darauf nicht möglich, wenn das System sich im SELinux-Enforcing-Modus befindet. Ein Logeintrag in der Datei »/var/log/audit/audit.log« sieht dann etwa wie in Listing 1 aus.

Listing 1

Zugriff verweigert

01 type=AVC msg=audit(1217917079.027:14267): avc:  denied  { getattr } for
02 pid=10054 comm="httpd" path="/var/www/html/index.html" dev=dm-2 ino=1974309
03 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0
04 tclass=file

Der Logtyp bestimmt hierbei den Ursprung der Nachricht. AVC steht für Access Vector Cache und ist ein Teil des Security-Servers im Kernel, der Zugriffsvektoren zwischenspeichert. Der Logtyp »SYSCALL« bezieht sich beispielsweise auf Events, die das Audit-Subsystem festhält, wenn es um das Monitoring von Systemcalls geht. Mit Hilfe von »ausearch -m Typ« ist ein Zugriff auf einen ganz bestimmten Logtyp möglich.

Der nächste Eintrag gibt den Zeitpunkt des Events in Unix-Zeit an. Mit »date -d @Unix-Zeit« lässt sich diese leicht in ein von Menschen lesbares Format verwandeln. Im Anschluss erfolgt die genaue Art der Logmeldung, also ob es sich um eine Deny-Meldung handelt oder nur um eine Information, etwa ob die SELinux-Policy neu geladen wurde oder ob sich der SELinux-Modus geändert hat.

Die nächsten beiden Angaben (»pid« und »comm« ) bestimmen die Herkunft der Fehlermeldung, hier also einen Webserver-Prozess mit seiner Prozessnummer. Das Objekt der Begierde folgt unmittelbar in Form eines Dateipfads (»path« ), Device (»dev« ) und Inode-Nummer (»ino« ). Da für die Interaktion zwischen Prozess und Datei jedoch Security-Label die größte Bedeutung haben, sind diese natürlich ebenfalls aufgeführt. »scontext« steht hierbei für den Source-Context des Webservers, »tcontext« für den Target-Context der Datei. Zum Abschluss gibt die Logmeldung noch Auskunft über den genauen Objekt-Typ. Damit ist die Unterscheidung von Objekten mit gleichem Security-Label möglich.

Seit einiger Zeit gibt es für diese doch recht kryptischen Logeinträge eine Alternative. Fedora Core hat mit Version 6 den Setroubleshoot-Daemon [2] eingeführt. Bei dieser Gnome-Anwendung handelt es sich um ein Plugin-basiertes Tool mit vielen unterschiedlichen Regelsätzen, das – abhängig vom stattgefundenen Event – dem Benutzer mit Rat und Tat zur Seite steht. Auch lassen sich mehrere Benachrichtigungs-Mechanismen einstellen. So kann der Benutzer veranlassen, dass er eine Mail erhält, wenn das SELinux-System eine nicht erlaubte Aktion unterbindet. Benutzer eines grafischen Desktops haben die Möglichkeit, ein Sealert-Applet in ihre Taskbar einzubinden, um sich direkt durch ein Pop-up über aktuelle Meldungen des Setroubleshoot-Daemon zu informieren. Die Logeinträge der Anwendung finden sich in der Datei »/var/log/messages« (Listing 2).

Listing 2

/var/log/messages

01 Aug  5 08:18:07 tiffy setroubleshoot: SELinux is preventing the httpd from
02 using potentially mislabeled files (/var/www/html/index.html). For complete
03 SELinux messages. run sealert -l 774df3c6-badf-4f42-b1f3-e8ff94897d6b

Folgt der Benutzer dem Rat des Setroubleshoot-Daemon und ruft den Befehl »sealert« mit den angegebenen Parametern auf, erhält er eine detaillierte Übersicht über das aufgetretene Problem und Informationen darüber, wie er es beheben kann (Listing 3).

Listing 3

sealert

01 [root@tiffy ~]# sealert -l 774df3c6-badf-4f42-b1f3-e8ff94897d6b
02 Summary:
03
04 SELinux is preventing the httpd from using potentially mislabeled files
05 (/var/www/html/index.html).
06
07 Detailed Description:
08
09 [SELinux is in permissive mode, the operation would have been denied but was
10 permitted due to permissive mode.]
11
12 SELinux has denied httpd access to potentially mislabeled file(s)
13 (/var/www/html/index.html). This means that SELinux will not allow httpd to
14 use these files. It is common for users to edit files in their home directory
15 or tmp directories and then move (mv) them to system directories. The problem
16 is that the files end up with the wrong file context which confined applications
17 are not allowed to access.
18
19 Allowing Access:
20
21 If you want httpd to access this files, you need to relabel them using
22 restorecon -v '/var/www/html/index.html'. You might want to relabel the entire
23 directory using restorecon -R -v '/var/www/html'.
24 Additional Information:
25
26 Source Context                system_u:system_r:httpd_t:s0
27 Target Context                unconfined_u:object_r:user_tmp_t:s0
28 Target Objects                /var/www/html/index.html [ file ]
29 Source                        httpd
30 Source Path                   /usr/sbin/httpd
31 Port                          <Unknown>
32 Host                          tiffy.tuxgeek.de
33 Source RPM Packages           httpd-2.2.8-3
34 Target RPM Packages
35 Policy RPM                    selinux-policy-3.3.1-79.fc9
36 Selinux Enabled               True
37 Policy Type                   targeted
38 MLS Enabled                   True
39 Enforcing Mode                Permissive
40 Plugin Name                   home_tmp_bad_labels
41 Host Name                     tiffy.tuxgeek.de
42 Platform                      Linux tiffy.tuxgeek.de 2.6.25.9-76.fc9.i686 #1
43 SMP
44                               Fri Jun 27 16:14:35 EDT 2008 i686 i686
45 Alert Count                   1
46 First Seen                    Tue Aug  5 08:17:59 2008
47 Last Seen                     Tue Aug  5 08:17:59 2008
48 Local ID                      774df3c6-badf-4f42-b1f3-e8ff94897d6b
49 Line Numbers

Diese Meldung weist schon auf das eigentliche Problem hin. Die Datei »/var/www/html/index.html« besitzt das falsche Security-Label, somit ist ein Zugriff des Webservers hierauf nicht möglich. Eine mögliche Lösung ist ebenfalls aufgeführt:

# restorecon -R -v /var/www/html
# ls -ldZ /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html

Der Aufruf von »restorecon« sorgt dafür, dass jedes Objekt im Verzeichnis »/var/www/html« das richtige Label bekommt. Danach sollte der Zugriff wieder funktionieren. Aber welches ist in diesem Zusammenhang eigentlich das richtige Label? Es ist jenes, das diese Datei in der binären Policy besitzt. Mit Hilfe von »semanage« bekommt der Admin schon im Vorfeld raus, wie das hinterlegte Label lautet:

# semanage fcontext -l | grep /var/www
/var/www(/.*)?          all files system_u:object_r:httpd_sys_content_t:s0

Was soll der Admin aber machen, um den Zugriff auf ein Objekt zu erlauben, das noch über keinen Eintrag in der Policy verfügt? In einem solchen Fall ist die Datei mit dem gewünschten Label in die Policy aufzunehmen. Das funktioniert ebenfalls mit dem Tool »semanage« . Angenommen das Webserver-Documentroot befindet sich unterhalb von »/www« , dann ist auch dieses Verzeichnis, mit allen darin enthaltenen Dateien, mit dem Label »httpd_sys_content_t« zu versehen. Der folgende Aufruf fügt der Policy einen entsprechenden Eintrag hinzu:

# semanage fcontext --add --type public_content_rw_t '/www(/.*)?'
# restorecon -Rv /www

Der abschließende Aufruf von »restorecon« setzt das neue Label auf das Verzeichnis und alle darin enthaltenen Dateien.

Genauso wie der Zugriff auf Dateien oder Verzeichnisse anhand eines Security-Labels stattfindet, geschieht es auch mit Netzwerkports. Das Tool »semanage« bindet das Security-Label an einen Port:

semanage port -a -t http_port_t -p tcp 8000

Hier wird der TCP-Port 8000 mit dem Label »httpd_port_t« versehen. Verifizieren lässt sich dies mit dem erneuten Aufruf von »semanage« :

# semanage port -l |grep http_port_t http_port_t
tcp      80, 443, 488, 8000, 8008, 8009

Manchmal funktioniert eine Anwendung im Enforcing-Modus nicht, die Logdatei zeigt jedoch keine Fehlermeldung an. In der Policy existieren nämlich so genannte Dontaudit-Regeln, die einen Zugriff zwar unterbinden, ihn aber nicht loggen. Das ist ganz praktisch, wenn zum Beispiel eine Anwendung Aktionen durchführen will, die für eine korrekte Funktion aber nicht notwendig sind. Da SELinux nach dem "Principle of least Privilege" arbeitet, sind solche Zugriffe nicht erlaubt. Natürlich soll aber auch nicht jedes Mal ein Eintrag im Log erfolgen.

comments powered by Disqus
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Ausgabe /2014

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit Rex
  • mit anderer Konfigurationsmanagement-Software