Mandatory-Access-Control (MAC) mit SE Linux

Was Stacheliges

Gelangen Eindringlinge erst einmal auf den eigenen Server, steht das angeblich so sichere Linux schnell nicht mehr so gut da. Haben sie erst einmal Root-Rechte, haben sie uneingeschänkten Zugang zu allem. SE Linux schiebt einen zusätzlichen Riegel vor.

Linux hat den Ruf ein besonders sicheres Betriebssystem zu sein. Jedoch schützen die klassischen Zugriffsrechte nicht vor Fehlkonfigurationen oder schlecht programmierter Software. Laufen Programm aus dem Ruder, weil der Admin vergessen hat, das letzte Update einzuspielen, oder hat ein Benutzer durch eine falsche Konfiguration erweiterte Rechte erlangt, ist guter Rat meist teuer. SE Linux verspricht hier Abhilfe, denn es begrenzt zumindest den potenziellen Schaden. Es führt eine zusätzliche Zugriffskontrolle ein, die sogenannte Mandatory-Access-Control (MAC).

Historie

Gut sieben Jahre ist es nun her, seitdem die National Security Agency (NSA) [1] die erste Version von SE Linux auf den Markt brachte. Damals noch als Erweiterung für Kernel 2.4 gedacht, haben diese Kernel-Patches mittlerweile Einzug in den offiziellen 2.6-Linux Kernel erhalten. Bei vielen Distributionen gehört SE Linux mittlerweile zum Lieferumfang. Die in diesem Artikel vorgestellten Beispiele basieren alle auf Red Hats Community-Distribution Fedora Core 8, sind aber generell auf jeder anderen Plattform, die Unterstützung für SE Linux anbietet, ebenfalls nachvollziehbar. Wichtig ist der entsprechende Support im Kernel ( »CONFIG_SECURITY_SELINUX« ) sowie die Pakete »libselinux« , »policycoreutils« und »selinux-policy-targeted« . Einige Standard-Pakete ( »SysV-Init« , »pam« , »util-linux« , »coreutils« und andere) müssen ebenfalls für den Betrieb unter SE Linux vorbereitet sein.

Kontroll-Listen

Auf klassischen Linux-Systeme kommt üblicherweise die so genannte Discretionary Access Control (DAC) zum Einsatz. Das bedeutet, dass der Eigentümer einer Datei beziehungsweise eines Objekts absolute Kontrolle über das von ihm erzeugte Objekt besitzt. Gestattet ein Besitzer versehentlich jedermann den Schreibzugriff auf eine von ihm erzeugten Datei, gibt es keine weitere Instanz die diesen Vorgang überprüft. Oder schafft es beispielsweise ein Angreifer beliebigen Programmcode auf einem Webserver auszuführen, indem er eine Schwachstelle in der Webserver-Software ausnutzt, so läuft dieser Programmcode, beispielsweise eine Shell, mit den Rechten des Benutzers unter dem auch der Webserver läuft. Oftmals ist dies der Benutzer »apache« . Das heisst, der Angreifer hat Zugriff auf sämtliche Dateien, auf die auch der Benutzer »apache« Zugriff hat.

Auch hier gibt es keine weitere Instanz, die überprüft, ob der Webserver auf die eine oder andere Datei wirklich zugreifen muss, um seine Arbeit korrekt verrichten zu können. Da der Angreifer ja nun über einen Zugang zum System verfügt, kann er sich unter Umständen sogar erweiterte Rechte auf der Maschine verschaffen. Vor kurzem erst wurden viele Linux-Systeme über einen Bug im Kernel kompromittiert, den Angreifer über den Systemaufruf »vmsplice()« ausnutzen konnten. Als Folge erhielten die Angreifer komplette Kontrolle über das gesamte System. Notwendig hierfür war lediglich der Zugang zu einem unprivilegierten Konto auf der betroffenen Maschine.

Auf Systemen mit aktiviertem SE Linux existiert neben der klassischen Zugangskontrolle auf Basis der DAC eine weitere Kontrollschicht, die sogenannte Mandatory Access Control (MAC). Jede Datei beziehungsweise jedes Objekt erhält ein zusätzliches Security-Label. Bei Datei-Objekten speichert Linux dieses Label in den erweiterten Attributen (Extended Attributes). Ebenso erhält jeder Prozess beziehungsweise jedes Subjekt ein solches Label. Diese Label, auch Security-Context genannt, besteht überlicherweise aus drei Komponenten: User:Rolle:Type/Domain. Im Folgenden zwei Beispiel für die Datei »/usr/bin/httpd« beziehungsweise den Webserver-Prozess »httpd« :

# ls -lZ /usr/sbin/http
-rwxr-xr-x  root     root system_u:object_r:↩
httpd_exec_t   /usr/sbin/httpd
# ps -AZ|grep httpd
user_u:system_r:httpd_t          2571 ↩
   ?        00:00:01 httpd

Wie das Security-Label sind auch die Posix-ACLs in den erweiterten Attributen einer Datei gespeichert. Im Beispiel der Datei »/usr/sbin/httpd« sehen sie so aus:

# getfattr -d -m security /usr/sbin/httpd
...
security.selinux="system_u:object_r:httpd_↩
exec_t\000"

SE Linux arbeitet zwar auch mit Filesystemen, die erweiterte Attribute nicht unterstützen, beispielsweise NFS oder ISO9660, hierfür muss der Admin aber in Trickkiste greifen. Das Mount-Kommando kennt für solche Fälle eine Option »context=<security-label>« . Hiermit lässt sich ein Security-Label für das komplette Filesystem angeben.

Eine wichtige Komponente ist die so genannten Policy, die erlaubte Zugriffe zwischen den einzelnen Objekten und Subjekten definiert. So ist innerhalb der Policy genau festgelegt, auf welche Objekte beispielsweise ein HTTPD-Prozess mit einer bestimmten Rolle zugreifen darf. Findet ein nicht explizit erlaubter Zugriff statt, wird dieser zuerst geloggt und schließlich – zumindest im Enforcing-Mode – verboten. Verantwortlich dafür, dass keine Verletzungen der Policy auftreten, ist der sogenannte Security-Server im Kernel. Hierbei handelt es sich um eine Instanz, die ausgehend von der eingesetzten Policy und den Security-Labeln entscheidet, ob ein Zugriff erlaubt ist. Um nicht zu starke Performance-Verluste in Kauf nehmen zu müssen, arbeitet dieser Kernel-interne Server mit einem Cache, dem sogenannten Access Vector Cache (AVC). Dank dieses Zwischenspeichers beschränkt sich die Leistungseinbuße bei SE-Linux-Systemen auf ungefähr sieben Prozent im Vergleich zu klassischen Systemen.

SELinux-Funktionen

SELinux kennt drei unterschiedliche Implementierungen:

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

Beim TE wird festgelegt, welches Subjekt auf welche Objekte zugreifen darf, zum Beispiel welcher Prozess auf welche Dateien. Allerdings gibt es eine Vielzahl unterschiedlicher Objekte, hierzu zählen beispielsweise auch Netzwerkports oder Speicherbereiche. SE-Linux prdnet jedem Subjekt eine Domäne und jedem Objekt einen Typ. Allgemein ausgedrückt regelt das Type-Enforcement also, welche Domäne auf welche Typen zugreifen darf. Es gibt bei der Darstellung keine Unterscheidung zwischen Typen und Domänen, beide enden immer auf »_t« , zum Beispiel »httpd_t« .

RBAC arbeitet mit einem abstrahierten User-Model und weist jedem Benutzer genau eine Rolle zu. Diesen Rolle lassen sich Berechtigungen zuweisen, beispielsweise auf welche Programme die Rolle Zugriff hat. Benutzer erben nun die Berechtigungen der Rolle. So ist es beispielsweise auch möglich, dem Benutzer Root eine Rolle zuzuweisen, die keine administrativen Rechte besitzt, weil sie den Zugang zu den entpsrechenden Programmen verbietet. Um in eine andere Rolle mit erweiterten Rechten zu wechseln, muss der Benutzer sich erst mit Hilfe seines Passwortes authentifizieren. Das ist ein interessantes Feature, wenn man Maschinen ohne den allmächtigen Root-Benutzer aufsetzen möchte. Ein Benutzer kann sich zu einem Zeitpunkt immer nur in einer Rolle befinden, jedoch mit dem Kommando »newrole« (ähnlich »su« ) die Rolle wechseln, wenn die Policy diesen Wechsel gestattet. Ein typischer Rollenname ist beispielsweise »user_r« – alle Rollen enden immer auf »_r« .

Russell Coker bietet zu Demo-Zwecken einige SELinux Play-Maschinen im Netz an [4] , die die Funktion von RBAC demonstrieren. Er stellt den Root-Account für diese Maschinen öffentlich zur Verfügung, sodass sich jeder Interessierte als Administrator einloggen kann. Jeder Tester wird dann schnell feststellen, dass er einen sehr eingeschränkten Befehlsumfung zur Verfügung hat, da der Benutzer »root« sich auf diesen Play-Maschinen in einer nicht administrativen Rolle befindet.

MLS schließlich definiert unterschiedliche Sicherheitsstufen und wird primär in extrem sicherheitskritischen Umgebungen, beispielsweise dem Militär, eingesetzt. Objekten werden hier Geheimhaltungsstufen (Vertraulich, Streng Vertraulich, Geheim und so weiter) zugewiesen und Subjekte erhalten Freigaben für diese unterschiedlichen Geheimhaltungsstufen. Kommt die MLS zum Einsatz, so wird das Security-Label um eine vierte und fünfte Komponente erweitert und hat somit folgenden Aufbau:

User:Role:Type/Domäne:Sensitivität:Kategorie

Abbildung 1: Der Kernel-interne Security Server entscheidet über erlaubte Zugriffe.

Als kleine Demonstration zur Funktionsweise des Type-Enforcements soll folgendes Szenario dienen: Der Admin legt die Datei »index.html« im Ordner »/tmp« an. Anschließend verschiebt (nicht kopiert!) er diese Datei in das Document-Root des Webservers, bei Fedora »/var/www/html/« . Anchließlich startet er den Webserver ( »/etc/init.d/httpd start« ) und ruft die eben erzeugte Seite im Webbrowser auf ( »http://localhost/index.html« ). Ist der Enforcing-Mode von SE Linux (default) aktiv, sollte der Webbrowser eine Fehlermeldung anzeigen. Zur Erklärung: Die Datei »index.html« wurde in »/tmp« angelegt, dadurch hat sie das Security-Label des Ordners »/tmp« geerbt:

# ls -lZ /tmp/index.html
-rw-r--r--  root     root     root:object_r:↩
tmp_t   /tmp/index.html

Der Webserver-Prozess wiederum läuft in einer Domäne mit dem Namen »httpd_t« :

# ps -AZ|grep httpd
user_u:system_r:httpd_t          2571 ?↩
        00:00:02  httpd

Es müsste nun nun also eine Allow-Regel in der Policy existieren, die der Domäne »httpd_t« den Zugriff auf Dateien vom Typ »tmp_t« gestattet. Um es vorwegzunehmen, eine solche Regel existiert nicht. Warum sollte sie auch existieren? Der Webserver muss auf seine Konfigurationsdateien zugreifen dürfen, auf seine Logs, auf CGI-Skripte und anderen Content innerhalb des Webserver-Verzeichnisses. Für all diese Dateien existieren bestimmte Typen, zum Beispiel »httpd_config_t« , »httpd_log_t« , »httpd_sys_script_exec_t« und »httpd_sys_content_t« .

Dateien im Order »/tmp« zählen üblicherweise nicht zu den Objekten, auf die ein Webserver zugreifen muss, insofern fehlt eine entsprechende Allow-Anweisung in der Policy-Datei für den Typ »tmp_t« .

Auch im Log »/var/log/audit/audit.log« findet sich ein Hinweis darauf, das ssoeben ein nicht erlaubter Dateiaufruf stattgefunden hat:

... audit(1202241301.521:12): avc: denied
{getattr } for  pid=6608 comm="httpd" name=↩
"index.html" dev=dm-0 ino=179881
scontext=user_u:system_r:httpd_t tcontext=↩
root:object_r:tmp_t tclass=file

Im Klartext bedeutet der Log-Eintrag, das der Prozess mit der PID 6608 und dem Namen »httpd« versucht, hat den Syscall »getattr« (also das Aufrufen der Attribute) auf eine Datei mit der Inode-Nummer 179881 und dem Namen »index.html« anzuwenden. »scontext« und »tcontext« sind die Bezeichnungen der Security-Label des Source-Prozesses ( »apache« ) und der Target-Datei ( »index.html« ). Die Ausgabe »avc:denied« zeigt an, dass der Security-Server im Kernel diese Aktion untersagt hat. Wer es gerne etwas aufgeräumter hat, der greift zum Anzeigen der Log-Einträge auf das Tool »seaudit« zurück ( Abbildung 2 ), das die einzelnen Logeinträge grafisch dargestellt. Mit dem Aufruf »seaudit-report --html Logdatei « ist es sogar möglich, eine HTML-Seite zu generieren, die neben den Logs auch diverse Statistiken über das SE-Linux-System anzeigt ( Abbildung 3 ).

Abbildung 2: Das Tool
Abbildung 3: seaudit-report

Läuft auf der Maschine »setroubleshootd« , erscheint zusätzlich folgender Eintrag in der Logdatei »/var/log/messages« :

setroubleshoot: #012    SELinux is ↩
preventing the /usr/sbin/httpd from using ↩
potentially mislabeled files (/var/www/html/↩
index.html).#012 For complete SELinux messages↩
run sealert -l 5e982b3b-3ae7-4848-b8bd-7d8553a07732

Der Daemon »setroubleshoot« wurde vor einiger Zeit entwickelt, um die etwas kryptischen Meldungen des Audit-Daemons im menschenlesbar darzustellen und dem Anwender Tipps zur Problembeseitigung zu geben. Führt der Anwender den im Log-Eintrag angegebenen Befehl aus, erhält er die in Listing 1 sichtbare Erklärung.

Listing 1

sealert -l 5e982b3b-3ae7-4848-b8bd-7d8553a07732

 

Der Gnome-Desktop blendet bei jedem neu erzeugten SE-Linux-Log-Eintrag ein kleines Icon (ein gelbes Schutzschild) in der Taskbar ein. Klickt der Anwender auf dieses Icon, erscheint der grafische SELinux-Troubleshoot-Browser, mit dem der Admin grafisch durch die aufbereiteten Meldungen blättern kann ( Abbildung 4 ).

Abbildung 4: Das

Mit dieser Hilfestellung ist es nun auch ungeübten Administratoren möglich, das Problem zu beseitigen:

restorecon -v /var/www/html/index.html

Dieser Befehl setzt mit Hilfe der Policy das korrekte Label der Datei »index.html« . Alternativ kann der Admin den korrekten Datei-Typ auch manuell angeben:

chcon -t httpd_sys_content_t /var/www/↩
html/index.html

In beiden Fällen sollte das Ergebnis wie folgt aussehen:

# ls -lZ /var/www/html/index.html
-rw-r--r--  root root system_u:object_r:↩
httpd_sys_content_t  /var/www/html/index.html

Beim erneuten Versuch, die Datei im Webbrowser anzuzeigen, sollte es nun keine Sicherheitshindernisse mehr geben.

Anhand dieses kleinen Beispiels lässt sich sehr schön die Funktionsweise von SELinux erkennen. Unabhängig von den klassischen Berechtigungen gestattet Linux den Zugriff nur, wenn ein entsprechender Eintrag in der SELinux-Policy existiert (Mandatory Access Control). Ein solcher Eintrag werden der sicherheitsbewusste Distributor oder Admin aber nur anlegen, wenn der Zugriff wirklich notwendig ist (Principle of least Privilege).

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.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2023