Schlagwort-Archive: selinux

SELinux Booleans

Bei SELinux Booleans handelt es sich um kleine Schalter, mit denen sich das Verhalten der SELinux-Richtlinien beeinflussen lässt. Dieser Artikel knüpft an die „Einführung in das grundlegende Konzept von SELinux“ an und erläutert die Verwendung von SELinux Booleans anhand eines einfachen Beispiels.

Hinweis: Das Beispiel aus diesem Artikel wurde auf einem RHEL/CentOS 7.3 getestet. Unter CentOS 7.2 funktioniert die hier gezeigte Konfiguration nicht. Für Details wird auf das Topic1 im CentOS-Support-Forum verwiesen.

Im Einführungsartikel2 wurde SELinux dazu genutzt, um den Zugriff des Apache auf das DocumentRoot-Verzeichnis /var/www/html zu beschränken. Nun möchte der Webmaster den Benutzern gestatten, Webseiten über ihre HOME-Verzeichnisse zu veröffentlichen und aktiviert dazu die Konfiguration für das Modul Userdir.3 4 5

[root@centos ~]$ cat /etc/httpd/conf.d/userdir.conf

    UserDir enabled
    UserDir public_html



    AllowOverride FileInfo AuthConfig Limit Indexes
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    Require method GET POST OPTIONS


[root@centos ~]#

Nun kann ein Benutzer in seinem HOME-Verzeichnis den Ordner public_html erstellen und eine test.txt-Datei erstellen:

[jkastning@centos ~]$ mkdir public_html
[jkastning@centos ~]$ sudo chmod 711 /home/jkastning/
[jkastning@centos ~]$ sudo chmod 755 public_html/
[jkastning@centos ~]$ vim public_html/test.txt

Hello User

Nach einem Neustart des Dienstes httpd sollte sich nun die Datei index.html aus dem Benutzerverzeichnis abrufen lassen. Statt dessen wird der Zugriff verweigert.

apache_userdir_forbidden

httpd_enable_homdirs –> off

In den Logdateien finden sich Hinweise, die auf SELinux als Ursache hindeuten.

[root@centos ~]# tail /var/log/audit/audit.log|grep AVC
type=AVC msg=audit(1480446615.354:844): avc:  denied  { getattr } for  pid=23150 comm="httpd" path="/home/jkastning/public_html/index.html" dev="sda1" ino=1052157 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_user_content_t:s0 tclass=file

[root@centos ~]# tail /var/log/messages | grep SELinux
Nov 29 20:10:44 centos setroubleshoot: SELinux is preventing httpd from getattr access on the file /home/jkastning/public_html/index.html. For complete SELinux messages. run sealert -l 13419731-cedd-4433-abb7-b2e7715d5636

Um weitere Informationen zu erhalten, führen wir das Kommando aus /var/log/messages aus (Ausgabe gekürzt):

[root@centos ~]# sealert -l 13419731-cedd-4433-abb7-b2e7715d5636
SELinux is preventing httpd from getattr access on the file /home/jkastning/public_html/index.html.

*****  Plugin catchall_boolean (24.7 confidence) suggests   ******************

If you want to allow httpd to enable homedirs
Then you must tell SELinux about this by enabling the 'httpd_enable_homedirs' boolean.
You can read 'None' man page for more details.
Do
setsebool -P httpd_enable_homedirs 1

In der obigen Ausgabe wird neben der Ursache auch gleich die Lösung mitgeliefert. Nach der Aktivierung des SELinux Boolean httpd_enable_homedirs kann der Inhalt der Datei index.html im Webbrowser abgerufen werden.

apache_userdir_allowed

httpd_enable_homedirs –> on

Damit wurde eine weitere Funktionalität von SELinux kurz vorgestellt. Für weiterführende Informationen sei auf die Manpages booleans(8)6, getsebool(8)7 und setsebool(8)8 verwiesen.

Einführung in das grundlegende Konzept von SELinux

SELinux1 (Security-Enhanced Linux; engl. „sicherheitsverbessertes Linux“) ist eine Erweiterung des Linux-Kernels, mit der eine zusätzliche Sicherheitsschicht in das Betriebssystem eingezogen wird.

In dieser Einführung wird das zu Grunde liegende Konzept kurz vorgestellt und erläutert, welche Modi SELinux besitzt, wie diese angezeigt und umgeschaltet werden können. An einem einfachen Beispiel mit dem Apache Webserver wird dargestellt, wie SELinux in der Praxis wirkt. Des Weiteren wird mit Hilfe des Beispiels das Vorgehen bei einer Fehleranalyse erläutert.

SELinux ist dazu gedacht, das bestehende Berechtigungskonzept unter Linux zu erweitern, um zu verhindern, dass kompromittierte Dienste auf Daten zugreifen, auf die kein Zugriff erforderlich ist.

Als einfaches Beispiel mag hier der Webserver Apache2 dienen.

Dieser liest die Dateien, welche er ausliefern soll, in der Standardkonfiguration aus dem dem Verzeichnis /var/www/html. Daneben darf der Dienst z.B. auch alle Verzeichnisse und Dateien unterhalb der Verzeichnisse /tmp und /var/tmp lesen.

user@host:~$ ls -ld /tmp
drwxrwxrwt. 5 root root 4096 Nov 27 19:05 /tmp
user@host:~$ ls -ld /var/tmp
drwxrwxrwt. 2 root root 4096 Nov 10 06:34 /var/tmp
user@host:~$

Grundsätzlich hat der Dienst Zugriff auf alle Verzeichnisse und Dateien, welche den Lese- bzw. Schreibzugriff für alle Benutzer erlauben.

SELinux kann nun dazu genutzt werden, um genau diesen Zugriff zu unterbinden. Die folgende Abbildung soll dies verdeutlichen:

selinux-example-apache

Mögliche Zugriffe mit und ohne SELinux am Beispiel des Apache

SELinux stellt einfach gesprochen ein Regelwerk dar, nach welchem bestimmt wird, auf welche Verzeichnisse, Dateien, Prozesse und Ports ein Dienst zugreifen darf. Dazu erhalten diese Objekte ein Label mit einem Security Context. Nur wenn das SELinux-Regelwerk den Zugriff von einer Ressource auf eine weitere Ressource explizit erlaubt, ist der Zugriff gestattet. Andernfalls wird die Interaktion unterbunden. Dabei unterscheidet SELinux die verschiedenen Label nach Kontexten. Diese sind:

  • user
  • role
  • type
  • sensitivity

Im Folgenden wird ausschließlich der Kontext „type“ weiter betrachtet. So besitzt z.B. der Dienst Apache das Label httpd_t, während Dateien unterhalb von /var/www/html das Label httpd_sys_content_t tragen. Da SELinux eine Regel besitzt, welche den Zugriff des Kontext httpd_t auf Dateien und Verzeichnisse mit dem Kontext httpd_sys_content_t gestattet, kann der Apache die Datei index.html aus dem Verzeichnis /var/www/html anzeigen:

output-index-html

Ausgabe der Datei /var/www/html/index.html

Obiger Screenshot enthält neben dem obligatorischen „Hallo Welt“ auch noch die Ausgabe des Verzeichnis-Listings, welches neben den üblichen Angaben wie Berechtigungen, Benutzer und Gruppe auch den SELinux-Kontext mit ausgibt. Wie man SELinux steuert und sich den Kontext von Verzeichnissen, Dateien und Prozessen anzeigen lässt, wird im Folgenden Abschnitt erläutert.

Steuerung von SELinux

SELinux kennt drei Modi:

  • Enforcing
  • Permissive
  • Disabled

In welchem Status sich SELinux befindet, kann mit dem Kommando getenforce abgefragt werden:

[root@centos ~]# getenforce
Enforcing
[root@centos ~]#

Obige Ausgabe bedeutet, dass SELinux im Modus „Enforcing“ ausgeführt wird. In diesem Modus verhindert SELinux Zugriffe, welche nicht explizit durch das Regelwerk erlaubt werden. Im Unterschied dazu werden diese Zugriffe im Modus „Permissive“ nicht verhindert, sie werden jedoch protokolliert. Dieser Modus eignet sich daher hervorragend, um das aktuelle Verhalten von Diensten zu analysieren und die Konfiguration ggf. anzupassen. Die Umschaltung zwischen den Modi „Enforcing“ und „Permissive“ kann zur Laufzeit erfolgen:

[root@centos ~]# getenforce
Enforcing
[root@centos ~]# setenforce 0
[root@centos ~]# getenforce
Permissive
[root@centos ~]# setenforce 1
[root@centos ~]# getenforce
Enforcing
[root@centos ~]#

Der Standard-Modus wird in der Datei /etc/selinux/config festgelegt.

Anzeige der SELinux-Kontexte

Der kleine Punkt (im Screenshot rot markiert) hinter den Berechtigungen zeigt an, dass ein SELinux-Kontext für eine Datei bzw. ein Verzeichnis existiert:

Der Punkt zeigt einen vorhandenen SELinux-Kontext an

Der Punkt zeigt einen vorhandenen SELinux-Kontext an

Welchen Kontext eine Datei bzw. ein Prozess besitzt, kann angezeigt werden, indem bekannte Kommandos mit der Option „-Z“ benutzt werden. Das folgende Listing zeigt einige Beispiele:

[root@centos ~]# ps -eZ | grep httpd
system_u:system_r:httpd_t:s0     2876 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0     2920 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0     2921 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0     2922 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0     2923 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0     2924 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0     2925 ?        00:00:00 httpd
system_u:system_r:httpd_t:s0     3152 ?        00:00:00 httpd
[root@centos ~]# ls -lisaZ /var/www/html/
total 12
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 .
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 ..
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
[root@centos ~]# ls -lisaZ /var/tmp
total 28
drwxrwxrwt. root root system_u:object_r:tmp_t:s0       .
drwxr-xr-x. root root system_u:object_r:var_t:s0       ..
drwxr-xr-x. abrt abrt system_u:object_r:abrt_var_cache_t:s0 abrt
drwx------. root root system_u:object_r:tmp_t:s0       systemd-private-f844adcb52b14995b675d9aa065e925c-colord.service-MczkBW
drwx------. root root system_u:object_r:tmp_t:s0       systemd-private-f844adcb52b14995b675d9aa065e925c-cups.service-c3Aouq
drwx------. root root system_u:object_r:tmp_t:s0       systemd-private-f844adcb52b14995b675d9aa065e925c-httpd.service-oAqhlb
drwx------. root root system_u:object_r:tmp_t:s0       systemd-private-f844adcb52b14995b675d9aa065e925c-rtkit-daemon.service-xpSsO2
[root@centos ~]# ls -lisaZ /tmp |head -n4
total 96
drwxrwxrwt. root      root      system_u:object_r:tmp_t:s0       .
dr-xr-xr-x. root      root      system_u:object_r:root_t:s0      ..
-rw-r--r--. root      root      system_u:object_r:tmp_t:s0       anaconda.log
[root@centos ~]#

Die Datei index.html hat bei ihrer Erstellung im Verzeichnis /var/www/html automatisch den korrekten Kontext httpd_sys_content_t erhalten und kann daher im Webbrowser angezeigt werden. Wird eine Datei im Verzeichnis /tmp erstellt, erhält diese automatisch den Kontext user_tmp_t:

[root@centos ~]# echo 'TEST' > /tmp/test.txt
[root@centos ~]# ls -lisaZ /tmp/test.txt
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 /tmp/test.txt
[root@centos ~]#

Was tun, wenn’s klemmt?

Um zu erläutern, wie man einem Fehler auf die Spur kommt, baue ich zuerst einen ein. Dazu verschiebe ich die im vorangegangenen Abschnitt erzeugte Datei in das DocumentRoot des Apache und versuche, diese im Browser aufzurufen.

forbidden

Forbidden

SELinux verhindert den Zugriff des Dienstes „httpd“ auf die Datei „text.txt“, da keine Regel existiert, welche den Zugriff vom Kontext httpd_t auf user_tmp_t explizit erlaubt. Doch wie kann man dies feststellen, wenn man nicht bereits zu Beginn um den falschen Kontext weiß?

Zuerst wirft man einen Blick auf die Dateiberechtigungen, welche aber keinen Fehler erkennen lassen:

[root@centos ~]# ls -lZ /var/www/html/
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
-rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 test.txt
[root@centos ~]#

Da die Dateiberechtigungen als Fehlerquelle ausscheiden und in diesem Beispiel keine POSIX-ACL3 verwendet werden, bleibt nur noch SELinux als Fehlerquelle übrig. Daher suchen wir einmal in /var/log/audit/audit.log nach Ereignissen vom Typ „AVC“:

[root@centos ~]# tail /var/log/audit/audit.log | grep AVC
type=AVC msg=audit(1480277043.225:537): avc:  denied  { open } for  pid=2922 comm="httpd" path="/var/www/html/test.txt" dev="sda1" ino=924457 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=file

Treffer! Um die Sache weiter zu analysieren, untersuchen wir als nächstes /var/log/messages (Ausgabe gekürzt):

Nov 27 21:29:13 centos setroubleshoot: SELinux is preventing /usr/sbin/httpd from open access on the file /var/www/html/test.txt. For complete SELinux messages. run sealert -l 7a6417b8-06e2-4499-8f0f-ed0bb16f2b2a

Hier findet sich eine Bestätigung, dass SELinux den Zugriff blockiert hat und ein Vorschlag, wie dieser Vorfall genauer analysiert werden kann. Damit lassen sich umfassende Informationen abrufen, welche sogar die Lösung mit ausgeben (Ausgabe gekürzt):

[root@centos ~]$ sealert -l 7a6417b8-06e2-4499-8f0f-ed0bb16f2b2a
SELinux is preventing /usr/sbin/httpd from open access on the file /var/www/html/test.txt.

*****  Plugin restorecon (92.2 confidence) suggests   ************************

If you want to fix the label. 
/var/www/html/test.txt default label should be httpd_sys_content_t.
Then you can run restorecon.
Do
# /sbin/restorecon -v /var/www/html/test.txt

*****

Der Bericht gibt an, wie das Standard-Label für die Datei text.txt gesetzt sein sollte. Darüber hinaus ist dem Bericht der Befehl zu entnehmen, mit dem die Label wieder auf den Standardwert zurückgesetzt werden können. Nachdem dieser Befehl ausgeführt wurde, kann die Datei text.txt im Webbrowser geöffnet werden.

[root@centos ~]# /sbin/restorecon -v /var/www/html/test.txt
/sbin/restorecon reset /var/www/html/test.txt context unconfined_u:object_r:user_tmp_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
[root@centos ~]#
correct-selinux-context

Aufruf von test.txt mit korrektem SELinux-Kontext

Schlusswort

Es wurde in das grundlegende Konzept von SELinux und die möglichen Betriebsmodi eingeführt. Darüber hinaus wurde erläutert, wie man sich die zu einem Objekt gehörenden SELinux-Kontexte anzeigen lassen kann und wie diese auf einen Standard-Kontext zurückgesetzt werden können. Abschließend wurde ein kleiner Einblick in das Vorgehen zur Fehleranalyse gegeben.

Damit bin ich am Ende dieser kleinen Einführung angekommen, wobei das Thema SELinux damit noch lange nicht abschließend behandelt ist. Für weiterführende Informationen sei an dieser Stelle auf die Dokumentation der einzelnen Distributionen verwiesen.4 5 6

Quellen und weiterführende Links