Kürzlich kündigte der Autor der Cosmopolitan C-Standardbibliothek und der Redbean-Plattform die Implementierung des pledge()-Isolationsmechanismus für Linux an.
Pledge wurde ursprünglich vom OpenBSD-Projekt entwickelt und ermöglicht es, Anwendungen den Zugriff auf ungenutzte Systemaufrufe gezielt zu untersagen (indem eine Whitelist mit zulässigen Systemaufrufen für die Anwendung erstellt und andere Aufrufe blockiert werden). Im Gegensatz zu den in Linux verfügbaren Mechanismen zur Zugriffskontrolle von Systemaufrufen, wie beispielsweise seccomp, ist Pledge von Grund auf so benutzerfreundlich wie möglich gestaltet.
Die gescheiterte Initiative, Anwendungen in der OpenBSD-Basisumgebung mithilfe des Systrace-Mechanismus zu isolieren, hat gezeigt, dass die Isolierung auf der Ebene einzelner Systemaufrufe zu kompliziert und zeitaufwändig ist.
Alternativ wurde Pledge vorgeschlagen, das die Erstellung von Isolationsregeln ermöglichte, ohne ins Detail gehen zu müssen und vorbereitete Zugriffsklassen zu manipulieren.
Die angebotenen Klassen sind beispielsweise stdio (Eingabe/Ausgabe), rpath (schreibgeschützte Dateien), wpath (Dateien schreiben), cpath (Dateien erstellen), tmppath (mit temporären Dateien arbeiten), inet (Sockets-Netzwerk), unix (Unix-Sockets ), dns (DNS-Auflösung), getpw (Lesezugriff auf Benutzerdatenbank), ioctl (ioctl-Aufruf), proc (Prozesssteuerung), exec (Startprozesse) und id (Berechtigungssteuerung).
Die Regeln für die Arbeit mit Systemaufrufen werden in Form von Annotationen spezifiziert, die eine Liste zulässiger Systemaufrufklassen und ein Array von Dateipfaden enthalten, auf die zugegriffen werden darf. Nach dem Kompilieren und Ausführen der modifizierten Anwendung übernimmt der Kernel die Überwachung der Einhaltung dieser Regeln.
Separat wird die Pledge-Implementierung für FreeBSD entwickelt, die sich durch die Möglichkeit auszeichnet, Anwendungen zu isolieren, ohne Änderungen an ihrem Code vorzunehmen, während bei OpenBSD der Pledge-Aufruf auf eine enge Integration mit der Basisumgebung und das Hinzufügen von Anmerkungen zum Code abzielt von jedem.
Pledge ist wie die verbotene Frucht, die wir alle begehren, wenn der Chef sagt, wir sollten Dinge wie Linux verwenden. Warum spielt das eine Rolle? Das liegt daran, dass pledge() die Sicherheit tatsächlich verständlich macht. Linux hatte nie wirklich eine Sicherheitsebene, die Normalsterbliche verstehen können.
Die Entwickler der Linux-Portierung von pledge folgten dem Beispiel von FreeBSD und stellten anstelle von Codeänderungen ein zusätzliches Hilfsprogramm von pledge.com bereit, mit dem sich Einschränkungen anwenden lassen, ohne den Anwendungscode zu verändern. Um beispielsweise das curl-Dienstprogramm so auszuführen, dass es nur Zugriff auf die Systemaufrufklassen stdio, rpath, inet und threadstdio hat, führen Sie einfach `./pledge.com -p 'stdio rpath inet thread' curl http://example.com` aus.
Das Dienstprogramm funktioniert auf allen Linux-Distributionen ab RHEL6 und benötigt keine Root-Rechte. Basierend auf der Cosmopolitan-Bibliothek bietet es zudem eine API zur Verwaltung von Einschränkungen in C-Programmcode. Dies ermöglicht unter anderem die Erstellung von Enklaven, um den Zugriff auf bestimmte Anwendungsfunktionen gezielt einzuschränken.
Es gab in der Vergangenheit einige Entwickler, die dies versucht haben. Ich werde keine Namen nennen, da die meisten dieser Projekte nie abgeschlossen wurden. Wenn es um SECOMP geht, erklären Online-Tutorials nur, wie man Systemaufrufe auf die Whitelist setzt, sodass die meisten Leute das Interesse verlieren, bevor sie herausfinden, wie man Argumente filtert. Die Projekte, die vorankamen, hatten auch Versehen, wie das Ändern von setuid/setgid/sticky-Bits. Daher sollte keine der aktuellen Alternativen verwendet werden. Ich denke, diese Bemühungen bringen uns dem Pledge() viel näher als je zuvor.
Die Implementierung erfordert keine Kernel-Änderungen: Dienstprogrammeinschränkungen werden in SECCOMP-BPF-Regeln übersetzt und unter Verwendung des nativen Systemaufruf-Isolationsmechanismus von Linux verarbeitet. Beispielsweise wird der Aufruf von Promise("stdio rpath", 0) in einen BPF-Filter konvertiert
Sollten Sie mehr erfahren wollen, finden Sie die Details unter folgendem Link.