Un conteneur n'a pas besoin du flag privileged complet pour être évadable. Une seule capacité, ajoutée avec --cap-add ou un securityContext.capabilities.add Kubernetes, peut suffire, car chaque capacité correspond à un chemin de code du noyau qui n'était jamais censé être accessible à une charge de travail semi-fiable. L'ensemble de capacités par défaut de Docker est déjà une liste réduite ; les évasions dangereuses viennent de capacités ajoutées par-dessus, ou d'une image de base lancée avec --cap-add=ALL.
Décodez exactement ce que vous détenez avant de choisir une page :
grep CapEff /proc/self/status # hex bitmask of effective capabilities
capsh --decode=00000000a80425fb # => the Docker default set
capsh --print # human-readable current/bounding set
getpcaps $$ # same, via libcap
Associez un bit de ce masque au nom de la capacité, puis allez à la page correspondante. Les ajouts à plus forte valeur, à peu près par ordre de directivité de l'évasion :
Sous-sujets#
- CAP_SYS_ADMIN : mount, pivot_root, et l'évasion via le release_agent de cgroup.
- CAP_SYS_MODULE : charger un module noyau qui exécute du code sur l'hôte.
- CAP_DAC_READ_SEARCH : lire n'importe quel fichier de l'hôte en force brute sur les handles d'inode.
- CAP_DAC_OVERRIDE : contourner les vérifications de permissions de fichiers pour écrire des fichiers de l'hôte.
- CAP_SYS_PTRACE : injecter du code dans les processus de l'hôte lorsque l'espace de noms PID est partagé.
- CAP_SYS_RAWIO : accès brut aux ports et à la mémoire physique pour patcher le noyau.
- CAP_BPF : charger des programmes BPF qui lisent et écrivent la mémoire du noyau.
- CAP_NET_RAW : sockets raw pour le sniffing et l'usurpation sur le réseau du conteneur.