Container schützen mit Seccomp-Filtern / Sudo Null IT News

Viele Unternehmen verwenden Container als grundlegende Technologie zum Verwalten und Ausführen ihrer Anwendungen. Wenn Sie bereits Erfahrung mit Containern haben, werden Sie ihre Motivation verstehen: Container bieten ein völlig neues Maß an Portabilität und Skalierbarkeit. Die Verwendung von Containern bedeutet jedoch, wie jede andere Technologie auch, neue Möglichkeiten, Anwendungs-Exploits zu nutzen.

Bei bestimmten Containerkonfigurationen kann ein Anwendungs-Exploit schließlich den Host gefährden, auf dem der Container ausgeführt wird. Es sind auch andere Aspekte zu berücksichtigen, z. B. Geheimnisse, die in Containern als Umgebungsvariablen gespeichert sind, und worauf Container Zugriff haben. Wenn Sie mehr über die Best Practices für Docker-Containersicherheit erfahren möchten, können Sie verwenden nützlicher Spickzettel.

Der etablierte Lebenszyklus der Softwareentwicklung umfasst bereits Sicherheitsprozesse wie das Scannen auf Schwachstellen und die Analyse der Softwarezusammensetzung, aber es sind noch mehr erforderlich. Die meisten vorhandenen Anwendungssicherheitstechnologien verhindern Anwendungsschwachstellen, aber nur wenige können den Schaden verhindern, der durch einen erfolgreichen Anwendungs-Exploit verursacht wird. Ich habe eine neue Methode kennengelernt, um Anwendungen in Containern nach Exploits zu schützen. In diesem Beitrag werde ich Ihnen sagen, was es ist und wie Sie es nahtlos in bestehende Softwareentwicklungsprozesse integrieren können. Als zusätzlichen Schutz habe ich Seccomp-BPF verwendet, also muss ich ein wenig darüber sprechen, bevor ich ins Detail gehe.

▍ Einführung

Programme, die auf Computern ausgeführt werden, nutzen aktiv die Funktionen des Betriebssystems. In modernen Programmiersprachen werden Aufgaben wie das Öffnen von Dateien und das Erstellen neuer Prozesse abstrahiert, aber innerhalb des Codes werden sie durch Anfragen an den aufgerufenen Kernel ausgeführt

Systemaufrufe

(Systemaufruf). Wie wichtig sind Systemaufrufe für den Betrieb eines Programms? Es gibt ungefähr vierhundert Syscalls im Linux-Kernel, und sogar ein einfaches »Hello, World!«-Programm, das in C geschrieben ist, verwendet zwei davon: schreiben und beenden.

Code, der im sogenannten “User Space” ausgeführt wird, kann nichts tun, ohne den Kernel dazu aufzufordern. Die klugen Entwickler des Linux-Kernels haben sich entschieden, dies auszunutzen und ein mächtiges Sicherheitsfeature zu schaffen. Im Juli 2012 wurde Linux 3.5 veröffentlicht, das Unterstützung für Seccomp-BPF hinzufügt.

Seccomp-BPF ist eine Funktion des Linux-Kernels, die es ermöglicht, durch Erstellen eines speziellen Filters die Liste der Systemaufrufe einzuschränken, die ein Prozess ausführen kann.

Theoretisch können Sie einen Seccomp-BPF-Filter erstellen, der es einem Prozess erlaubt, nur die Systemaufrufe auszuführen, die für seinen Betrieb erforderlich sind, und sonst nichts. Dies ist nützlich, falls die Anwendung so anfällig für Exploits ist, dass ein Angreifer zusätzliche Prozesse erstellen kann. Wenn Seccomp es einem Prozess nicht erlaubt, neue Syscalls auszuführen, besteht eine gute Chance, dass dies einen Angreifer ausbremst.

Seccomp ist eine sehr coole Sache, es ist sogar in die Containerlaufzeit und Verwaltungstools wie Docker und Kubernetes integriert. Es stellt sich die Frage: “Warum wird Seccomp nicht überall eingesetzt?” Ich denke, der Grund ist, dass es nicht genügend Ressourcen gibt, um die Lücke zwischen einer Low-Level-Kernelfunktion wie Seccomp und modernen Softwareentwicklungsprozessen zu schließen. Nicht jede Organisation hat einen Low-Level-Code-Entwickler mit umfassendem Wissen über Syscall. Darüber hinaus müssen Sie zusätzliche Ressourcen aufwenden, um herauszufinden, welche Systemaufrufe Ihr Programm benötigt, und sie mit jeder neuen im Code implementierten Funktion ergänzen.

Ich dachte darüber nach, wie ich dieses Problem lösen könnte, und kam zu folgendem Gedanken: „Was wäre, wenn wir die Systemaufrufe aufschreiben, die das Programm im Laufe seiner Arbeit ausführt?“ Ich stellte meine Idee einem meiner Kollegen vor, und am nächsten Tag schickte er mir einen Link zum Tool auf GitHub. Es stellte sich heraus, dass die Red-Hat-Entwickler bereits ein Tool namens erstellt hatten oci-seccomp-bpf-hookdas tut genau das!

▍ Erstellen eines Seccomp-BPF-Filters

Werkzeug

oci-seccomp-bpf-hook

wurde erstellt, um mit Linux-Containern zu arbeiten. OCI steht für „Open Container Initiative“ und ist eine Reihe von Standards für Containerlaufzeiten, die definieren, welche Arten von Schnittstellen sie bereitstellen können sollen. OCI-kompatible Laufzeiten (z. B. Docker) verfügen über einen Mechanismus namens „Hooks“, mit dem Sie Code ausführen können, bevor ein Container gestartet und nachdem er beendet wurde. Anstatt zu erklären, wie das Red Hat-Tool diese Hooks verwendet, ist es besser, es anhand eines Beispiels zu zeigen.

Red Hat hat oci-seccomp-bpf-hook zur Verwendung mit seiner Podman-Container-Laufzeitumgebung entwickelt. Podman ist in vielerlei Hinsicht abwärtskompatibel mit Docker. Wenn Sie also mit Docker gearbeitet haben, wird Ihnen die Syntax in meinen Beispielen bekannt vorkommen. Außerdem ist der OCI-Hook derzeit nur in den zugehörigen DNF-Repositories von Red Hat verfügbar oder kann von der Quelle installiert werden. Um die Demo einfach zu halten, verwende ich einfach einen Fedora-Server (wenn Sie keine Fedora-Umgebung haben, empfehle ich, eine virtuelle Fedora-Maschine auf etwas wie Virtualbox oder VMware auszuführen).

Der erste Schritt zur Verwendung von oci-seccomp-bpf-hook besteht darin, sicherzustellen, dass es mit podman installiert wird. Dazu können Sie den folgenden Befehl ausführen:

sudo dnf install podman oci-seccomp-bpf-hook

Jetzt, da wir Podman und den OCI-Hook haben, können wir endlich damit beginnen, den Seccomp-BPF-Filter zu generieren. BEI

Liesmich

Sie können feststellen, dass die Syntax wie folgt aussieht:

sudo podman run –annotation io.containers.trace-syscall=”if:[absolute path to the input file];von:[absolute path to the output file]” BILDBEFEHL

Lassen Sie uns den Befehl ausführen

ls

in einem einfachen Behälter und leiten den Ausgang zu

/dev/null

. Dabei zeichnen wir die vom Befehl getätigten Systemaufrufe auf

ls

und speichern Sie sie in einer Datei

/tmp/ls.json

.

sudo podman run –annotation io.containers.trace-syscall=of:/tmp/ls.json fedora:35 ls / > /dev/null

Da übergeben wir die Ausgabe des Befehls

ls

in

/dev/null

, sollte es keine Ausgabe im Terminal geben. Nach dem Ausführen des Befehls können wir jedoch einen Blick auf die Datei werfen, in der die Systemaufrufe gespeichert wurden. Darin sehen wir, dass der Befehl funktioniert hat und Systemaufrufe aufgezeichnet wurden:

cat /tmp/ls.json {“defaultAction”:”SCMP_ACT_ERRNO”,”architectures”:[“SCMP_ARCH_X86_64″],”Systemaufrufe”:[{“names”:[“access”,”arch_prctl”,”brk”,”capset”,”chdir”,”close”,”close_range”,”dup2″,”execve”,”exit_group”,”fchdir”,”fchown”,”fstatfs”,”getdents64″,”getegid”,”geteuid”,”getgid”,”getrandom”,”getuid”,”ioctl”,”lseek”,”mmap”,”mount”,”mprotect”,”munmap”,”newfstatat”,”openat”,”openat2″,”pivot_root”,”prctl”,”pread64″,”prlimit64″,”pselect6″,”read”,”rt_sigaction”,”rt_sigprocmask”,”seccomp”,”set_robust_list”,”set_tid_address”,”sethostname”,”setresgid”,”setresuid”,”setsid”,”statfs”,”statx”,”umask”,”umount2″,”write”],”action”:”SCMP_ACT_ALLOW”,”args”:[],”Kommentar”:””,”enthält”:{},”schließt”:{}}]}

Diese Datei ist unser Seccomp-Filter, jetzt können wir ihn mit jeder Laufzeit verwenden, die ihn unterstützt. Versuchen wir, einen Filter mit demselben containerisierten Befehl zu verwenden

ls

was wir gerade gemacht haben:

sudo podman run –security-opt seccomp=/tmp/ls.json fedora ls / > /dev/null

Es gibt keine Ausgabe oder Fehler, was bedeutet, dass der Befehl mit angewendetem Seccomp-Filter erfolgreich ausgeführt wurde. Und jetzt beginnt der Spaß. Wir werden dem Container Funktionen hinzufügen, die noch nicht vorhanden waren, als wir die Systemaufrufe zum Erstellen des Seccomp-Filters aufgezeichnet haben. Es wird ausreichen, um das Team zu erweitern

ls

Flagge

-l

.

sudo podman run –security-opt seccomp=/tmp/ls.json fedora ls -l / > /dev/null ls: /: Operation nicht erlaubt ls: /proc: Operation nicht erlaubt ls: /root: Operation nicht erlaubt …

Wie Sie sehen können, erhalten wir dieses Mal eine Reihe von Fehlern, die besagen, dass die Operation, die unser Befehl auszuführen versucht, nicht ausgeführt werden kann. Hinzufügen einer Flagge

-l

zum Team

ls

mehrere neue Systemaufrufe zum Prozess hinzugefügt, die nicht in der weißen Liste des Seccomp-Filters sind. Generieren wir mit dem Befehl einen neuen Seccomp-Filter

ls-l

werden wir sehen, dass der neue Filter funktioniert, da er jetzt über alle erforderlichen Systemaufrufe verfügt.

sudo podman run –annotation io.containers.trace-syscall=of:/tmp/lsl.json fedora ls -l / > /dev/null sudo podman run –security-opt seccomp=/tmp/lsl.json fedora ls -l / > /dev/null

Wie Sie sehen können, schränkt die Verwendung von Seccomp-Filtern mit Containern deren Fähigkeiten stark ein. In einer Situation, in der ein Angreifer Ihre Anwendung ausnutzen kann, kann dies ihn daran hindern, Schaden anzurichten oder sogar Exploits zu verwenden.

Dank des OCI-Hooks von Red Hat müssen Sie nicht mehr über umfassende Kenntnisse der Linux-Kernel-Systemaufrufe verfügen, um einen Seccomp-Filter zu erstellen. Sie können ganz einfach einen anwendungsspezifischen Filter erstellen, der verhindert, dass der Container über das hinausgeht, was er tun sollte. Dies ist ein wichtiger Schritt zur Überbrückung der Lücke zwischen Kernel-Fähigkeiten und Softwareentwicklung auf hohem Niveau.

▍ Abschließend

Egal wie schön

oci-seccomp-bpf-hook

, allein hat es meinen Traum, Seccomp in den etablierten Softwareentwicklungsprozess zu integrieren, nicht vollständig erfüllt. Dennoch werden zusätzliche Ressourcen benötigt, um dieses Tool auszuführen, und Entwickler werden keine Zeit damit verbringen, den Seccomp-Filter für jedes Anwendungsupdate manuell zu ändern. Um diese Lücke endlich zu schließen und die Verwendung von Seccomp in Unternehmensanwendungen so einfach wie möglich zu machen, müssen wir einen Weg finden, die Generierung von Seccomp-BPF-Filtern zu automatisieren. Glücklicherweise finden wir, wenn wir uns den modernen Softwareentwicklungsprozess ansehen, den perfekten Ort, um diese Automatisierung zu implementieren:

in timeContinuous Integration (CI)

.

CI-Prozesse sind bereits fester Bestandteil des etablierten Softwareentwicklungslebenszyklus geworden. Wenn Sie mit CI nicht vertraut sind, möchte ich sagen, dass Sie damit Funktionen wie automatisierte Komponententests und Code-Sicherheitsscans bei jedem Commit in ein Git-Repository verwenden können. Es gibt viele Tools für CI, daher ist dies ein idealer Schritt, um die Generierung eines Seccomp-Filters für eine containerisierte Anwendung zu automatisieren.

Ich werde in Kürze einen weiteren Beitrag schreiben, der zeigt, wie man einen CI-Prozess erstellt, der jedes Mal, wenn der Code aktualisiert wird, einen Seccomp-Filter generiert. Damit können Sie endlich die Syscall-Einschränkungen von Seccomp nutzen und Ihre Anwendungen sichern!

Telegrammkanal und gemütlich plaudern zur Diskussion

Similar Posts

Leave a Reply

Your email address will not be published.