Un guide sur les vulnérabilités d'escalade de privilèges dans les conteneurs
L'une des nombreuses promesses des conteneurs est l'isolation.
Grâce à une utilisation judicieuse des namespaces et des cgroups Linux, les conteneurs créent un sandbox où les processus peuvent s'exécuter indépendamment les uns des autres. Ceci, combiné à une expérience développeur agréable, a permis aux conteneurs de gagner en popularité auprès des ingénieurs et des professionnels de la sécurité.
Mais est-ce vraiment suffisant ?
Et pouvez-vous affirmer avec certitude que vos workloads sont sécurisés si l'un d'entre eux venait à être compromis ?
Eh bien, dans cet article, nous aborderons le rêve de tout attaquant et le cauchemar des administrateurs système, en vous expliquant comment et pourquoi cela se produit, et les moyens de l'éviter avant de vous retrouver en première page de Hacker News. Pour en savoir plus sur les vulnérabilités de sécurité des conteneurs Docker, consultez : Top 9 Docker Container Security Vulnerabilities.
L'isolation des conteneurs et ses failles de sécurité
Un détail clé souvent négligé avec les conteneurs est qu'ils partagent tous le même hôte. Cela signifie que chaque conteneur n'est sécurisé qu'autant que le suivant. Si l'hôte ou un seul conteneur est compromis, cela pourrait entraîner un désastre pour votre infrastructure.
Cela ne signifie pas que vous devriez abandonner complètement les conteneurs. Non. Le but ici est de comprendre les détails.
L'isolation commence à se dégrader lorsque les attaquants trouvent un moyen d'escalader les privilèges. L'escalade de privilèges est l'une des manœuvres les plus excitantes mais aussi les plus difficiles dans les attaques de sécurité offensive. Elle transforme un point d'appui à faibles privilèges en une compromission complète du système.
Les vulnérabilités d'escalade de privilèges dans les conteneurs rendent le contournement des frontières de sécurité moins difficile et bien plus gratifiant, car un seul conteneur suffit pour obtenir l'accès à un hôte.
Ce n'est pas seulement de la théorie ; la tristement célèbre vulnérabilité runC de 2019 (CVE-2019-5736) a permis aux attaquants d'écraser le binaire runC de l'hôte et de s'emparer de l'accès root de l'hôte.
Ces attaques sont loin d'être éphémères, c'est pourquoi vous pourriez rencontrer des questions comme celle-ci :

Plus récemment, des vulnérabilités comme CVE-2024-21626 et des attaques subtiles basées sur les couches nous ont montré que même les conteneurs non-root peuvent devenir dangereux en cas de mauvaise utilisation des capacités Linux, des montages ou de la superposition de systèmes de fichiers.
C'est pourquoi, en nous appuyant sur notre précédent guide sur les vulnérabilités Docker, nous explorerons le fonctionnement de ces attaques, les CVE récentes qui soulignent leurs risques croissants, et comment les prévenir.
Vulnérabilités récentes d'escalade de privilèges dans les conteneurs
Bien que toutes les vulnérabilités des conteneurs ne mènent pas à une escalade de privilèges, les plus dangereuses le font souvent. Certaines vulnérabilités contournent l'isolation des conteneurs et s'emparent de privilèges élevés comme aucune autre.
Voici trois vulnérabilités récentes d'escalade de privilèges dans les conteneurs.
CVE-2024-21626 : Évasion du répertoire de travail de runC
CVE-2024-21626 est une vulnérabilité d'évasion de conteneur de haute gravité qui affecte le runtime de conteneur largement utilisé, runC. La vulnérabilité provient d'une utilisation non sécurisée de l'appel prctl PR_SET_NO_NEW_PRIVS avec execve, permettant à un attaquant de contourner le drapeau no_new_privs lorsque le conteneur a été démarré avec des montages ou des capacités trop permissifs.
Le flag no_new_privs est l'une des principales mesures d'atténuation contre l'escalade de privilèges sur laquelle de nombreux moteurs de conteneurs s'appuient pour le sandboxing.
La faille a été introduite dans les versions de runC à partir de la v1.1.11 et a été corrigée dans la v1.1.12.
CVE-2023-2640 et CVE-2023-32629 dans le module OverlayFS du noyau Ubuntu
OverlayFS est l'un des blocs de construction fondamentaux des conteneurs et de Kubernetes. Il superpose deux répertoires (lowerdir et upperdir) sur un seul hôte Linux et les présente comme un répertoire unique, offrant de meilleures performances pour les commandes Docker liées aux couches, telles que docker build et docker commit.
CVE-2023-2640 et CVE-2023-32629 permettent à un acteur malveillant d'utiliser un conteneur privilégié non-root avec un montage de volume pour escalader les privilèges. Ceci est possible car les montages de volume sont traités comme des disques séparés et peuvent être utilisés pour créer un OverlayFS, qui existe en dehors de la couche du conteneur. Cela permet aux attaquants de contourner les restrictions standard des conteneurs et de manipuler les attributs de fichiers étendus sur les volumes montés, qui sont ensuite copiés vers la couche supérieure avec des capacités élevées (telles que CAP_SETUID ou CAP_SYS_ADMIN) intactes.
CVE-2022-0492
Le 4 mars 2022, des chercheurs en sécurité ont découvert une faille critique dans le cgroup_release_agent_write du noyau Linux qui avait le potentiel de permettre l'évasion de conteneur et de prendre le contrôle de l'intégralité du nœud sur lequel le conteneur s'exécute.
Les fournisseurs de cloud et les distributions Linux ont agi rapidement. Des correctifs ont été publiés, des avis de sécurité ont été diffusés. Mais sous la surface, la complexité demeurait. Contrairement à d'autres logiciels, le noyau Linux ne dispose pas d'un schéma de versioning standardisé entre les distributions.
Ce qui signifie que l'application de ces correctifs et la mise à niveau des images de base ont pris des mois. Pendant ce temps, les environnements sont restés vulnérables à des attaques potentielles.
Prévenir les escalades de privilèges dans Docker et Docker Compose
La meilleure façon de prévenir les attaques par escalade de privilèges depuis un conteneur Docker est de configurer les applications de votre conteneur pour qu'elles s'exécutent en tant qu'utilisateurs non privilégiés et de s'assurer ensuite que les conteneurs n'ont pas d'accès privilégié.
En pratique, pour prévenir l'escalade de privilèges dans Docker, vous devez effectuer les opérations suivantes :
- Verrouiller l'escalade de privilèges
- Définir un utilisateur non-root approprié
- Supprimer les capacités du noyau Linux
Vous avez deux options : soit à l'exécution, soit dans votre configuration Docker Compose.
À l'exécution, utilisez les drapeaux suivants :
docker run \
--read-only \
--security-opt=no-new-privileges \
--network your-isolated-network \
--cap-drop ALL
--cap-add CHOWN \
--pids-limit 99 \
--user=your-user \ # votre utilisateur non-root.
... # D'AUTRES OPTIONS ICI
your-app:v1.0.1Avec Docker Compose, la configuration sera la suivante :
services:
webapp:
image: your-app:v1.0.1
read_only: true
security_opt:
- no-new-privileges:true
networks:
- your-isolated-network
cap_drop:
- ALL
cap_add:
- CHOWN
# D'AUTRES OPTIONS ICI
...Exécuter des conteneurs qui nécessitent un accès utilisateur root
Il existe des cas (exécution d'utilitaires système, de services hérités, etc.) où un conteneur pourrait nécessiter un accès root pour s'exécuter. Dans ces cas, vous pouvez remapper cet utilisateur à un utilisateur moins privilégié sur l'hôte Docker.
Le remappage d'un UID de conteneur garantit que, même si le conteneur pense s'exécuter en tant que root, il fonctionne en réalité comme un utilisateur non privilégié du point de vue de l'hôte, ce qui réduit le risque d'évasion de conteneur et de compromission de l'hôte.
Vous pouvez vous référer à la documentation Docker sur le remappage des espaces de noms utilisateur pour des étapes détaillées et les meilleures pratiques.
Prévenir l'escalade de privilèges dans Kubernetes
Dans Kubernetes, la meilleure façon de prévenir l'escalade de privilèges est lors de la création du conteneur, en utilisant la configuration spec.containers.securityContext. En effet, une fois qu'un conteneur est créé avec des privilèges trop permissifs, il ne peut pas être mis à jour à l'exécution, et vous devrez le supprimer et le recréer.
Le securityContext suivant sécurise le conteneur d'application contre l'escalade de privilèges, même avec les versions Linux du CVE-2022-0492 non patché, comme mentionné ci-dessus.
containers:
- name: app
image: myapp:bullseye-20230912
securityContext:
runAsUser: 1000 # Utiliser un ID utilisateur non-root
runAsGroup: 1000 # Utiliser un ID de groupe non-root
runAsNonRoot: true # Appliquer explicitement l'exécution non-root
allowPrivilegeEscalation: false # Empêcher le processus d'acquérir plus de privilèges
readOnlyRootFilesystem: true # Empêcher les écritures sur le système de fichiers root
capabilities:
drop:
- ALL # Supprimer toutes les capacités pour minimiser la surface d'attaque
add:
- NET_BIND_SERVICE # Ajouter uniquement les capacités dont l'application a besoin
seccompProfile:
type: RuntimeDefault # Utiliser le profil seccomp par défaut du runtime du conteneurUne autre excellente façon de prévenir l'escalade de privilèges dans Kubernetes est d'empêcher le déploiement de Pods sans contexte de sécurité. Les contrôleurs d'admission Kubernetes vous permettent d'intercepter les requêtes vers le serveur API, par exemple un déploiement, et de valider que certaines conditions sont remplies avant leur traitement.
Pour des cas d'utilisation plus avancés, vous pouvez écrire un contrôleur d'admission à partir de zéro ; cependant, des solutions open source comme Kyverno vous permettent d'écrire des politiques à l'échelle du cluster qui peuvent patcher les déploiements qui n'ont pas de contexte de sécurité défini. Cela ressemble généralement à ceci :
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-default-securitycontext
annotations:
policies.kyverno.io/title: Add Default securityContext
policies.kyverno.io/category: Sample
policies.kyverno.io/subject: Pod
policies.kyverno.io/minversion: 1.6.0
policies.kyverno.io/description: >-
Une entrée `securityContext` de Pod définit des champs tels que l'utilisateur et le groupe qui doivent être utilisés pour exécuter le Pod.
Parfois, choisir des valeurs par défaut pour les utilisateurs plutôt que de bloquer est une meilleure alternative pour ne pas entraver de telles définitions de Pod. Cette politique mutera un Pod pour définir les champs `runAsNonRoot`, `runAsUser`, `runAsGroup` et `fsGroup` dans le `securityContext` du Pod s'ils ne sont pas déjà définis.
spec:
rules:
- name: add-default-securitycontext
match:
any:
- resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
spec:
securityContext:
+(runAsNonRoot): true
+(runAsUser): 1000
+(runAsGroup): 3000
+(fsGroup): 2000Le manifeste ci-dessus utilise la définition de ressource personnalisée (CRD) ClusterPolicy pour patcher les pods via mutate.PatchStrategicMerge et un contexte de sécurité avec un utilisateur non-root.
Les conteneurs sécurisés se construisent, ne se supposent pas
Bien que les conteneurs offrent une isolation et un moyen fiable de construire et d'exécuter des applications, la nature en constante évolution de la sécurité des conteneurs signifie que vous ne pouvez pas vous fier uniquement aux mesures préventives. Au lieu de cela, vous devriez utiliser une stratégie qui vous permet de réagir rapidement aux incidents dès qu'ils se produisent.
Cette stratégie commence par une analyse proactive.
Avec Aikido, vous pouvez automatiquement analyser les images de conteneurs pour détecter les paquets vulnérables, les environnements d'exécution obsolètes ou les instructions Dockerfile risquées avant qu'ils n'atteignent la production. Son scanner de dépendances open source étend cette protection en vérifiant vos bibliothèques à la recherche de CVE exploitables et même de vulnérabilités corrigées silencieusement que les attaquants pourraient utiliser pour obtenir des privilèges élevés.
Ces analyses sont renforcées par des vérifications IaC et de configuration qui signalent les paramètres Kubernetes ou Docker non sécurisés, et par des portes de sécurité CI/CD qui appliquent des politiques de moindre privilège au niveau du pipeline. Et parce que la prévention ne peut jamais être parfaite, Aikido Zen ajoute une protection en temps d’exécution pour détecter et répondre aux comportements anormaux des conteneurs en temps réel.
Sécurisez votre logiciel dès maintenant.



