Für Normaluser funktionieren viele Befehle nur, wenn ihnen Set-UID administrative Privilegien verleiht. Doch das ist riskant – ein Bug und etwas Pech genügen, schon ist der User Root. Klug gesetzte Posix Capabilities statt S-Bits beschränken die Zusatzrechte dagegen auf das Nötigste.
Ohne Set-UID-Programme läuft kein Linux-System (siehe Kasten “Set-UID-Bit”). Solange jedes mit S-Bit ausgestattete Programm sicher entworfen und programmiert ist, sind S-Bits zwar ein Segen. Sie bergen aber ein erhebliches Risiko: Ein Fehler in einem einzelnen S-Bit-Programm genügt, und ein normaler User kann sich dessen sämtliche Rechte verschaffen, in der Regel also Root werden. Als privilegierter Prozess setzen sich Set-UID-Root-Programme über alle Berechtigungsprüfungen hinweg. Dabei brauchen die meisten Tools bei Weitem nicht alle Privilegien des Root-Rechts.
|
Set-UID-Bit |
|---|
|
Linux führt einen Prozess immer unter der Kennung jenes Benutzers aus, der das Programm startet. Somit gelten die Rechte eines Users für alle seine Aktionen. Dieses über 35 Jahren bewährte Konzept hat Linux von Unix übernommen. Allerdings funktioniert das simple Schema nicht in jedem Fall, zum Beispiel wenn ein User sein Kennwort ändern möchte. Das Passwort steht in »/etc/passwd« oder »/etc/shadow«, beide Dateien sind für einen normalen Benutzer aber nicht schreibbar und nur »/etc/passwd« ist lesbar. Ein pauschales Schreibrecht wäre fatal, denn jeder Anwender und jede Anwendung könnte alle Passwörter ändern. Unter fremder FlaggeUm das Dilemma zu lösen, erfand Dennis Ritchie, einer der Unix-Väter, das Set-UID-Bit. Die Bell Laboratories meldeten seine Idee 1973 sogar zum Patent an, das sie 1979 unter der Nummer 4 135 240 auch erhielten [1] und später als Public Domain freigaben. Mit dem Set-UID-Bit ist es möglich, dass ein Benutzer einen Prozess erzeugt, der die Rechte des Dateibesitzers, also eines anderen Benutzers, ausübt. Auf Fedora 8 sieht zum Beispiel das Passwort-Programm wie folgt aus: -rwsr-xr-x 1 root root 25604 5. Apr 2007 /usr/bin/passwd Die Programmdatei gehört »root« und hat das Set-UID-Bit gesetzt, erkennbar an dem kleinen »s« statt eines »x« an vierter Stelle. Der entstehende Prozess »passwd« hat dank S-Bit effektiv die Rechte des Benutzers »root« (Effective UID), also die Rechte des Besitzers der Programmdatei. Die Rechte des aufrufenden Users behält er aber bei (Real UID). Dank Saved UID kann der Prozess sogar jederzeit zwischen den Rechten wechseln. Ruft der Benutzer »ralf« den Befehl »passwd« auf, dann lassen sich die Rechteverhältnisse mit dem Befehl »ps -o cmd,pid,ppid,euser,ruser, -U ralf« anzeigen: CMD PID PPID EUSER RUSER -bash 2851 2848 ralf ralf passwd 2912 2851 root ralf Die Ausgabe verrät, dass der Benutzer »ralf« sich angemeldet hat, ihm gehört die Login-Shell »-bash«. Anschließend hat er den Befehl »passwd« aufgerufen. Der läuft mit der realen User-ID (Ruser) »ralf« und der effektiven UID (Euser) »root«. Nun könnte das »passwd«-Tool alle Möglichkeiten von Root nutzen und beispielsweise fremde Passwörter ändern oder die Firewall abschalten. Solange keine Programmierfehler vorliegen, beschränkt sich »passwd« freilich darauf, das Passwort des aufrufenden Users zu ändern. Um das Risiko zu mindern, haben die Linux-Distributoren in den letzten Jahren den Einsatz der Set-UID-Bits reduziert. |
Kampf der Gießkanne
Um der Rechtevergabe nach dem Gießkannenprinzip zu entkommen, haben die Unix-Hersteller Alternativen gesucht. Entstanden sind die Capabilities, die einzeln aufführen, welche Rechte ein Prozess haben kann. Es gab unter den Nummern Posix.6 und später Posix 1003.1e sogar einen Entwurf für einen Standard. Nach 13 Jahren Komitee-Arbeit verwarf das IEEE den Entwurf aber im Jahr 1998 [2]. Dieser Teil der Geschichte lebt heute noch im Namen Posix Capabilities (kurz Pcaps) weiter – und in den Access Control Lists (ACL), die ebenfalls ihre Wurzeln in diesen Arbeiten haben.
Root zerteilt
Seit Kernel 2.2, genauer seit dem 2.1er Entwicklungszyklus, unterteilt Linux das Root-Recht in diskrete Privilegien, über die ein Prozess verfügen kann. Diese Privilegien heißen unter Linux Posix Capabilities oder Pcaps, während Sun sie in Solaris als Privilege bezeichnet. Ein Prozess darf unter Linux sogar die notwendigen Pcaps für einzelne Codeabschnitte aktivieren (auf »effective« setzen) oder abschalten. Sie sind somit für Bugs in anderen Codeteilen nicht nutzbar. Welche Capabilities unter Linux bereitstehen, zeigen Tabelle 1, die Manpage »capabilities(7)« sowie die Kommentare im Header »/usr/include/sys/capability.h« oder in den Kernelsourcen in »/usr/src/linux/include/linux/capability.h«.
|
Tabelle 1: Posix |
|---|
Grenzen setzen
Administrativ ließen sich Posix Capabilities bislang nur systemweit über die Schnittstelle »/proc/sys/kernel/cap-bound« verwalten. Hiermit konnte der Administrator einem laufenden Gesamtsystem Capabilities unwiderruflich entziehen, sie waren bis zum Reboot nicht mehr verfügbar. Ohne »CAP_SYS_MODULE« ist es zum Beispiel nicht mehr gestattet, Module in den Kernel zu laden, und ohne »CAP_SYS_BOOT« gelingt kein geordneter Reboot mehr.
Mit den Programmen aus dem Libcap1-Paket [7] war es immerhin möglich, die Capabilities laufender Prozesse zu setzen. Auch komplexe MAC-Systeme wie App Armor und SE Linux [3] erlauben es quasi nebenbei, die Capabilities von Prozessen zu ändern. Wer Befehlen wie »ping«, »passwd« und »mount« statt voller Root-Rechte aber nur die tatsächlich nötigen Capabilities verleihen will, sucht viel simplere Tools als solche, die ihm primär ein neues Zugriffsrechtemodell ins System pflanzen. Was bislang fehlte, war eine praktikable Möglichkeit, einem Programm die notwendigen Privilegien in Form von Pcaps im Vorhinein zuzuweisen, analog zum Setzen des S-Bit im Dateisystem. Die notwendige Infrastruktur fehlte im Kernel.
Es gab bereits mehrfach Patches für den Linux-Kernel, die diese Funktionalität ergänzen ([4], [5], [6]). Das Patch von Serge E. Hallyn [4] hat nun endlich alle Hürden genommen und ist im Linux-Kernel 2.6.24 enthalten. Für ein komplettes System fehlen noch Userspace-Tools zum Anzeigen und Setzen der Posix Capabilities. Hier sorgen Andrew Morgan und KaiGai Kohei für Abhilfe.
Kontrolle aus dem Userspace
Andrew Morgan entwickelte vor Jahren das Paket Libcap1 [7], das allerdings nicht zu den Patches von Serge E. Hallyn passt. Das änderte KaiGai Kohei im Rahmen des Google Sommer of Code, dazu erweiterte er das Paket von Morgan um eigene Patches. Ende 2007 nahm Andrew die Arbeiten an der Libcap wieder auf und integrierte auch die Version von Kohei. Daraus entstand die Libcap2 [8]. Das Paket enthält die Tools »getcap« und »setcap« zum Lesen beziehungsweise Setzen der Pcaps. Derzeit ist es in der Regel noch nötig, die Userspace-Tools aus den Quellen zu installieren. Chris Friedhoff hat bisher die umfangreichste Dokumentation zu diesem Thema zusammengestellt ([9] und Kasten “Auferstehung der Pcaps”).
Einsatz unter Linux
Für den Filesystem-Support der Pcaps ist ein Linux-Kernel mit aktivierten File Posix Capabilities nötig. In aktuellen Distributionen bedeutet das meist, Linux von Kernel.org zu laden, selbst zu übersetzen und in den Security Options das Feld »File POSIX Capabilities« anzukreuzen (siehe Abbildung 1). Bei der Gelegenheit empfiehlt es sich auch, das Kprobes-Interface zu aktivieren (Abbildung 2). Das hilft später beim Ermitteln der von den Programmen benötigten Capabilities. Zudem muss das verwendete Dateisystem Extended Attributes unterstützen.
Läuft der neue Kernel, dann fehlen noch passende Userspace-Werkzeuge. Die sind als Teil der Libcap2 auf Kernel.org zu finden [8]. Wie üblich gilt es, die Quellen zu laden, zu übersetzen und zu installieren. Hierfür genügt »make && make install«, ein Configure-Schritt ist nicht vorgesehen. Anschließend stehen die Befehle »setcap« und »getcap« zusammen mit ihren Manpages zur Verfügung. Für einen Capability-Test bietet sich neben den beiden Befehlen »ping« und »traceroute« das Skript »quicktest.sh« an.
Ping braucht Privilegien, um die speziellen ICMP-Pakete ins LAN senden zu dürfen. Normalerweise verschafft das Set-UID-Root-Bit dem Tool diese Fähigkeiten. Nach einem »chmod u-s /bin/ping« fehlen diese Privilegien, und sobald ein unprivilegierter Benutzer das Kommando aufrufen will, scheitert zum Beispiel »ping localhost«:
ping: icmp open socket: Die Operation ist nicht erlaubt
Um »ping« wieder für jeden Benutzer benutzbar zu machen, braucht das Tool passende Posix Capabilities. Herausfinden, welche Capability genau erforderlich sind, bedeutet normalerweise die Funktionsweise eines Tools studieren und dann gezielt die richtigen Capabilities setzen – zu viele wären unnötig riskant und bei zu wenigen funktioniert das Tool nicht. Das klingt nach einer aufwändigen Aufgabe. Doch es geht einfacher: Das »Capable_Probe«-Modul von Serge E. Hallyn [10] meldet via Syslog jeden Prozess und die geforderte Pcap.

Abbildung 1: Die File Posix Capabilities sind zwar seit Kernel 2.6.24 enthalten, allerdings per Default deaktiviert. Falls »Enable different security models« ausgewählt ist, muss auch noch »Default Linux Capabilities« aktiviert sein.

Abbildung 2: Die Kprobes-Schnittstelle findet zusammen mit dem Modul »Capable_Probe« heraus, welche Posix Capabilities ein Programm braucht. Die »Kprobes«-Konfiguration befindet sich unter »Instrumentation Support«.
Bedürftigkeit ermittelt
Die Meldungen landen meist in der Logdatei »/var/log/messages« oder in »/var/log/kern.log«. Das Modul sollte nicht immer geladen sein, da es sonst die Logfiles mit großen Mengen unerwünschter und überflüssiger Meldungen flutet. Lediglich für die Diagnose der benötigten Posix Capabilities sollte der Administrator das geschwätzige Modul laden und anschließend mit »modprobe -r capable_probe« wieder entfernen.
Listing 1 zeigt, welche Nachrichten Ping verursacht. Der Klartext zu den Capability-Nummern steht in »/usr/include/linux/capability.h«, eine Zusammenfassung dazu in Tabelle 1.
|
Listing 1: |
|---|
01 Feb 14 12:34:49 station1 kernel: cr_capable: asking for capability 13 for ping 02 Feb 14 12:34:49 station1 kernel: cr_capable: asking for capability 7 for ping 03 Feb 14 12:34:49 station1 kernel: cr_capable: asking for capability 21 for ping |
Zu gierig
Ping versucht also, die Capabilities 13 »CAP_NET_RAW«, 7 »CAP_SETUID« und 21 »CAP_SYS_ADMIN« wahrzunehmen. Die Set-UID-Manipulation (7) ist allerdings unnötig und auch das mächtige 21 scheint kein geeigneter Kandidat zu sein. »CAP_NET_RAW« klingt vielversprechend und der folgende Befehl gewährt Ping diese Capability:
setcap cap_net_raw=ep /bin/ping
Anschließend kann wieder jeder unprivilegierte Benutzer pingen. Offenkundig genügt dieses Privileg dem »ping«. Nur wenn er das gewünschte Socket nicht öffnen kann, versucht der Befehl weitere Schritte, die das Capable_Probe-Modul auch prompt meldet. Wegen dieses recht häufigen Phänomens empfiehlt es sich, die angemeckerten Privilegien der Reihe nach zuzuweisen und dabei gründlich zu überdenken, wie plausibel es ist, dass ein Programm die jeweilige Capability benötigt. Für viele Programme hat Chris Friedhoff [9] schon die benötigten Posix Capabilities aufgelistet.
Posix Capability Sets
Um die Vererbung und das dynamische Ein- und Ausschalten von Posix Capabilities in geregelte Bahnen zu lenken, besitzen Programme und Prozesse drei Sätze (Capability Sets) von Pcaps. Die Bedeutung der Sets unterscheidet sich je nachdem, ob es sich um einen Prozess oder eine Datei handelt: Permitted »p«, Effective »e« und Inheritable »i«. Tabelle 2 beschreibt die Details der erlaubten, aktiven und vererbten Rechte. Für File Pcaps gilt zudem, dass nur jene aus dem fP- oder fI-Set auch im fE-Set sein können. Für Process Pcaps gilt hingegen, dass nur die aus dem pP-Set auch im pE- oder pI-Set sein können.
Ist eine Anwendung auf Pcaps vorbereit, wird sie nur mit einem Permitted Set arbeiten und das Effective Set die meiste Zeit leer lassen. Nur um die Codestellen herum, die Privilegien brauchen, wird sie die Pcaps aktivieren. Auch bestimmt diese Anwendung selber, welche Capabilities in ihrem Inheritance Set stehen und sie potenziell an neue Prozesse vererbt. Programme, die sich nicht selbst um Pcaps kümmern, brauchen zusätzlich zum Permitted Set auch ein passendes Effective Set. Das File Effective Set verleiht ihnen vom Start weg die nötigen Privilegien:
setcap cap_net_raw=ep /bin/ping
Beim Setzen der File Posix Capabilities stehen drei Operatoren zur Verfügung: »=«, »+« und »-«. Sie funktionieren ähnlich wie die Operatoren des Befehls »chmod«. Allerdings ist die Reihenfolge gewöhnungsbedürftig: »cap_net_raw=ep« aktiviert die Capability in den beiden Sets Effective und Permitted und löscht sie im Inheritable Set. Mit »+« und »-« addiert beziehungsweise subtrahiert »setcap« die Capabilities in den entsprechenden Sätzen, ohne die anderen Sets zu beeinflussen.
Welche Pcaps eine Datei hat, zeigt das Kommando »getcap«. In einem normalen Directory-Listing sind Dateien mit Extended Attributes leider nicht zu erkennen – das ist ein Problem, das alle Extended Attributes und so auch die Posix Capabilities haben. Das Extended-Attribute-Tool »attr -l« zeigt immerhin, dass ein Programm über das erweiterte Attribut »capability« verfügt, also dass ihm File Pcaps zugewiesen sind.
|
Tabelle 2: Posix Capability |
|---|
Oft, aber nicht immer
Auch der oben genannte Befehl »passwd« funktioniert mit den Filesystem-Capabilities – das Set-UID-Flag wird damit entbehrlich. Er braucht das Recht, die Dateizugriffskontrolle zu umgehen. Ein Blick in Tabelle 1 zeigt, welche Capability das erledigt:
setcap cap_dac_override=ep /usr/bin/passwd
In der Praxis reichen die Rechte unter Umständen nicht, vor allem wenn das Passwort-Programm mit PAM arbeitet (Pluggable Authentication Modules, [11]), braucht es für die weiteren Aufgaben auch weitere Privilegien.
Viele Dienste, die zwar kein Set-UID-Flag haben, dafür aber mit der User-Kennung Root starten, können mit Hilfe der Pcaps von Anbeginn unter einem unprivilegierten Account laufen. Chris Friedhoff zeigt auf seiner Seite [9] exemplarisch, wie das bei Apache, Bind, Samba und dem DHCP-Server funktioniert. Interessanterweise kombiniert er Posix Capabilities und Set-UID-Technik, er nutzt aber eigene User- und Gruppen-IDs für jeden Dienst. Allerdings müssen die Zugriffsrechte per ACL auf die mit Pcaps ausgestatteten Files dafür sorgen, dass kein unprivilegierter User Apache oder Bind mit unerwünschten Optionen startet.
Scheitern an UID 0
Leider ersetzen File Posix Capabilities die Set-UID-Root-Technik nicht immer problemlos. Viele Applikationen erwarten schlicht, dass sie als Root laufen, und prüfen dazu ihre User-ID. Ein simpler Test entlarvt diese Vorgehensweise:
- Dem Programm alle Posix Capabilities gewähren
- Set-UID-Bit entfernen oder privilegierte Dienste als normaler
User starten
Auf einem Fedora-8-System reagiert zum Beispiel der NTP-Server empfindlich auf die Änderung. Dank der vollen Capabilities hätte er faktisch trotz Nobody-Userkennung dieselben Rechte wie unter dem Root-Account. Er bemerkt dies aber nicht und besteht auf UID=0:
# setcap all=ep /usr/sbin/ntpd # su - nobody $ /usr/sbin/ntpd must be run as root, not uid 99
Alle Pcaps auf einmal sind mit »all=ep« schnell ausgewählt. Allerdings funktioniert das erst ab Libcap 2.08, frühere Versionen haben einen Bug bei der Umwandlung eines 64-Bit- in einen 32-Bit-Wert. Wer eine ältere Version verwendet, muss alle Capabilities einzeln setzen. Neben deren Namen versteht »setcap« glücklicherweise auch die Nummern, ein Konstrukt wie »setcap `seq -s, 0 31`=ep /usr/sbin/ntpd« ersetzt das »all«.
Läuft das Programm mit allen Posix Capabilities auch nach dem Start durch einen unprivilegierten Benutzer, kann der Admin sukzessive die überflüssigen Capabilities entfernen.
Mehr Privilegien
Mit den Filesystem-Capabilities ist es sogar möglich, unprivilegierten Benutzern Funktionen zu erlauben, die bisher bei Einsatz der Set-UID-Bits als sehr kritisch angesehen wurden. So kann der Sysadmin dem Befehl »ntpdate« die notwendigen Capabilities zuweisen. Dann darf auch ein normaler User die Zeit des Systems mit einem zentralen Zeitserver synchronisieren. Folgendes Kommando erteilt die Rechte:
setcap cap_net_bind_service,cap_sys_time=ep /usr/sbin/ntpdate
Anschließend darf ein unprivilegierter Benutzer den Befehl verwenden. Allerdings lauern hier neue Gefahren: Auch Otto Normaluser könnte das »ntpdate«-Kommando auf einen gefälschten Zeitserver ausrichten und damit die Systemzeit – böswillig oder nicht – verstellen.
Vorsicht Falle
Während ein Admin diesen Angriff vielleicht noch erwartet, rechnet die Software selbst vermutlich nicht damit, mehr Privilegien zu haben als ihr Aufrufer. In dieser Situation müssen Programme besonders sorgsam arbeiten, um sich nicht von findigen Usern für unerwartete Zwecke missbrauchen zu lassen. Ob eine Software ausreichend sicher programmiert ist, kann letztlich nur ein eingehendes Audit entscheiden. Immerhin: Schlimmstenfalls bleiben die Zusatzrechte, die ein Angreifer erlangt, auf die Capabilities des geknackten Programms beschränkt, während beim allmächtigen Set-UID-Root das Risiko erheblich höher ausfällt.
Endlich
Die File Posix Capabilities erlauben es, die schon lange im Kernel vorhandenen Posix Capabilities über das Dateisystem zu verwalten. Das funktioniert so, wie es ein Unix/Linux-Admin erwartet: Das Kommando »setcap Privilegien Datei« setzt die fein separierten Posix Capabilities ganz so wie ein »chown root && chmod u+s Datei«, das pauschale Set-UID-Root-Rechte verleiht. Schade nur, dass derzeit »ls« & Co. nichts über die zusätzlichen Rechte verraten, hierzu ist ein »getcap«-Aufruf nötig.
Set-UID-Root durch Posix Capabilities zu ersetzen schließt keine Sicherheitslücken. Programme, die nicht auf Pcaps vorbereitet sind, können schlimmstenfalls sogar anfälliger werden. Im Ernstfall begrenzen Capabilities aber die Folgen: Statt sofort zum Sysadmin zu mutieren, erhält ein erfolgreicher Angreifer nur wenige Zusatzrechte, mit denen er deutlich weniger Schaden anrichten kann. (fjl)
|
Infos |
|---|
|
[1] Set-UID-Patent von Dennis Ritchie und den Bell Labs: [http://www.freepatentsonline.com/4135240.html] [2] Winfried Trümper über Posix.1e: [http://wt.xpilot.org/publications/posix.1e/] [3] Schwerpunkt zu App Armor und SE Linux: Linux-Magazin 06/06 [4] Serge E. Hallyns Patch: [http://lkml.org/lkml/2006/11/27/170] [5] Olaf Dietsches Patch: [http://www.olafdietsche.de/linux/capability/] [6] David A. Madores Patch: [http://www.madore.org/~david/linux/newcaps/] [7] Libcap1: [http://www.kernel.org/pub/linux/libs/security/linux-privs/libcap1/] [8] Libcap2: [http://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/] [9] Chris Friedhoff, “POSIX File Capabilities”: [http://www.friedhoff.org/posixfilecaps.html] [10] Capable_Probe: [http://www.friedhoff.org/posixfilecaps/capable_probe.tar.bz2] [11] Dirk von Suchodoletz, “Hereinspaziert: Die Pforten zur Linux-Maschine – Pluggable Authentication Modules”: Linux-Magazin 05/04, S. 38 [12] Ralf Spenneberg, “Linux Capabilities”, in: “SELinux & AppArmor”, [http://www.os-t.de/HTML-SELinux/node20.html] [13] Serge E. Hallyn, “POSIX file capabilities: Parceling the power of root”: [http://www.ibm.com/developerworks/linux/library/l-posixcap.html] |










