Programme mit SELinux-Sandbox absichern

Sandkasten

Das Surfen im World Wide Web wird immer gefährlicher. Viele Anwender wünschen sich deshalb einen besonders sicheren Webbrowser, der sie vor Malware und anderen unliebsamen Überraschungen schützt. Mit Hilfe von SELinux lassen sich besonders gefährdete Anwendungen nun in einen Käfig einsperren.

Firefox gilt gemeinhin als sehr beliebter und sicherer Webbrowser. Doch leider schützt Beliebtheit nicht vor Software-Fehlern. Und so meldete im Juli 2009 die Mozilla Foundation eine ganze Reihe von Bugs für die 3.5-Serie des Webbrowsers. Beispielsweise schlich sich ein Fehler in den Just-in-time (JIT) Javascript Compiler ein [1] . Ein entsprechender Exploit ließ nicht lange auf sich warten [2] . Landet man mit einer verwundbaren Version des Browsers auf einer Webseite mit dem Exploit-Code, lässt sich auf dem betroffenen Client-System beliebiger Code ausführen – besonders ärgerlich für Benutzer, die mit Ihrem Webbrowser nicht nur Benutzernamen und Passwort speichern sondern auch Kreditkartennummern und andere sensible Daten.

Genau aus diesem Grunde sind Webbrowser schon lange ins Visier der SELinux-Entwickler geraten. Gäbe es ein entsprechendes Regelwerk, könnte man hiermit sämtliche Zugriffsversuche des Webbrowers steuern. Das ist jedoch leider leichter gesagt als getan. So möchten beispielsweise die meisten Applikationen auf einem Gnome-Desktop die komplette Kontrolle über das Home-Verzeichnis eines Benutzers haben, da hier die notwendigen Konfigurationsdateien der Anwendung und des Desktops (Gconf) liegen. Desweiteren ist die Kommunikation mit dem Messaging-System des Rechners (Dbus) notwendig, und auf das Tmp-Verzeichnis braucht zumindest der X-Server Zugriff, unter dem Firefox läuft. Ein Eckpfeiler von SELinux – das Principle of least Privilege – lässt sich so nur schwer umsetzen, da doch sehr viele unterschiedliche Systemzugriffe notwendig sind.

Das SELinux Entwickler-Team bei Red Hat hat sich deshalb für einen anderen Weg entschieden. Sie entwickelten eine Art virtuellen Käfig in den man grafische Anwendungen, wie beispielsweise den Firefox, einsperren kann. Das Problem an dieser Stelle besteht jedoch in den bereits erwähnten notwendigen Dateisystem-Zugriffen einer Desktop Anwendung. Die Lösung hierfür ist nicht weniger pfiffig als elegent. Statt die Anwendung auf das bestehende Home-Verzeichnis eines Benutzers und auf das reguläre Tmp-Verzeichniss loszulassen, gaukelt man der Anwendung einfach andere Ordner als Home und Tmp vor. Mit Hilfe eines Bind-Mounts kann man diese dann einfach anstelle der regulären Ordner einbinden. Mehr dazu im nächsten Abschnitt. Möchte man nun also eine Applikation in einen Käfig einsperren, so ruft der Anwender diese wie folgt auf:

sandbox -X evince

Das Tool sandbox erzeugt den virtuellen Käfig. Dieser besteht aus jeweils einem neuen Ordner im Heimatverzeichnis eines Benutzers und im Tmp-Verzeichnis. Diese Ordner bekommen einen eigenen SELinux-Context inklusive eines zufälligen MCS-Labels. Hiermit schottet man Anwendungen aus verschiedenen Käfigen voneinander ab. Es ist also nicht möglich, dass der PDF-Viewer aus der einen Sandbox auf die Passwort-Daten des Webbrowsers, der in einer anderen Sandbox läuft, zugreift. Das Tool »seunshare« führt dann einen Bind-mount auf die neuen Verzeichnisse aus. Somit sieht die zu startende Applikationen bei jedem Aufruf immer wieder neue, und somit leere Home- und Tmp-Verzeichnisse. Die Shell des Benutzers startet »seunshare« dann ebenfalls mit einem SELinux-Context der Sandbox: »sandbox_x_t:MCS« . MCS ist hierbei wieder ein zufälliges MCS-Label.

Client-Anwendungen innerhalb des Käfigs bekommen das Label »sandbox_x_client_t« zugewiesen. Für diese Domäne existiert eine fein granulierte Policy, welche die erlaubten Zugriffe festlegt (Sandbox-Policy-Modul). Startet der Anwender nun den PDF-Viewer Evince, benötigt der natürlich erst einmal einen X-Server und einen Window-Manager. Hier kommen Xephyr und Matchbox zum Einsatz. Ein Zugriff auf den X-Server des Host-Systems ist nicht möglich. Die Applikation selbst läuft dann im Full-Screen Mode in dem dedizierten Window-Managers der Sandbox. Somit ist ein Zugriff auf andere Funktionen des Window-Managers nicht möglich. Auch auf das Netzwerk ist aus der Sandbox heraus ersteinmal kein Zugriff möglich. Um Dateien modifizieren zu können, benötigen diese das Label »sandbox_x_file_t« , andernfalls verbietet die Policy den Zugriff ( Abbildung 1 , Abbildung 2 ).

Abbildung 1: Die sandbox-Policy erlaubt einen Zugriff auf Dateien vom Typen sandbox_x_file_t, nicht jedoch auf Dateien von Typen tmp_t.
Abbildung 2: Der Zugriff aus der Sandbox ist nur auf ganz bestimmte Ressourcen möglich.

Soll die Applikation aus der Sanddbox heraus auf das Netzwerk zugreifen, so besteht die Möglichkeit, diese mit einem anderen Label als dem Default-Label »sandbox_x_client_t« zu starten. Um beispielsweise Firefox den Zugriff auf die Außenwelt zu gestatten, könnte man diesen mit dem Label »sandbox_web_t« starten:

sandbox -X -t sandbox_web_t firefox

Für einen uneingeschränkten Netzwerk-Zugriff existiert das Label »sandbox_net_t« ( Abbildung 3 ). Hier ist jedoch Vorsicht geboten. Die Idee hinter einer Sandbox ist es ja, fein granulierten Zugriff zu ermöglichen. Befindet sich beispielsweise ein Fehler in einer Appliaktion die mit dem Label »sandbox_net_t« gestartet wurde, so dürfen diese trotz Sandbox sensible Benutzer- oder Systemdaten aus der Sandbox heraus befördern. Aus diesem Grund ist es also besser der Applikation lediglich den Zugriff auf das Netzwerkprotokoll zu gestatten, das für den einwandfreien Betrieb notwendig ist.

Abbildung 3: Startet man eine Anwendung mit dem Label sandbox_net_t, so erhält diese kompletten Netzzugang

Die SELinux-Entwickler stellen für genau diesen Zweck eine Reihe von Makros zur Verfügung. Diese kann man prima für eigene Policy-Entwicklungen verwenden. So lässt sich mit Hilfe »von sandbox_x_domain_template« ein Regelwerk für beliebige Anwendungen erzeugen. Soll beispielsweise eine Anwendung das Protokoll »smtp« aus der Sandbox heraus verwenden können, so lässt sich das Makro innerhalb der eigenen Policy wie folgt aufrufen:

sandbox_x_domain_template(sandbox_mail)

Ein Blick in die Quellen der Makro-Definition verrät schnell was beim Aufruf des Makros passiert ( Listing 1 ). Beim Zugriff auf das Makro erhält man ein Grundgerüst für eine neue SELinux-Domäne in der die Anwendung laufen soll. Erweitert man dieses durch weitere Regeln, so lässt sich anschliessend das neu kompilierte Policy-Modul mittels semodule zum System hinzufügen. Eine genaue Anleitung zum Entwickeln eigener Regelwerke würde den Rahmen dieses Artikels sprengen, jedoch hat der Autor unter [3] einen Einstieg in das Thema Policy-Entwicklung für SE Linux veröffentlicht.

Listing 1

Ausschnitt aus <C>sandbox.if<C>

type $1_t, sandbox_x_domain;
domain_type($1_t)
type $1_file_t, sandbox_file_type;
files_type($1_file_t)
type $1_client_t, sandbox_x_domain;
domain_type($1_client_t)
can_exec($1_client_t, $1_file_t)
...

Auch zum Testen und für den sicheren Betrieb von neuen oder unbekannten Skripten und nicht-GUI Anwendungen kann man auf die Sandbox zurückgreifen. Dies ist gerade dann hilfreich, hat man ein (vermutlich) hilfreiches Skript aus dem Internet geladen, ist sich aber nicht sicher ob das Skript wirklich aus einer vertrauenswürdigen Quelle stammt und nicht eventuell Schaden auf dem eigenen System anrichtet. Zum Glück hat im Open-Source Umfeld jeder Zugriff auf die Quellen eines Programms, jedoch ist nicht jederman in der Lage diese auch entsprechend lesen und auswerten zu können. Startet man die unbekannte Anwendung nun wieder innerhalb der Sandbox, so legt der zuvor definierte Regelsatz fest, welche Zugriffe das Skript erhält. Die Funktionsweise ist dabei ähnlich wie für grafische Anwendungen, lediglich die Angabe der Option »-X« fällt hierbei weg. Die SELinux-Domäne, in der eingesperrten Anwendungen laufen, nennt sich hierbei dann »sandbox_t« :

# ls -lZ /etc/passwd
-rw-r--r--. root root system_u:object_r:etc_t↩
:s0       /etc/passwd
# sandbox cat /etc/passwd|cut -d: -f1
/bin/cat: /etc/passwd: Permission denied

Das letzte Beispiel sollte eigentlich eine Liste aller zur Verfügung stehenden Benutzerkonten ausgeben. Die Policy zeigt jedoch keine "Open-Berechtigung" für Dateien vom Typ »etc_t« an, somit können Anwendungen aus der Sandbox heraus keine Dateien mit diesem Typ öffnen ( Listing 2 )

Listing 2

Open verboten

# sesearch --allow -s sandbox_t -t etc_t -c file
Found 2 semantic av rules:
   allow sandbox_domain etc_t : file { read write getattr lock append } ;
   allow sandbox_domain file_type : file entrypoint ;

Diese Regel verwirrt auf den ersten Blick vielleicht etwas, da hier die Berechtigungen Read und Write aufgeführt sind. Allerdings sind für diese Zugriffe die Datei-Deskriptoren in die Sandbox "hinein zu reichen". Ändert man den Aufruf des Skriptes also wie folgt ab, so erhält man auch das gewünschte Ergebnis:

cat /etc/passwd|sandbox cut -d: -f1

Auch hier hilft ein Blick in die Policy weiter um Details der erlaubten Zugriffe zu erfahren ( Listing 3 ).

Listing 3

<C>sesearch<C> zeigt Policy

$ sesearch --allow -s sandbox_t -c file -p open -d
Found 1 semantic av rules:
   allow sandbox_t sandbox_file_t : file { ioctl read write create getattr setattr lock append unlink link rename execute execute_no_trans open } ;

Soll eine Anwendung aus der Sandbox heraus nun also eine Datei selbstständig öffnen können, so benötigt diese expliziet den Datei-Typ »sandbox_file_t« , ansonsten ist der Zugriff nicht erlaubt. Ein Netzwerkzugrff ist für Skripte aus der Domain »sandbox_t« Domain heraus generell nicht möglich ( Listing 4 ) , hierfür benötigt man wieder eigene Regelsätze für die sandbox_t Domäne.

Listing 4

Ping verboten

type=AVC msg=audit(1256541838.863:183): avc:  denied  { create } for  pid=5474
comm="ping" scontext=unconfined_u:unconfined_r:sandbox_t:s0:c313,c341
tcontext=unconfined_u:unconfined_r:sandbox_t:s0:c313,c341 tclass=rawip_socket

Abschließend sei noch angemerkt, dass die Entwicklung der Sandbox-Funktion gerade erst begonnen hat und momentan auch nur in der Beta-Version von Fedora 12 zur Verfügung steht. Einige Funktionen, wie beispielsweise Copy-And-Paste zwischen Sandbox und Host-System oder das Speichern von Dateien innerhalb der Sandbox, sind zu diesem Zeitpunkt noch nicht vorhanden, werden aber sicher in einer der nächsten Versionen nachgerüstet.

Am Kiosk

Wer jetzt auf den Geschmack gekommen ist und den Zugriff für sämtliche Anwendungen eines Systems einschränken möchte, der sollte sich einmal den Guest-/Xguest-Account eines SELinux-Systems ansehen. Hiermit ist es möglich einen kompletten User-Account innerhalb einer Terminal-Sitzung (Guest) beziehungsweise einer Desktop-Sitzung (Xguest) so einzuschränken, dass wieder nur Zugriffe anhand eines vorher definierten Regelwerks (Guest-/Xguest-Policy Module) erlaubt sind. Benutzt »sandbox« für den Zugriff auf auf Ressourcen primär die SELinux Implementierung Type-Enforcement (TE), so kommt beim Guest-/Xguest-Account auch die Implementierung Role-based-Access-Control (RBAC) zum Einsatz. Seit dem Merge der Targeted- und der Strict-Policy stehen diese nun in einem einzelnen Regelwerk zur Verfügung.

Meldet man sich auf einen System mit Xguest-Account an, so startet die Shell des Benutzers in der geschützten SELinux-Domäne xguest ( Abbildung 4 ). Der Benutzer selbst befindet sich in der gleichnamigen SELinux-Rolle, die den Zugriff auf nur ganz bestimmte Domänen gestattet:

# id -Z
xguest_u:xguest_r:xguest_t:s0
Abbildung 4: Über den gdm-Anmeldemanager erhalten Benutzer Zugriff auf einen restriktiven Desktop.

Das Policy-Modul »xguest« regelt nun wieder den Zugriff auf die einzelnen Ressourcen, dabei laufen sämtliche Applikationen des Benutzers nun in der Xguest-Domäne. So ist es beispielsweise nicht möglich mit sämtlichen Anwendungen auf das uneingeschränkt auf das Netzwerk zuzugreifen, einzige Ausnahme bildet hier der Webbrowser Firefox. Hier ist ein uneingeschränkter Zugriff über das HTTP-Protokoll erlaubt. Die Policy verbietet auch das Ausführen von Dateien aus dem Tmp- oder Home-Verzeichnis des Benutzers. Lädt man also beispielsweise mit dem Firefox schadhafte Programme aus dem Netz, so verhindert die Xguest-Policy deren Ausführung und somit weiteren Schaden. Soll ein Xguest-Benutzer trotzdem beliebige Dateien ausführen können, so gestattet man diesen Zugriff über ein entsprechendes Boolean:

setsebool -P allow_xguest_exec_content=1

Möchte man aus der xguest-Domäne auch den Zugriff auf andere Netzwerk-Dienste gestatten, so benötigt man hierfür wieder ein eigenes Policy-Modul. Soll beispielsweise ein xguest-Benutzer Mails versenden, so braucht die Domäne Zugriff auf den SMTP-Port. Ohne eine entsprechende Regel wäre der Zugang ansonsten verboten wie ein Ausschnitt aus der Datei »audit.log« beweist ( Listing 5 ).

Listing 5

Ausschnitt aus <C>audit.log<C>

type=AVC msg=audit(1256575191.000:861): avc:  denied  { name_connect } for
pid=15663 comm="telnet" dest=25 scontext=xguest_u:xguest_r:xguest_t:s0
tcontext=system_u:object_r:smtp_port_t:s0 tclass=tcp_socket

Ein eigenes Modul soll nun den Zugang erlauben. Wie dieses aussehen könnte zeigt Listing 6 .

Listing 6

Xguest-Policy für SMTP

# mkdir ~/policy
# cat > xguest_smtp.te <<eof
policy_module(xguest_smtp,1.0.0)
require {
        type xguest_t;
}
#============= xguest_t ==============
corenet_tcp_connect_smtp_port(xguest_t)
# make -f /usr/share/selinux/devel/Makefile
Compiling targeted xguest_smtp module
/usr/bin/checkmodule:  loading policy configuration from tmp/xguest_smtp.tmp
/usr/bin/checkmodule:  policy configuration loaded
/usr/bin/checkmodule:  writing binary representation (version 10) to
tmp/xguest_smtp.mod
Creating targeted xguest_smtp.pp policy package
rm tmp/xguest_smtp.mod.fc tmp/xguest_smtp.mod
# semodule -i xguest_smtp.pp
# semodule -l |grep xguest_smtp
xguest_smtpt  1.0.0

Hat man das neue Policy-Modul dem System hinzugefügt, sollte auch der Zugriff über das SMTP-Prokoll funktionieren. Möchte man die eigene Policy weiter verfeinern, so sucht man im »audit.log« einfach nach weiteren Deny-Meldungen und erweitert damit das soeben erstellte Policy-Modul um entsprechende Anweisungen.

Bleibt abschliessend nur noch die Frage, wie man nun einen beliebigen Benutzer-Account in die Xguest-Domäne hinein zwingt. Im einfachsten Fall verwendet man hierfür das Tool »usermod« für bestehende Konten oder »useradd« für neue Konten ( Listing 7 ).

Listing 7

Neue Konten für Xguest

# usermod -Z xguest_u foobar
# semanage login -l
Login Name                SELinux User              MLS/MCS Range
__default__               unconfined_u              s0-s0:c0.c1023
foobar                    xguest_u                  s0
root                      unconfined_u              s0-s0:c0.c1023
system_u                  system_u                  s0-s0:c0.c1023
xguest                    xguest_u                  s0

Meldet sich der Benutzer dann auf seinem Desktop an, so läuft die komplette Benutzer-Sitzung in der geschützen SELinux-Domäne xguest:

$ id -Z
xguest_u:xguest_r:xguest_t:s0

Fazit

Mit der sehr neuen SELinux-Sandbox-Technologie ist es nun sehr einfach möglich, beliebige Anwendungen unter das Schutzschild von SELinux zu stellen um somit eine erhöhten Sicherheit für dasd eigene System zu bekommen. Eigene Policies sind für diese Anwendungen dann lediglich im Bedarfsfall zu schreiben. Zielten die SELinux-Regelwerke bisher primär darauf ab einzelne System-Dienste zu schützen, so stehen nun auch reguläre Benutzer unter dem Schutz der Mandatoy Access Control. Dank Xguest erscheinen nun auch ganz neue Einsatzgebiete, wie beispielsweise Kiosk-Systeme, auf dem SELinux-Radar.

Infos

  1. JavaScript-Bug im Firefox Webbrowser: http://blog.mozilla.com/security/2009/07/14/critical-javascript-vulnerability-in-firefox-35/
  2. Exploit für den Javascript-Bug: http://raidrush.ws/news/firefox-3.5.1-buffer-overflow-exploit/
  3. An die Kette gelegt, Thorsten Scherf, Linux-Magazin-Sonderheft 02/2008, S. 22
comments powered by Disqus
Mehr zum Thema

SELinux in der Praxis

Der Schutzschild SELinux lässt immer noch viele Admins zusammenzucken. Dabei ist der Betrieb mittlerweile sehr umkompliziert und schafft einen gewaltigen Mehrwert in Bezug auf die Sicherheit des kompletten Systems. Das Regelwerk den eigenen Wünschen anzupassen, ist auch keine große Kunst mehr.
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