Das Sandbox2-Design basiert auf bekannten und etablierten Technologien, einem Richtlinienframework und zwei Prozessen: dem Sandbox-Executor und dem Sandboxee.
Beteiligte Technologien
In den folgenden Abschnitten werden die Technologien behandelt, die die Grundlage für Sandbox2 bilden.
Linux-Namespaces
Linux-Namespaces sind ein Versuch, Virtualisierung auf Betriebssystemebene zu ermöglichen. Mehrere Userspaces werden scheinbar unabhängig voneinander ausgeführt, teilen sich aber eine einzelne Kernel-Instanz. In Sandbox2 werden die folgenden Arten von Namespaces verwendet:
- IPC
- Netzwerk (sofern nicht explizit durch Aufrufen von
PolicyBuilder::AllowUnrestrictedNetworking()deaktiviert) - Mount (mit einer benutzerdefinierten Ansicht der Dateisystemstruktur)
- PID
- Nutzer
- UTS
Weitere Informationen zu Linux-Namespaces finden Sie auf Wikipedia oder auf der entsprechenden Manpage.
IPC
Mit Sandbox2 können beliebige Daten zwischen dem Sandbox-Executor und dem nicht vertrauenswürdigen Sandboxee ausgetauscht werden. Es werden TLV-Nachrichten (Type-Length-Value), die Übergabe von Dateideskriptoren und der Austausch von Anmeldedaten über Tokens und Handles unterstützt.
Seccomp-BPF
Sandbox2 basiert auf seccomp-bpf, einer Erweiterung des sicheren Berechnungsmodus (seccomp), mit der Berkeley Packet Filter-Regeln (BPF) zum Filtern von Systemaufrufen verwendet werden können.
seccomp ist eine Linux-Kernel-Funktion, die die Systemaufrufe eines Prozesses auf exit, sigreturn, read und write beschränkt. Wenn ein Prozess versucht, einen anderen Systemaufruf auszuführen, wird er beendet. Die seccomp-bpf-Erweiterung bietet mehr Flexibilität als seccomp. Anstatt eine feste Anzahl von Systemaufrufen zuzulassen, führt seccomp-bpf ein BPF-Programm für die Systemaufrufdaten aus. Je nach Rückgabewert des Programms kann der Systemaufruf ausgeführt, übersprungen und ein Dummy-Wert zurückgegeben, der Prozess beendet, ein Signal generiert oder der Tracer benachrichtigt werden.
Ptrace
Der Systemaufruf ptrace (Prozessverfolgung) bietet Funktionen, mit denen der Tracer-Prozess die Ausführung des Tracee-Prozesses beobachten und steuern kann. Sobald der Tracer-Prozess angehängt ist, hat er die vollständige Kontrolle über den Tracee. Weitere Informationen zu ptrace finden Sie auf Wikipedia oder auf der entsprechenden Manpage.
Sandbox-Richtlinie
Die Sandbox Richtlinie ist der wichtigste Teil einer Sandbox, da sie die Aktionen angibt, die der Sandboxee ausführen kann und nicht ausführen kann. Eine Sandbox-Richtlinie besteht aus zwei Teilen:
- Systemaufrufrichtlinie
- Namespace-Einrichtung
Standardrichtlinie für Systemaufrufe
Die Standardrichtlinie blockiert Systemaufrufe, die immer gefährlich sind, und hat Vorrang vor der vom Nutzer bereitgestellten erweiterten Richtlinie.
Erweiterte Richtlinie für Systemaufrufe
Die erweiterte Richtlinie für Systemaufrufe kann mit der
PolicyBuilder
erstellt werden. Diese Klasse definiert eine Reihe von praktischen Regeln (z.B. AllowStaticStartup, AllowDynamicStartup, AllowOpen), mit denen die Lesbarkeit Ihrer Richtlinie verbessert werden kann.
In den meisten Fällen sollten Sie mit
DefaultPolicyBuilder
(sapi::Sandbox2Config::DefaultPolicyBuilder()) beginnen. Dadurch wird ein
PolicyBuilder zurückgegeben, der mit einer Basisrichtlinie für typische
Single-Thread-Bibliotheken vorkonfiguriert ist und mit zusätzlichen Regeln angepasst werden kann
(z. B. .AllowDynamicStartup() und .AddLibrariesForBinary() beim Sandboxing
einer Binärdatei). In Sandboxed API (SAPI) wird DefaultPolicyBuilder() von sapi::SandboxConfig::DefaultConfig() zusammen mit sapi::SandboxConfig::DefaultFlags(), sapi::SandboxConfig::DefaultEnvironmentVariables() und sapi::Sandbox2Config::DefaultLimits() verwendet. Ein PolicyBuilder sollte nur dann direkt
verwendet werden, wenn DefaultPolicyBuilder() nicht verwendet werden kann oder eine
genaue Konfiguration erforderlich ist.
Wenn Sie Systemaufrufe weiter einschränken oder komplexere Regeln benötigen, können Sie
rohe BPF-Makros mit AddPolicyOnSyscall und AddPolicyOnSyscalls angeben. Im
crc4-Beispiel wird dieser
Mechanismus verwendet, um Argumente für die read, write, und close Systemaufrufe einzuschränken.
Im Allgemeinen gilt: Je strenger die Sandbox-Richtlinie, desto besser, da die Ausnutzung von Schwachstellen im Code durch die Richtlinie eingeschränkt wird. Wenn Sie genau angeben können, welche Systemaufrufe und Argumente für den normalen Betrieb des Programms erforderlich sind, sind auch Angreifer, die eine Schwachstelle zur Code-Ausführung ausnutzen, auf dieselben Einschränkungen beschränkt.
Eine sehr strenge Sandbox-Richtlinie könnte alle Systemaufrufe außer Lese- und Schreibvorgängen für Standardeingabe- und Standardausgabe-Dateideskriptoren ablehnen. In dieser Sandbox könnte ein Programm Eingaben entgegennehmen, verarbeiten und die Ausgabe zurückgeben. Wenn der Prozess jedoch versuchen würde, einen anderen Systemaufruf auszuführen, würde er aufgrund eines Richtlinienverstoßes beendet. Wenn der Prozess also kompromittiert wird (Code-Ausführung durch einen böswilligen Nutzer), kann er nichts Schlimmeres anrichten als eine fehlerhafte Ausgabe zu erzeugen (die vom Executor und anderen weiterhin korrekt verarbeitet werden muss).
Namespace-Einrichtung
Das PolicyBuilder-Objekt wird auch verwendet, um die individuelle Ansicht des Dateisystems für einen Sandboxee einzurichten. Einzelne Dateien (AddFile / AddFileAt), ganze Verzeichnisse
(AddDirectory / AddDirectoryAt) sowie temporärer Speicher (AddTmpfs)
können in die Umgebung des Sandboxee eingebunden werden. Außerdem kann AddLibrariesForBinary verwendet werden, um automatisch alle Bibliotheken einzubinden, die von der angegebenen dynamisch verknüpften ausführbaren Datei benötigt werden.
Befehlszeilen-Flags
Jede Sandbox2-Richtlinie kann deaktiviert werden, indem eines der folgenden Befehlszeilen-Flags angegeben wird. Diese Flags sind für Testzwecke vorgesehen (z.B. beim Optimieren der erweiterten Richtlinie für Systemaufrufe).
--sandbox2_danger_danger_permit_all--sandbox2_danger_danger_permit_all_and_log
Sandbox-Executor
Der Sandbox Executor ist ein Prozess, der selbst nicht in einer Sandbox ausgeführt wird. Er ist der ptrace-Tracer-Prozess, der an den Sandboxee angehängt wird (ptrace-Tracee-Prozess). Der Sandbox-Executor richtet auch eine Monitor -Instanz ein und führt sie aus, die den Sandboxee verfolgt und Statusinformationen bereitstellt.
Sandbox2 bietet drei Ausführungsmodi: Standalone, Sandbox2-Forkserver und benutzerdefinierter Forkserver. Wenn Sie einen Forkserver verwenden, wird der Sandboxee als untergeordneter Prozess des Sandbox-Executors erstellt. Diese Modi werden hier ausführlich erläutert.
Sandboxee
Der Sandboxee ist der Prozess, der in der eingeschränkten Sandbox-Umgebung ausgeführt wird, die durch die Sandbox-Richtlinie definiert wurde. Der Sandbox-Executor sendet die Richtlinie über IPC an den Sandboxee. Der Sandboxee wendet dann die Richtlinie an. Jeder Verstoß gegen die Richtlinie führt zur Beendigung des Prozesses, sofern nicht anders konfiguriert (siehe Sandbox-Richtlinie).