- Speichersicherheit und Sandboxing sind voneinander unabhängige Sicherheitskonzepte; erst beides zusammen bildet eine starke Verteidigungsarchitektur.
- Fil-C ist eine speichersichere Implementierung für C/C++, die Sicherheit bis auf Ebene der Linux-Systemaufrufe gewährleistet und sich auch in Systemkomponenten wie OpenSSH einsetzen lässt.
- Bei der Portierung der seccomp-BPF-basierten Sandbox von OpenSSH auf Fil-C waren die Begrenzung der Thread-Erzeugung und die Anpassung des seccomp-Filters die zentralen Aufgaben.
- Für die Verwaltung von Hintergrund-Threads in der Fil-C-Runtime wurde die API
zlock_runtime_threads() hinzugefügt, um das Thread-Verhalten innerhalb der Sandbox zu steuern.
- Fil-C implementiert
prctl so, dass der Aufruf synchron auf alle Runtime-Threads angewendet wird, damit no_new_privs und der seccomp-Filter konsistent auf den gesamten Prozess angewendet werden.
Das Verhältnis von Speichersicherheit und Sandboxing
- Speichersicherheit und Sandboxing sind unterschiedliche Sicherheitsebenen; nur eine von beiden reicht nicht für vollständigen Schutz aus.
- Beispiel für speichersicher, aber nicht sandboxed: ein Java-Programm, das über Benutzereingaben Dateien überschreiben kann.
- Beispiel für sandboxed, aber nicht speichersicher: ein in Assembler geschriebenes Programm mit eingeschränkten Rechten.
- Reale Sandboxes haben strukturelle Schwachstellen, etwa die erlaubte Kommunikation mit einem Broker-Prozess.
- Deshalb ist die Kombination aus Speichersicherheit und Sandboxing die beste Verteidigungsstrategie.
Die Kombination von Fil-C und der OpenSSH-Sandbox
- Fil-C ist eine speichersichere Implementierung für C/C++, die Sicherheit auf Ebene der Linux-Systemaufrufe aufrechterhält.
- Die Fil-C-Runtime kann auch in niedrigschwelligen Systemkomponenten wie
init und udevd laufen.
- OpenSSH funktioniert unter Fil-C normal und nutzt die seccomp-BPF-Sandbox.
- OpenSSH baut seine Sandbox unter Linux mit den folgenden Werkzeugen auf.
chroot zur Einschränkung des Dateisystemzugriffs
- Ausführung als Benutzer/Gruppe
sshd
setrlimit zur Begrenzung des Öffnens von Dateien und der Prozesserzeugung
- seccomp-BPF-Filter, die nur erlaubte Systemaufrufe zulassen
- Fil-C unterstützt
chroot und den Benutzerwechsel grundsätzlich, doch setrlimit und seccomp-BPF können mit dem Verhalten der Runtime kollidieren und erfordern daher zusätzliche Anpassungen.
Thread-Steuerung in der Fil-C-Runtime
- Die Fil-C-Runtime verwendet Hintergrund-Threads für die Garbage Collection und hält sie bei Bedarf automatisch an oder startet sie neu.
- Die
setrlimit-Sandbox von OpenSSH soll die Erzeugung neuer Prozesse verbieten, daher kann die Thread-Erzeugung der Runtime damit in Konflikt geraten.
- Zur Lösung dieses Problems wurde in
<stdfil.h> die API zlock_runtime_threads() ergänzt.
- Die Runtime erstellt sofort alle benötigten Threads und deaktiviert danach deren automatisches Beenden.
- Der Aufruf erfolgt in der Funktion
ssh_sandbox_child von OpenSSH vor setrlimit oder seccomp-BPF.
Anpassung des OpenSSH-seccomp-Filters
- Nach Anwendung von
zlock_runtime_threads() funktionieren die meisten Sandbox-Funktionen unverändert weiter.
- Am seccomp-Filter wurden die folgenden Änderungen vorgenommen.
- Bei Verstößen wird
SECCOMP_RET_KILL_PROCESS gesetzt, damit auch die Fil-C-Hintergrund-Threads beendet werden.
MAP_NORESERVE wurde zur Allowlist hinzugefügt, um den Speicher-Allocator von Fil-C zu unterstützen.
- Aufrufe von
sched_yield werden erlaubt, da sie in der Lock-Implementierung von Fil-C verwendet werden.
- Die von Fil-C für die Synchronisierung verwendeten
futex-Aufrufe waren bereits erlaubt, sodass keine weiteren Änderungen nötig waren.
Die Implementierung von prctl in Fil-C
- OpenSSH verwendet beim Installieren des seccomp-Filters zwei
prctl-Aufrufe.
PR_SET_NO_NEW_PRIVS, um den Erwerb zusätzlicher Privilegien zu verhindern
PR_SET_SECCOMP, SECCOMP_MODE_FILTER, um den Filter zu aktivieren
- Das Problem ist, dass
prctl nur auf den aufrufenden Thread wirkt, wodurch andere Runtime-Threads von Fil-C ohne Filter verbleiben könnten.
- Um das zu verhindern, nutzt Fil-C die API
filc_runtime_threads_handshake(), um die Anwendung auf alle Runtime-Threads zu synchronisieren.
- Dadurch wird sichergestellt, dass jeder Thread denselben
prctl-Aufruf ausführt.
- Wenn mehrere Benutzer-Threads existieren, löst Fil-C einen Sicherheitsfehler aus und verstärkt so den Schutz.
Fazit
- Die Kombination aus Speichersicherheit und Sandboxing ist die stärkste Sicherheitskombination.
- Fil-C integriert die seccomp-basierte Sandbox von OpenSSH vollständig und bewahrt dabei Speichersicherheit ohne Absenkung des Schutzniveaus.
- Mit Fil-C in einer Linux-Umgebung lassen sich Sicherheit auf Systemebene und Sicherheit auf Sprachebene gleichzeitig erreichen.
Noch keine Kommentare.