Sandbox2 – Erläuterung

Das Sandbox2-Design baut auf bekannten und etablierten Technologien, einem Richtlinien-Framework und zwei Prozessen auf: Sandbox Executor und Sandboxee.

Beteiligte Technologien

In den folgenden Abschnitten werden die Technologien beschrieben, die die Grundlage für Sandbox2 bilden.

Linux-Namespaces

Die Linux-Namespaces sind ein Versuch, eine Virtualisierung auf Betriebssystemebene bereitzustellen. Auch wenn mehrere Userspaces scheinbar unabhängig voneinander ausgeführt werden, nutzen sie dieselbe Kernel-Instanz. Sandbox2 verwendet die folgenden Arten von Namespaces:

  • IPC
  • Netzwerk (sofern nicht ausdrücklich durch Aufrufen von PolicyBuilder::AllowUnrestrictedNetworking() deaktiviert)
  • Bereitstellen (mit einer benutzerdefinierten Ansicht der Dateisystemstruktur)
  • PID
  • Nutzer (sofern nicht ausdrücklich durch Aufrufen von PolicyBuilder::AllowUnsafeKeepCapabilities() deaktiviert)
  • UTS

Weitere Informationen über Linux-Namespaces finden Sie auf Wikipedia oder auf der entsprechenden Manpage.

IPC

Sandbox2 ermöglicht den Austausch beliebiger Daten zwischen Sandbox Executor und dem nicht vertrauenswürdigen Sandboxee. TLV-Nachrichten (Type-Length-Value), die Weitergabe von Dateideskriptoren und der Austausch von Anmeldedaten über Tokens und Handles werden unterstützt.

Seccomp-BPF

Sandbox2 basiert auf seccomp-bpf, einer Erweiterung des sicheren Computing-Modus (seccomp), mit der Systemaufrufe mithilfe von Berkeley-Paketfilter-Regeln (BPF) gefiltert werden können.

seccomp ist eine Linux-Kernel-Einrichtung, die die Systemaufrufe eines Prozesses auf exit, sigreturn, read und write beschränkt. Wenn ein Prozess versucht, einen weiteren Systemaufruf auszuführen, wird er beendet. Die Erweiterung seccomp-bpf bietet mehr Flexibilität als seccomp. Anstatt einen festen Satz von Systemaufrufen zuzulassen, führt seccomp-bpf ein BPF-Programm für die Systemaufrufdaten aus. Abhängig vom Rückgabewert des Programms kann es den Systemaufruf ausführen, den Systemaufruf überspringen und einen Dummy-Wert zurückgeben, den Prozess beenden, ein Signal generieren oder den Tracer benachrichtigen.

Ptrace

Der Systemaufruf ptrace (Prozess-Trace) bietet Funktionen, mit denen der Tracer-Prozess die Ausführung des Tracee-Prozesses beobachten und steuern kann. Nach dem Anhängen hat der Tracer-Prozess die vollständige Kontrolle über das 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 festlegt, die der Sandboxee ausführen kann und welche nicht. Eine Sandbox-Richtlinie besteht aus zwei Teilen:

  • Syscall-Richtlinie
  • Namespace einrichten

Standard-Syscall-Richtlinie

Die Standardrichtlinie blockiert immer gefährliche Systemaufrufe und hat Vorrang vor der vom Nutzer bereitgestellten erweiterten Richtlinie.

Richtlinie zu erweiterten Syscalls

Die erweiterte Syscall-Richtlinie kann mithilfe unserer PolicyBuilder-Klasse erstellt werden. Diese Klasse definiert eine Reihe von Convenience-Regeln (z.B. AllowStaticStartup, AllowDynamicStartup, AllowOpen), mit denen die Lesbarkeit Ihrer Richtlinie verbessert werden kann.

Wenn Sie Systemaufrufe weiter einschränken möchten oder komplexere Regeln benötigen, können Sie unformatierte BPF-Makros mit AddPolicyOnSyscall und AddPolicyOnSyscalls angeben. Im crc4-Beispiel wird dieser Mechanismus genutzt, um Argumente für die Systemaufrufe read, write und close einzuschränken.

Im Allgemeinen gilt: Je strenger die Sandbox-Richtlinie, desto besser, denn die Ausnutzung von Sicherheitslücken im Code wird durch die Richtlinie eingeschränkt. Wenn Sie genau festlegen können, welche Systemaufrufe und Argumente für den normalen Betrieb des Programms erforderlich sind, sind alle Angreifer, die eine Sicherheitslücke bei der Codeausführung ausnutzen, ebenfalls auf dieselben Grenzwerte beschränkt.

Eine sehr enge Sandbox-Richtlinie könnte alle Systemaufrufe außer Lese- und Schreibvorgängen für Standardeingabe- und -ausgabedateideskriptoren ablehnen. Innerhalb dieser Sandbox könnte ein Programm Eingaben annehmen, verarbeiten und die Ausgabe zurückgeben. Sollte der Prozess jedoch versuchen, einen weiteren Systemaufruf durchzuführen, wird er aufgrund eines Richtlinienverstoßes beendet. Wenn der Prozess kompromittiert wird (Codeausführung durch einen böswilligen Nutzer), kann er also nichts Schlimmeres tun, als eine schlechte Ausgabe zu erzeugen, die der Executor und andere weiterhin korrekt handhaben müssen.

Namespace einrichten

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 der Sandboxee-Umgebung zugeordnet werden. Außerdem können mit AddLibrariesForBinary automatisch alle Bibliotheken zugeordnet werden, die von der angegebenen dynamisch verknüpften ausführbaren Datei benötigt werden.

Befehlszeilen-Flags

Jede Sandbox2-Richtlinie kann durch Angabe eines der folgenden Befehlszeilen-Flags deaktiviert werden. Diese Flags sind für Testzwecke gedacht (z.B. zur Verfeinerung der Richtlinie für erweiterte Syscalls).

  • --sandbox2_danger_danger_permit_all
  • --sandbox2_danger_danger_permit_all_and_log

Sandbox-Executor

Der Sandbox Executor ist ein Prozess, der nicht in einer Sandbox ausgeführt wird. Es ist der ptrace-Tracer-Prozess, der an die Sandboxee angehängt wird (ptrace-Tracer-Prozess). Sandbox Executor richtet auch eine Monitor-Instanz ein und führt sie aus, die den Sandboxee verfolgt und Statusinformationen bereitstellt.

Sandbox2 ermöglicht drei Ausführungsmodi: Standalone, Sandbox2 Forkserver und Custom ForkServer. Wenn Sie einen Forkserver verwenden, wird das Sandboxee als untergeordneter Prozess von Sandbox Executor 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. Sandbox Executor sendet die Richtlinie über IPC an den Sandboxee. Der Sandboxee wendet dann die Richtlinie an. Jeder Verstoß gegen die Richtlinien führt zur Beendigung des Vorgangs, sofern nichts anderes konfiguriert wurde (siehe Sandbox-Richtlinie).