SDB:AppArmor details
Getestet mit openSUSE | Empfohlene Artikel | Verwandte Artikel | |||
|
Inhaltsverzeichnis
Funktion von AppArmor
Das hört sich einfach an, ist momentan aber schwierig umzusetzen; so können Sie zwar Anwendungen daraufhin testen, dass sie die Funktionen erbringen, für die sie gedacht sind, aber nicht darauf, dass sie nie etwas ausführen, was nicht gewollt ist, wenn sie fremdartige Eingaben erhalten, da die Liste der möglichen Eingaben unendlich ist. Kurz und bündig von Ivan Arce folgendermaßen zusammengefasst: "Reliable software does what it is supposed to do. Secure software does what it is supposed to do... and nothing else." (Zuverlässige Software macht, was sie machen soll. Sichere Software macht, was sie machen soll... und sonst nichts.)
Aufbau
Es gibt Werkzeuge, die Quellcode und/oder binäre Dateien während der Kompilierung auf mögliche Schwachstellen überprüfen. Allerdings sind diese Lösungen während des Übersetzens der Software auf Grund theoretischer und praktischer Gründe nur schwer umzusetzen und leisten keine vollständige Arbeit. Aus wirtschaftlichen und sozialen Gründen werden solche Werkzeuge und sorgfältige Pflege nur selten angewandt. Als Ergebnis dessen enthält die meiste Software reichlich latent vorhandene Fehler, von denen viele von Angreifern ausgenutzt werden können um die Programme zu kompromittieren. Sicherheit wäre einfach, wenn man nur noch fehlerfreie Software schreiben würde, woran es allerdings wohl ewig hapern wird :)
Ziele
Um potentielle Sicherheitsrisiken zu bekämpfen, wollen wir das Prinzip der mindestnotwendigen Rechte für Software anwenden. Wann immer eine Anwendung läuft, sollte sie nur die Rechte zur Verwendung der Systemressourcen besitzen, die sie unbedingt zum Funktionieren benötigt. Sollte sie trotzdem einmal kompromittiert werden, wird das Ausmaß eines möglichen Schadens auf ein Mindestmaß reduziert. Trotz dieser Rechtebeschränkung muss die Ausführung von Programmen sicher, transparent und schnell erfolgen.
- Sicher - Die Anwendung kann nicht aus diesen Einschränkungen ausbrechen oder sie umgehen.
- Schnell - Der Geschwindigkeitsverlust ist vernachlässigbar.
- Transparent - Anwendungen und Benutzer können ihre Aufgaben mit nur wenigen Änderungen wie eh und jeh erledigen.
Sicherheit ist lebenswichtig, so dass sie keine Täuschung sein sollte. Transparenz und Geschwindigkeit sind wichtig, da die schlechteste Sicherheit die ist, die ausgeschaltet wird, weil sie zu problematisch oder arbeitsintesiv ist. Hier beschreiben wir, wie AppArmor Sicherheit, Geschwindigkeit und Transparenz erreicht.
Sicherheit durch LSM: Linux Security Modules Schnittstelle
Um (nicht umgehbare) Sicherheit mit vermittelnden Methoden wie AppArmor zu erreichen, muss diese im Kernel verankert sein. AppArmor war ursprünglich ein Kernelpatch, was aber zu großen Problemen beim Verteilen und Einsetzen führte, besonders bei Firmenkunden. Um Kernel seitige Sicherheit ohne das Verwenden von Kernelpatches zu erreichen, ersann Immunix Inc. (welche AppArmor entwickelt haben, bevor sie von Novell gekauft wurden) eine Möglichkeit für Linux 2.6 namens LSM: Linux Security Modules Schnittstelle. LSM stellt eine Kernel-API für Module zur Verfügung, welche es nachladbaren Modulen ermöglicht, eine Schicht zur effektiven Zugriffskontrolle einzuführen. Andere Mitwirkende bei der Entwicklung von LSM sind die SELinux Entwicklergemeinde, IBM, und verschiedene andere OSS-Entwickler.
Die Vermittlung durch andere Schichten als den Kernel bsw. Bibliotheken führt zu Umgehung' s Möglichkeiten: Wenn ein Angreifer beliebigen Code in eine eingeschränkte Anwendung einschleusen kann (bsw. durch Pufferüberläufe) dann kann er das Programm auch veranlassen, den Kernel direkt anzusprechen ohne den Umweg über die Sicherheitsbibliothek, was zur Umgehung der Sicherheitsrichtlinien führen würde. Deshalb ist solch eine Beschränkung am besten tief im Kernel aufgehoben und es ist nicht mit dem Abfangen von Systemaufrufen getan. Sicherheitsvermittlungen können auch durch das Ersetzen der syscall-Tabelle erreicht werden (wie es von Systrace gemacht wird), was aber zu drei signifikanten Problemen führt:
- Codeverstopfung: Der Kernel hat eine Menge an Infrastruktur Informationen zu übersetzen, bspw. die Anfrage, eine Datei namens "foo" in einen bestimmten inode unter Berücksichtigung des aktuellen Arbeitsverzeichnisses zu öffnen, usw. Keine dieser Informationen ist in dem Moment verfügbar, wenn der Systemaufruf abgefangen wird, weshalb ein Vermittlungssystem den Code verdoppeln muss, um ihn erst zu übersetzen, bevor es entscheiden kann, ob es Zugriff auf "foo" gewährt. Schlimmer noch: Da die Übersetzung doppelt geschieht, tritt auch noch eine zusätzliche Wartezeit ein.
- SMP Sicherheit: Der Name der Datei befindet sich im Nutzer verfügbaren Arbeitsspeicher, was ihn in der Zeit angreifbar macht, in der das Vermittlungsmodul die Zugriffsberechtigung überprüft und der Kernel den Zugriff erlaubt. Das Vermittlungsmodul sieht dann eine Anfrage auf die Datei "foo" und nachdem es sie freigegeben hat, ändert der Nutzer die Anfrage auf "../bar". Dieser Angriff funktioniert besonders gut auf SMP-Systemen, welche in naher Zukunft die meisten sein werden, wenn die überwiegende Zahl der Prozessoren Mehrkernausführungen sind.
- Linus: Aus Gründen, die sich aus der GPL ableiten, hat Linus sich entschieden, die Möglichkeit zum Nachladen der syscall-Tabelle in Linux 2.6 zu entfernen, so dass das Vermitteln von Systemaufrufen in modernen Kernel ohne das Einspielen eines Kernel Patches problematisch ist.
Im Gegensatz zur Vermittlung von Systemaufrufen ist LSM tief im Kernel verankert. Wann immer der Aufruf eines Benutzerebenen Prozesses zum Zugriff auf eine wichtige tiefere Kernel Datenstruktur führt, wie Funktion' s Deskriptoren oder inodes, fragt die LSM-Verankerung bei einem geladenen LSM-Modul nach, ob dieser Aufruf rechtens ist. Das LSM-Modul prüft die Situation, trifft eine Entscheidung zur Zugriffskontrolle und antwortet dem Kernel mit "ja" oder "nein", welcher dann den Zugriff freigibt oder dem Anfrager eine Fehlermeldung sendet. Solcherart Zugriffskontrolltechniken wie SELinux und AppArmor können als ladbare Module arbeiten und müssen nicht extra in den Kernel gepatcht werden.
Geschwindigkeit durch Einfachheit
Um Geschwindigkeit zu erreichen, benutzt AppArmor ein sehr einfaches Sicherheitsmodell, so dass Zugriffe schnell überprüft werden können. Die jeweiligen Sicherheitsrichtlinien sind sehr klein gehalten, so dass sie komplett in den Arbeitsspeicher des Kernels geladen werden können, wodurch man nicht auf eine doppelte Speicherarchitektur für die Richtlinien angewiesen ist.
Transparenz durch Vertrautheit
Um Transparenz zu erreichen, nutzt AppArmor die klassische UNIX-Sicherheitssemantik, wendet diese aber auf die Programme an. Eine AppArmor-Richtlinie spezifiziert ein Set aus POSIX.1e-Fähigkeiten und benennt eine Reihe von Dateien, auf die zugegriffen werden kann. Die POSIX.1e-Fähigkeiten werden durch Namen spezifiziert. Die Dateien werden mit dem vollen Pfadnamen angegeben, dabei können die typischen Platzhalter der Shell-Syntax benutzt werden, gefolgt von den Zugriffsmethoden (R, W, und X, mit ein wenig Abstand zur Übersichtlichkeit). So würde eine AppArmor-Richtlinie zum Absichern von ntpd (dem network time protocol daemon) folgendermaßen aussehen:
/usr/sbin/ntpd { #include <abstractions/base> #include <abstractions/nameservice> #include <program-chunks/ntpd> capability ipc_lock, capability net_bind_service, capability sys_time, capability sys_chroot, capability setuid, /etc/ntp.conf r, /etc/ntp/drift* rwl, /etc/ntp/keys r, /etc/ntp/step-tickers r, /tmp/ntp* rwl, /usr/sbin/ntpd rix, /var/log/ntp w, /var/log/ntp.log w, /var/run/ntpd.pid w, /var/lib/ntp/drift rwl, /var/lib/ntp/drift.TEMP rwl, /var/lib/ntp/var/run/ntp/ntpd.pid w, /var/lib/ntp/drift/ntp.drift r, /drift/ntp.drift.TEMP rwl, /drift/ntp.drift rwl, }
Von hier aus ist es relativ unkompliziert, mit einigem Grundlagenwissen und einfachem Ausprobieren zu selbst erstellten Sicherheitsrichtlinien zu gelangen. Trotzdem wäre das immer noch zu mühsam, so dass sich wohl eine große Mehrheit der Entwickler und Benutzer nicht damit beschäftigen wollte. Um die Transparenz aber weiter zu steigern, enthält AppArmor einen "Lernmodus", welcher es erlaubt, Richtlinien zu erstellen, indem man eine Anwendung einfach laufen lässt und dabei überwacht, wie sie sich verhält. Im Lernmodus werden die Regeln nicht sofort umgesetzt sondern es werden nur deren Verletzungen protokolliert und die Prozessverzweigungen verfolgt, so dass der Überwachungsbericht einer Programmausführung am Ende eine charakteristische Beschreibung ihrer Aktivitäten enthält. AppArmor enthält ein Programm zur Protokollanalyse, welches die Protokolle überprüft und den Benutzer auffordert, Fragen zu beantworten und aus den Antworten automatisch ein Programmprofil erstellt. Lernmodus und Protokollanalyse sind außerdem in der Lage, existierende Profile schrittweise zu verbessern, falls diesen noch notwendige Regeln fehlen.
Anwendungs- & Systemsicherheit
Eine einzelne Anwendung kann mit einem individuellen Profil abgesichert werden, aber wie sichert man ein ganzes System ab? Eine wichtige Frage beim Absichern eines jeden Systems lautet: Was wird bedroht? Man könnte einfach für jedes Programm im System ein Sicherheitsprofil erstellen, was aber recht aufwändig und in den meisten Fällen gar nicht nötig ist. Denken Sie dabei zum Beispiel an das Netzwerkbedrohungsmodell: Wir wollen entfernte Angreifer davon abhalten, die Kontrolle über das System zu erlangen. Um solch einen Angriff abzuwehren müssen wir sicherstellen, dass alle Anwendungen die mit dem Netzwerk kommunizieren über ein AppArmor-Profil verfügen. Wenn wir also für jede Anwendung die sich mit dem Netzwerk verbindet ein Profil erstellen, kontrollieren die AppArmor-Sicherheitsrichtlinien alles, was ein Angreifer aus dem Netzwerk mit dem System versuchen könnte.
Beachten Sie: Wenn ein AppArmor-Profil die Ausführung eines anderen Programms gewährt, legt es fest, ob dieser Kindprozess in seinem eigenen Profil ausgeführt wird (bezeichnet als px), im Profil der aufrufenden Anwendung, deren Profil also Erbt (bezeichnet als ix), oder ob der Kindprozess ohne Einschränkungen zur Ausführung kommt (bezeichnet als ux). Die px-Berechtigung sollte für wichtige Programme benutzt werden die Zugriff auf Daten vermitteln, so wie Apache Sendmail ausführt um einige E-Mails zu versenden. Die ix-Berechtigung sollte für kleine Werkzeugprogramme benutzt werden, die mit Daten arbeiten, welche sie vom aufrufenden Prozess bekommen haben, etwa wenn ein Shell-Skript cp zum kopieren einer Datei aufruft. Die ux-Berechtigung ist sehr gefährlich und sollte nur mit Bedacht eingesetzt werden um administrativen Zugriff zu gewähren der nicht von AppArmor reguliert wird, etwa die vom SSH-Daemon gestartete ultimative Systemadministratoren-Shell.
Da das Netzwerkbedrohungsmodell so oft vorkommt, bringt AppArmor ein Systemanalyseprogramm namens unconfined mit, welches den Rechner auf offene Netzwerkports überprüft und die Programme ausfindig macht, die auf diesen offenen Ports lauschen. Danach listet es eventuelle Profile auf, die die betroffenen Programme umgeben. Wenn unconfined meldet, dass alle offenen Netzwerkports zu AppArmor-Profilen führen, ist die schlimmste Bedrohung die von einem entfernten Angreifer für den Rechner ausgeht abgewendet.
Ähnliches gilt beim Schutz eines Einzelplatzrechners vor Netzwerkangriffen: Alle Programme die Netzwerkeingaben verarbeiten sollten von einem Profil umgeben werden. Einige dieser Programme haben ständig Netzwerkports geöffnet, bspw. SSH-Klienten. Manche haben nur flüchtig offene Netzwerkports, bspw. Webbrowser, E-Mail-Klienten und Sofortnachrichtenklienten (IM). Und einige dieser Programme haben gar keine offenen Netzwerkports, sind deshalb aber nicht weniger gefährdet, wie bspw. OpenOffice.org, welches oft damit beauftragt wird ein Textdokument aus einem E-Mailanhang zu öffnen. Trotzdem müssen nicht alle Programme auf dem Arbeitsplatzrechner mit einem Sicherheitsprofil versehen werden, sondern nur die, die Netzwerkverkehr verarbeiten.
In einer anderen Situation, in der ein von Vielen benutzter Einzelplatzrechner vor Angriffen durch lokale Benutzer geschützt werden soll, sollten alle Programme die Maus- oder Tastatureingaben entgegennehmen abgesichert werden, genauso wie eventuell andere vorhandene Lesegeräte wie Strichcode- oder Magnetstreifenleser. Dieses "Tastaturangriffsmodell" ist dem des oben behandelten Netzwerkangriffs ähnlich, nur dass die Gefahr hier eher von lokalen Ein- und Ausgabegeräten wie Tastaturen und Kartenlesern ausgeht, und weniger von Netzwerkschnittstellen.