
Sichere Codeausführung
CodeJail verwaltet die Ausführung von nicht vertrauenswürdigem Code in sicheren Sandboxen. Es ist in erster Linie für die Ausführung von Python entwickelt, kann aber auch für andere Sprachen verwendet werden.
Die Sicherheit wird mit AppArmor durchgesetzt. Wenn Ihr Betriebssystem AppArmor nicht unterstützt oder wenn das AppArmor-Profil nicht korrekt definiert und konfiguriert ist, schützt CodeJail die Ausführung nicht.
CodeJail ist so konzipiert, dass es konfigurierbar ist und sich bei korrekter Installation automatisch für die Python-Ausführung konfiguriert.
Eine CodeJail-Sandbox besteht aus mehreren Teilen:
#) Sandbox-Umgebung. Für ein Python-Setup wären dies Python und zugehörige Kernpakete als virtualenv. Diese wird in diesem Dokument durchgängig als bezeichnet. Sie ist schreibgeschützt und wird von allen Sandbox-Instanzen gemeinsam genutzt.
Sandbox-Code hat außerdem Zugriff auf Betriebssystembibliotheken, soweit es das AppArmor-Profil erlaubt.
#) Sandbox-Ausführungsverzeichnis. Dies ist ein flüchtiges, schreibgeschütztes Verzeichnis mit einem Namen wie /tmp/codejail-XXXXXXXX, das den eingereichten Code
(./jailed_code), optionale zusätzliche Dateien und ein beschreibbares temporäres
Verzeichnis (./tmp) enthält, das der eingereichte Code als Arbeitsbereich nutzen kann.
Der eingereichte Code ist typischerweise der Code, der vom Studenten eingereicht wurde, um auf dem Server getestet zu werden, und die zusätzlichen Dateien sind typischerweise eine
python_lib.zip mit Bewertungs- oder Hilfsbibliotheken.
Zum Ausführen benötigt CodeJail zwei Benutzerkonten. Ein Konto ist das Hauptkonto, unter dem der Code läuft und das Zugriff hat, Sandboxen zu erstellen. Dies wird als <SANDBOX_CALLER> bezeichnet. Das zweite Konto ist das Konto, unter dem die Sandbox läuft. Dies ist typischerweise das Konto sandbox.
Diese Bibliothek ist derzeit so getestet, dass sie mit den folgenden Versionen funktioniert
Python:
Ubuntu:
(Beachten Sie, dass die Python-Version, die innerhalb der Sandbox verwendet wird, von der Version abweichen kann, die für die Bibliothek selbst verwendet wird.)
Diese Anweisungen beschreiben, wie Sie Ihr Betriebssystem konfigurieren, damit CodeJail Python-Code sicher ausführen kann. Es ist jedoch auch möglich, codejail.safe_exec.ALWAYS_BE_UNSAFE = True zu setzen und eingereichten Python-Code direkt auf dem Rechner ohne jegliche Sicherheit auszuführen. Das mag für Entwicklerrechner in Ordnung sein, denen Sicherheit nicht wichtig ist, und ermöglicht das Testen einer Integration mit der CodeJail-API. Es darf jedoch nicht verwendet werden, wenn Eingaben aus nicht vertrauenswürdigen Quellen stammen. Verwenden Sie diese Option nicht in Produktionssystemen.
Um die Python-Ausführung abzusichern, erstellen Sie ein neues virtualenv. Das bedeutet, Sie haben zwei: das Haupt-virtualenv für Ihr Projekt und das neue für Sandbox-Python-Code.
Wählen Sie einen Ort für das neue virtualenv und nennen Sie ihn . Es wird automatisch erkannt und verwendet, wenn Sie es direkt neben Ihrem vorhandenen virtualenv platzieren, jedoch mit angehängtem -sandbox. Wenn sich Ihr bestehendes virtualenv also in /home/chris/ve/myproj befindet, machen Sie zu /home/chris/ve/myproj-sandbox.
Der Benutzer, der das LMS ausführt, ist <SANDBOX_CALLER>, zum Beispiel Sie auf Ihrem Entwicklungsrechner oder www-data auf einem Server.
Weitere Details hier, die von Ihrer Konfiguration abhängen:
Erstellen Sie das neue virtualenv mit --copies, damit eine eigene Python-ausführbare Datei zur Beschränkung vorhanden ist::
$ sudo python3.12 -m venv --copies
Standardmäßig würde das virtualenv nur auf das System-Python verlinken, und die Standardkonfiguration von AppArmor auf einigen Betriebssystemen kann verhindern, dass die Beschränkung darauf angewendet wird.
(Optional) Wenn Sie bestimmte Pakete für Ihren Sandbox-Code verfügbar machen möchten, installieren Sie diese, indem Sie die Sandbox-virtualenv aktivieren und pip zur Installation verwenden::
$ /bin/pip install -r requirements/sandbox.txt
Fügen Sie einen Sandbox-Benutzer hinzu::
$ sudo addgroup sandbox $ sudo adduser --disabled-login sandbox --ingroup sandbox
Lassen Sie den Webserver das Sandbox-Python als sandbox ausführen. Erstellen Sie die Datei /etc/sudoers.d/01-sandbox::
$ sudo visudo -f /etc/sudoers.d/01-sandbox
<SANDBOX_CALLER> ALL=(sandbox) SETENV:NOPASSWD:/bin/python <SANDBOX_CALLER> ALL=(sandbox) SETENV:NOPASSWD:/usr/bin/find <SANDBOX_CALLER> ALL=(ALL) NOPASSWD:/usr/bin/pkill
(Beachten Sie, dass die find-Binärdatei beliebigen Code ausführen kann, dies also keine sichere sudoers-Datei für andere Zwecke als CodeJail ist.)
Bearbeiten Sie ein AppArmor-Profil. Dies ist eine Textdatei, die die Beschränkungen für die Sandbox-Python-ausführbare Datei festlegt. Die Datei muss sich in /etc/apparmor.d befinden und sollte basierend auf der ausführbaren Datei benannt werden, wobei Schrägstriche durch Punkte ersetzt werden. Wenn sich Ihr Sandbox-Python beispielsweise unter /home/chris/ve/myproj-sandbox/bin/python befindet, muss Ihr AppArmor-Profil /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python lauten.
Wenn Ihr CodeJail ordnungsgemäß für die Verwendung von safe_exec konfiguriert ist, versuchen Sie diese Befehle in Ihrem Python-Terminal::
import codejail.jail_code
codejail.jail_code.configure('python', '<SANDENV>/bin/python', user='sandbox')
import codejail.safe_exec
jailed_globals = {}
codejail.safe_exec.safe_exec("output=open('/etc/passwd').read()", jailed_globals)
print(jailed_globals) # should be unreachable if codejail is working properly
Dies sollte mit einer Ausnahme fehlschlagen.
Wenn Sie die in der virtualenv Ihrer Sandbox installierten Pakete ändern müssen, müssen Sie AppArmor deaktivieren, da Ihr Sandbox-Python nicht das Recht hat, die Dateien in seinem site-packages-Verzeichnis zu ändern.
Deaktivieren Sie AppArmor für Ihre Sandbox::
$ sudo apt-get install apparmor-utils # if you haven't already $ sudo aa-complain /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python
Installieren Sie die Pakete oder ändern Sie sie anderweitig::
$ pip install -r requirements/sandbox.txt
Aktivieren Sie AppArmor für Ihre Sandbox erneut::
$ sudo aa-enforce /etc/apparmor.d/home.chris.ve.myproj-sandbox.bin.python
Um die Tests auszuführen, müssen Sie die Standard-Installationsschritte durchführen. Dann müssen Sie die folgenden Umgebungsvariablen setzen::
$ export CODEJAIL_TEST_USER=<owner of sandbox (usually 'sandbox')>
$ export CODEJAIL_TEST_VENV=<SANDENV>
Führen Sie die Tests mit dem Makefile aus::
$ make tests
Mehrere Proxy-Tests werden übersprungen, wenn der Proxy-Modus nicht konfiguriert ist.
CodeJail ist allgemein genug, um in verschiedenen Projekten zur Ausführung von nicht vertrauenswürdigem Code verwendet zu werden. Es bietet zwei Ebenen:
jail_code.py bietet eine sichere Ausführung von Subprozessen. Dies geschieht, indem das Programm in einem von AppArmor verwalteten Subprozess ausgeführt wird.
safe_exec.py bietet eine spezialisierte Handhabung der Python-Ausführung und verwendet jail_code, um die Semantik der exec-Anweisung von Python bereitzustellen.
CodeJail führt Programme unter AppArmor aus. AppArmor ist eine vom Betriebssystem bereitgestellte Funktion, um die Ressourcen zu beschränken, auf die Programme zugreifen können. Um Python-Code mit eingeschränktem Zugriff auf Ressourcen auszuführen, erstellen wir ein neues virtualenv, benennen diese Python-ausführbare Datei dann in einem AppArmor-Profil und beschränken Ressourcen in diesem Profil. CodeJail führt das bereitgestellte Python-Programm mit dieser ausführbaren Datei aus, und AppArmor beschränkt automatisch die Ressourcen, auf die es zugreifen kann. CodeJail verwendet außerdem setrlimit, um die Menge an CPU-Zeit und/oder Speicher zu begrenzen, die dem Prozess zur Verfügung steht.
codejail.jail_code nimmt ein auszuführendes Programm, in seine Umgebung zu kopierende Dateien, Befehlszeilenargumente und einen stdin-Stream entgegen. Es erstellt ein temporäres Verzeichnis, erstellt oder kopiert die benötigten Dateien, startet einen Subprozess zur Ausführung des Codes und gibt die Ausgabe und den Exit-Status des Prozesses zurück.
codejail.safe_exec emuliert die exec-Anweisung von Python. Es nimmt einen Teil Python-Code und führt ihn mit jail_code aus, wobei das globals-Wörterbuch als Nebeneffekt verändert wird. safe_exec tut dies, indem es die globals als JSON in den Subprozess und wieder hinaus serialisiert.
Wenn Codejail oder AppArmor nicht ordnungsgemäß konfiguriert ist, kann Codejail standardmäßig Code unsicher (ohne Sandboxing) ausführen. Es ist nicht standardmäßig sicher. Projekte, die Codejail integrieren, sollten in Erwägung ziehen, eine Laufzeit-Testsuite einzuschließen, die beim Start vor der Annahme nicht vertrauenswürdiger Eingaben die ordnungsgemäße Beschränkung überprüft.
Die Sandbox-Isolation wird über die AppArmor-Beschränkung erreicht. Codejail ermöglicht dies, kann die Ausführung jedoch ohne den Einsatz von AppArmor nicht isolieren.
Ressourcengrenzen können nur mit den Mechanismen eingeschränkt werden, die Linux' rlimit bereitstellt. Einige bemerkenswerte Mängel:
FSIZE die Größe jeder einzelnen Datei begrenzen kann, die ein Prozess erstellen kann, und die Anzahl der Dateien begrenzen kann, die er gleichzeitig geöffnet hat, kann es nicht die Gesamtzahl der geschriebenen Dateien begrenzen und daher auch nicht die Gesamtzahl der Bytes, die über alle Dateien hinweg geschrieben werden. Eine teilweise Abhilfe besteht darin, die maximale Ausführungszeit zu begrenzen. (Alle in der Sandbox geschriebenen Dateien werden am Ende der Ausführung in jedem Fall gelöscht.)NPROC-Limit begrenzt die Fähigkeit des aktuellen Prozesses, neue Threads und Prozesse zu erstellen, aber die Nutzungsanzahl (wie viele Prozesse bereits existieren) ist die Summe über alle Prozesse mit derselben UID, sogar in anderen Containern auf demselben Host, in denen die UID möglicherweise auf einen anderen Benutzernamen abgebildet ist. Diese Einschränkung gilt auch für den App-Benutzer, bedingt durch die Art, wie die rlimits angewendet werden. Selbst wenn UIDs so gewählt werden, dass sie nicht von anderer Software auf dem Host verwendet werden, teilen sich mehrere Codejail-Sandbox-Prozesse auf demselben Host diesen Nutzungspool und können die Fähigkeit des jeweils anderen zur Prozesserstellung verringern. In dieser Situation muss NPROC höher gesetzt werden, als es für eine einzelne Codejail-Instanz, die jeweils eine Anfrage verarbeitet, der Fall wäre.Sandboxen haben keine starke Isolation voneinander. Bei ordnungsgemäßer Konfiguration sollte nicht vertrauenswürdiger Code keine anderen aktiv laufenden Codeausführungen entdecken können. Wenn diese Annahme jedoch verletzt wird, könnte eine Sandbox theoretisch in eine andere eingreifen.
Bitte melden Sie Sicherheitsprobleme nicht öffentlich. Bitte senden Sie eine E-Mail an [email protected].
Ein Beispielprofil finden Sie in apparmor-profiles/. Das Profil muss angepasst werden, um Ihrem Sandbox-Speicherort zu entsprechen.
Parsen Sie die Profile::
$ sudo apparmor_parser --replace --warn=all --warn=no-debug-cache --Werror <APPARMOR_FILE>
Reaktivieren Sie das Haupt-virtualenv Ihres Projekts erneut.
Deaktivieren Sie die Verwendung von PAM zum Setzen von rlimits::
sed -i '/pam_limits.so/d' /etc/pam.d/sudo