Häufig gestellte Fragen

Kann ich Threads verwenden?

Ja, Threads werden in Sandbox2 unterstützt.

Alle Threads müssen in einer Sandbox ausgeführt werden

Aufgrund der Funktionsweise von Linux wird die seccomp-bpf-Richtlinie nur auf den aktuellen Thread angewendet. Das bedeutet, dass die Richtlinie nicht auf andere vorhandene Threads angewendet wird, aber zukünftige Threads die Richtlinie übernehmen:

  • Wenn Sie Sandbox2 im ersten Modus verwenden, in dem die Sandbox vor execve() aktiviert wird, erben alle Threads die Richtlinie und es gibt kein Problem. Dies ist die bevorzugte Methode für die Sandbox.
  • Wenn Sie den zweiten Modus verwenden, in dem der Executor set_enable_sandbox_before_exec(false) hat und der Sandboxee dem Executor mitteilt, wann er mit SandboxMeHere() in der Sandbox ausgeführt werden möchte, muss der Filter auf alle Threads angewendet werden. Andernfalls besteht das Risiko eines Sandbox-Ausbruchs: Schädlicher Code könnte von einem Sandbox-Thread zu einem nicht in der Sandbox ausgeführten Thread migrieren.

Wie sollte ich meine Sandboxee kompilieren?

Im Vergleich zu einer statisch verknüpften ausführbaren Datei führt das Kompilieren der Sandboxee zu einer dynamisch verknüpften ausführbaren Datei zu einer erheblichen Zunahme der Systemaufrufe (z.B. open/openat, mmap usw.), die auf die Zulassungsliste gesetzt werden müssen. Alle diese zusätzlichen Systemaufrufe sind aufgrund des dynamischen Linker-Aufrufs zur Laufzeit erforderlich, um die gemeinsam genutzten Bibliotheken zu laden.

Bei statisch verknüpften Sandboxees müssen zwar weniger Systemaufrufe auf die Zulassungsliste gesetzt werden, es gibt aber auch Sicherheitsrisiken: Die ASLR-Heap-Entropie wird von 30 Bit auf 8 Bit reduziert, was Exploits erleichtert.

Dieses Dilemma lässt sich im Wesentlichen auf Folgendes reduzieren:

  • Dynamisch: Gutes Heap-ASLR, möglicherweise schwieriger, die erste Codeausführung zu erreichen, aber auf Kosten einer weniger effektiven Sandbox-Richtlinie, aus der möglicherweise leichter auszubrechen ist.
  • Statisch: schlechtes Heap-ASLR, möglicherweise einfacher, die erste Codeausführung zu erreichen, aber eine effektivere Sandbox-Richtlinie, aus der möglicherweise schwieriger auszubrechen ist.

Bisher wurde in statisch verknüpften Binärdateien kein positionsunabhängiger Code (pie) unterstützt. Außerdem hat Bazel pie standardmäßig hinzugefügt. Um einen restriktiven Syscall-Filter zu definieren, mussten Sie den Standardwert von Bazel überschreiben.

Compiler haben sich im Laufe der Jahre verbessert und unterstützen jetzt die Option static-pie. Mit dieser Option wird ein Compiler angewiesen, positionsunabhängigen Code zu generieren. Im Vergleich zu pie sind jetzt aber auch alle statisch verknüpften Bibliotheken enthalten. Aus Sicherheitssicht verringert static-pie weiterhin die ASLR-Entropie (von 30 Bit auf 14 Bit), aber das ist eine Verbesserung gegenüber der vorherigen Situation ohne pie.

Da Bazel standardmäßig pie hinzufügt und „static“ damit nicht kompatibel ist, sollten Sie das Linker-Options-Flag verwenden, um das Linker-Flag -static-pie an die cc_binary-Regel zu übergeben und die Standardeinstellung zu überschreiben:

  linkstatic = 1,
  linkopts=["-static-pie"],

Ein Beispiel für diese Optionen finden Sie im statischen Beispiel BUILD: static_bin.cc wird statisch mit static-pie verknüpft, was eine sehr restriktive Syscall-Richtlinie ermöglicht. Das funktioniert auch gut für das Sandboxing von Drittanbieter-Binärdateien.

Kann ich 32-Bit-x86-Binärdateien in einer Sandbox ausführen?

Sandbox2 kann nur die Architektur in einer Sandbox ausführen, mit der es kompiliert wurde.

Außerdem wurde die Unterstützung für 32-Bit-x86 aus Sandbox2 entfernt. Wenn Sie versuchen, ein 32-Bit-x86-Binärprogramm mit einem 64-Bit-x86-Executor in einer Sandbox auszuführen, oder ein 64-Bit-x86-Binärprogramm, das 32-Bit-Systemaufrufe (über „int 0x80“) ausführt, wird in beiden Fällen ein Sandbox-Verstoß generiert, der durch das Architekturlabel [X86-32] identifiziert werden kann.

Der Grund für dieses Verhalten ist, dass sich die Syscall-Nummern zwischen den Architekturen unterscheiden. Da die Syscall-Richtlinie in der Architektur des Executors geschrieben ist, wäre es gefährlich, eine andere Architektur für die Sandboxee zuzulassen. Dies könnte dazu führen, dass ein scheinbar harmloser Syscall zugelassen wird, der in Wirklichkeit bedeutet, dass ein anderer, schädlicherer Syscall die Sandbox für einen Escape öffnen könnte.

Gibt es Einschränkungen hinsichtlich der Anzahl der Sandboxes, die ein Executor-Prozess anfordern kann?

Für jede Sandboxee-Instanz (neuer Prozess, der vom Forkserver abgeleitet wird) wird ein neuer Thread erstellt. Hier liegt die Einschränkung.

Kann ein Executor die Erstellung von mehr als einer Sandbox beantragen?

Nein. Es gibt eine 1:1-Beziehung. In einer Executor-Instanz wird die PID des Sandboxee gespeichert, die Comms-Instanz zur Sandbox-Instanz verwaltet usw.

Warum erhalte ich in forkserver.cc die Meldung „Function not implemented“ (Funktion nicht implementiert)?

Sandbox2 kann nur auf relativ neuen Kernels ausgeführt werden. Derzeit ist das der 3.19-Kernel. Das kann sich aber in Zukunft ändern. Das liegt daran, dass wir relativ neue Kernelfunktionen wie Nutzernamespaces und seccomp mit dem TSYNC-Flag verwenden.

Wenn Sie die Produktionsumgebung verwenden, sollte dies kein Problem sein, da auf fast allen Geräten ein aktueller Kernel ausgeführt wird. Wenn Sie Probleme damit haben, wenden Sie sich bitte an uns.

Wenn Sie Debian oder Ubuntu verwenden, können Sie den Kernel ganz einfach aktualisieren, indem Sie Folgendes ausführen:

sudo apt-get install linux-image-<RECENT_VERSION>