API shim de containerd

Chaque conteneur géré par containerd dispose d'un processus shim qui expose une API de contrôle sur une socket Unix en abstract namespace. Une faille a laissé cette socket accessible et non authentifiée depuis des conteneurs partageant le network namespace de l'hôte, de sorte qu'un processus pouvait appeler l'API du shim pour créer et démarrer de nouveaux processus sous le shim, s'exécutant en tant que root sur l'hôte.

2 min de lecturemis à jour le 12 oct. 2026florianamette1 contributeur
Demander à votre assistant (MCP)Modifier sur GitHub

containerd exécute un processus shim par conteneur (containerd-shim-runc-v2) qui gère le cycle de vie du conteneur et expose une API de contrôle ttrpc. Cette API était accessible via une socket de domaine Unix dans l'abstract namespace de Linux, lequel, contrairement à une socket de système de fichiers, est délimité par le network namespace plutôt que par un chemin. Un conteneur qui partageait le network namespace de l'hôte pouvait donc se connecter à la socket abstract du shim, et comme l'API n'effectuait aucune authentification de l'appelant, il pouvait invoquer des opérations du shim telles que Exec et Start pour créer un nouveau processus sous le shim. Les processus créés de cette manière s'exécutent avec les privilèges du shim en tant que root sur l'hôte, offrant une évasion de conteneur sans toucher au noyau ni à l'image.

Confirmez les préconditions :

bash
containerd --version 2>/dev/null            # affected 1.x line before the fix
ls -l /proc/self/ns/net; readlink /proc/1/ns/net   # shared host net namespace needed
cat /proc/net/unix | grep -a containerd-shim        # abstract shim sockets (names begin with @)

Un nom de socket abstract apparaît dans /proc/net/unix avec un @ en tête ; une entrée containerd-shim à cet endroit, combinée à un network namespace hôte partagé, indique l'accessibilité.

Technique#

bash
# 1. Identify the shim's abstract socket address from /proc/net/unix
#    (abstract names start with a NUL byte, shown as @ or a leading blank)
grep -a shim /proc/net/unix

# 2. Connect to that abstract address and speak the ttrpc shim protocol.
#    Using containerd's own client against the discovered address, call the
#    Task service to create and start a process under the shim, for example:
#    Exec(ExecProcessRequest{ ExecID, Spec{ args:["/bin/sh","-c","id > /tmp/o"] }})
#    Start(StartRequest{ ID, ExecID })

Comme le shim s'exécute en tant que root sur l'hôte et que le nouveau processus est un enfant du shim en dehors du confinement du conteneur d'origine, la commande s'exécute avec les privilèges root de l'hôte.

Notes d'exploitation#

  • Les deux conditions déterminantes sont un network namespace hôte partagé (afin que la socket abstract soit accessible) et l'API de shim non authentifiée ; supprimer l'une ou l'autre ferme la voie. Un conteneur disposant de son propre network namespace ne peut pas voir la socket abstract de l'hôte.
  • Le protocole est ttrpc, une variante compacte de gRPC ; l'exploitation pratique réutilise les bibliothèques client de containerd pointées vers l'adresse abstract découverte plutôt que de reconstruire le format de fil à la main.
  • Les correctifs ont ajouté l'authentification et restreint l'exposition de la socket du shim ; un containerd corrigé le met en échec. Identifiez la version avant de compter sur ceci.

Références#