Docker Breakout / Privilege Escalation
Last updated
Last updated
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
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.
Dans ce cas, vous pouvez utiliser des commandes docker classiques pour communiquer avec le démon docker :
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 :
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
...
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 :
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 :
Linux CapabilitiesUn 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 :
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 :
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:
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
.
À 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 :
Trouvez une explication de la technique dans :
Docker release_agent cgroups escapeDans 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 :
release_agent exploit - Relative Paths to PIDsL'exécution du PoC dans un conteneur privilégié devrait fournir une sortie similaire à :
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 :
release_agent (déjà abordé précédemment)
Cependant, vous pouvez trouver d'autres fichiers sensibles à vérifier sur cette page :
Sensitive MountsÀ 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...
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.
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.
Exemple d'exploitation de ce writeup:
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:
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 :
Vous pouvez également accéder aux descripteurs de fichiers d'autres processus et lire leurs fichiers ouverts :
Vous pouvez également arrêter des processus et provoquer un déni de service.
Si vous avez d'une manière ou d'une autre un accès privilégié sur un processus en dehors du conteneur, vous pourriez exécuter quelque chose comme nsenter --target <pid> --all
ou nsenter --target <pid> --mount --net --pid --cgroup
pour exécuter un shell avec les mêmes restrictions ns (espérons-le aucune) que ce processus.
Si un conteneur est configuré avec le pilote de réseau Docker host (--network=host
), la pile réseau de ce conteneur n'est pas isolée de l'hôte Docker (le conteneur partage l'espace réseau de l'hôte) et le conteneur ne reçoit pas d'adresse IP propre. En d'autres termes, le conteneur lie tous les services directement à l'IP de l'hôte. De plus, le conteneur peut intercepter TOUT le trafic réseau que l'hôte envoie et reçoit sur l'interface partagée tcpdump -i eth0
.
Par exemple, vous pouvez utiliser cela pour sniffer et même falsifier le trafic entre l'hôte et l'instance de métadonnées.
Comme dans les exemples suivants :
Vous pourrez également accéder aux services réseau liés à localhost à l'intérieur de l'hôte ou même accéder aux autorisations de métadonnées du nœud (qui peuvent être différentes de celles auxquelles un conteneur peut accéder).
Avec hostIPC=true
, vous avez accès aux ressources de communication inter-processus (IPC) de l'hôte, telles que la mémoire partagée dans /dev/shm
. Cela permet de lire/écrire là où les mêmes ressources IPC sont utilisées par d'autres processus de l'hôte ou du pod. Utilisez ipcs
pour inspecter ces mécanismes IPC plus en détail.
Inspecter /dev/shm - Recherchez des fichiers dans cet emplacement de mémoire partagée : ls -la /dev/shm
Inspecter les installations IPC existantes - Vous pouvez vérifier si des installations IPC sont utilisées avec /usr/bin/ipcs
. Vérifiez-le avec : ipcs -a
Si l'appel système unshare
n'est pas interdit, vous pouvez récupérer toutes les capacités en exécutant :
La deuxième technique expliquée dans l'article https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/ indique comment vous pouvez abuser des montages de liaison avec les espaces utilisateurs, pour affecter les fichiers à l'intérieur de l'hôte (dans ce cas spécifique, supprimer des fichiers).
Utilisez Trickest pour construire facilement et automatiser des flux de travail alimentés par les outils communautaires les plus avancés au monde. Accédez dès aujourd'hui :
Dans le cas où vous pouvez exécuter docker exec
en tant que root (probablement avec sudo), vous pouvez essayer d'escalader les privilèges en vous échappant d'un conteneur en abusant de la CVE-2019-5736 (exploit ici). Cette technique va essentiellement écraser le binaire /bin/sh de l'hôte à partir d'un conteneur, de sorte que toute personne exécutant docker exec peut déclencher la charge utile.
Modifiez la charge utile en conséquence et compilez le main.go avec go build main.go
. Le binaire résultant doit être placé dans le conteneur Docker pour l'exécution.
Lors de l'exécution, dès qu'il affiche [+] Overwritten /bin/sh successfully
, vous devez exécuter ce qui suit depuis la machine hôte :
docker exec -it <nom-du-conteneur> /bin/sh
Cela déclenchera la charge utile qui est présente dans le fichier main.go.
Pour plus d'informations : https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html
Il existe d'autres CVE auxquelles le conteneur peut être vulnérable, vous pouvez trouver une liste dans https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list
Espaces de noms : Le processus doit être complètement séparé des autres processus via des espaces de noms, donc nous ne pouvons pas échapper à l'interaction avec d'autres processus en raison des espaces de noms (par défaut, ne peut pas communiquer via IPC, sockets Unix, services réseau, D-Bus, /proc
d'autres processus).
Utilisateur root : Par défaut, l'utilisateur exécutant le processus est l'utilisateur root (mais ses privilèges sont limités).
Capacités : Docker laisse les capacités suivantes : 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
Appels système : Ce sont les appels système que l'utilisateur root ne pourra pas appeler (en raison du manque de capacités + Seccomp). Les autres appels système pourraient être utilisés pour tenter de s'échapper.
If you are in userspace (no kernel exploit involved) the way to find new escapes mainly involve the following actions (these templates usually require a container in privileged mode):
Find the path of the containers filesystem inside the host
You can do this via mount, or via brute-force PIDs as explained in the second release_agent exploit
Find some functionality where you can indicate the path of a script to be executed by a host process (helper) if something happens
You should be able to execute the trigger from inside the host
You need to know where the containers files are located inside the host to indicate a script you write inside the host
Have enough capabilities and disabled protections to be able to abuse that functionality
You might need to mount things o perform special privileged actions you cannot do in a default docker container
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools. Get Access Today: