Impossible à contenir : Découverte d'une vulnérabilité d'injection de commandes dans Kubernetes
Commentaires éditoriaux et additionnels de Tricia Howard
Synthèse
Tomer Peled, chercheur sur la sécurité d'Akamai, a récemment découvert une vulnérabilité très sévère dans Kubernetes, dénommée CVE-2023-3676, avec un score CVSS de 8,8.
Cette découverte a conduit à l'identification de deux vulnérabilités supplémentaires, étant donné qu'elles partagent la même cause fondamentale : l'appel de fonction non sécurisé et le manque de sécurisation des saisies de l'utilisateur.
Cette vulnérabilité permet l'exécution de code à distance avec des privilèges SYSTÈME sur tous les terminaux Windows au sein d'un cluster Kubernetes. Pour exploiter cette vulnérabilité, le pirate doit appliquer un fichier YAML malveillant sur le cluster.
Cette vulnérabilité peut être exploitée sur les installations par défaut de Kubernetes, et a été testée à la fois pour des déploiements sur site et sur Azure Kubernetes Service.
Nous fournissons un fichier YAML comme démonstration, ainsi qu'une règle OPA pour bloquer cette vulnérabilité.
Introduction
YAML (qui signifie YAML Ain't Markup Language) est un langage de sérialisation de données similaire à JSON qui est principalement utilisé dans les fichiers de configuration. En tant que tel, il joue un rôle important dans Kubernetes, le nouveau système d'orchestration des conteneurs omniprésent qui aide les organisations à automatiser le déploiement, la mise à l'échelle et la gestion des applications conteneurisées. Le cadre de Kubernetes utilise des fichiers YAML pour pratiquement tout, de la configuration de l'interface réseau des conteneurs à la gestion des pods et même à la manipulation des secrets.
Les fichiers YAML dans Kubernetes ont fait l'objet de recherches ces dernières années. Étant donné que Kubernetes s'appuie sur YAML pour la configuration des clusters, ce sujet de recherche est particulièrement intéressant à explorer.
Comment YAML et Kubernetes ont-ils été exploités auparavant ?
En 2022, CVE-2022-1471 a été trouvée dans le constructeur de SnakeYAML, un analyseur connu des fichiers YAML. Cette vulnérabilité a permis la création d'objets non sécurisés, ce qui pouvait conduire à l'exécution de code sur des applications vulnérables l'utilisant. Un autre exemple montrant l'impact possible des fichiers YAML est disponible dans cet avis CVE à propos de CVE-2021-25749, écrit par l'équipe de sécurité Kubernetes. Cette vulnérabilité permet aux pirates de contourner la vérification des personnes autorisées à effectuer l'exécution en tant que root en orthographiant mal leur nom dans le fichier YAML.
Dans le cadre de nos recherches sur Kubernetes, nous avons découvert CVE-2017-1002101 et CVE-2021-25741. Ces vulnérabilités ont démontré comment les pirates peuvent utiliser des concurrences critiques et des liens symboliques en conjonction avec la sous-propriété subPath dans un fichier YAML pour accéder à des données privilégiées en dehors du conteneur.
Ces vulnérabilités passées nous ont incités à poursuivre le traitement des chemins dans la base de code Kubernetes, ce qui a finalement conduit à la découverte de la vulnérabilité dont nous discutons aujourd'hui.
Dans cet article de blog, nous montrerons comment un pirate avec les privilèges « apply » (les privilèges requis pour interagir avec l'API de Kubernetes) peut injecter du code qui sera exécuté sur des machines Windows distantes avec des privilèges SYSTÈME.
Informations sur cette vulnérabilité
Lorsqu'un pod est créé, l'utilisateur a la possibilité de créer un répertoire partagé entre le pod et l'hôte. Cette fonction, appelée volumes, est utile, par exemple, lors de la prise en charge de sites Web via un conteneur dans un pod. Nous pouvons partager les fichiers du site à partir d'un répertoire partagé avec l'hôte. De cette façon, il est possible de modifier la disposition du site comme nous le souhaitons sans avoir besoin de recompiler une image contenant le site à chaque fois.
L'activation des volumes s'effectue en incluant le paramètre des volumes dans le fichier YAML du pod. Les emplacements de montage du volume sont répertoriés dans mountPath (emplacement dans le conteneur) et hostPath (emplacement sur l'hôte).
Le plus important pour nousest que nous pouvons monter notre fichier ou répertoire partagé dans un emplacement choisi en utilisant la sous-propriété subPath. Toutes les propriétés pertinentes pour les volumes sont visibles dans la figure 1.
L'analyse de notre fichier YAML est effectuée par kubelet, un service central dans Kubernetes qui est responsable de l'exécution des applications conteneurisées sur un nœud. Dans le cadre du correctif pour CVE-2021-25741, kubelet valide tous les paramètres du fichier YAML et s'assure également qu'aucun lien symbolique n'est créé suite à l'utilisation du paramètre subPath en appelant la fonction interne « isLinkPath ». La fonction est illustrée dans la figure 2.
La fonction prend comme paramètre le subPath qui a été fourni par l'utilisateur dans le fichier YAML. Elle utilise ensuite ce chemin pour créer une commande PowerShell destinée à déterminer le type de chemin (c'est-à-dire s'il s'agit d'un lien symbolique ou non). La commande PowerShell formatée est alors immédiatement appelée par l'appel de fonction « exec.Command ».
La présence de « exec.Command » combinée avec une entrée non assainie fournie par l'utilisateur souligne fortement une opportunité d'injection de commandes.
PowerShell permet aux utilisateurs d'évaluer les valeurs à l'intérieur des chaînes avant qu'elles ne soient utilisées. Cela peut être fait en ajoutant $(<expression_to_be_evaluated>) à votre chaîne, par exemple (Figure 3).
PS> echo “the value of 1+1 is $(1+1)
Output:
the value of 1+1 is 2
Figure 3 : Exemple de PowerShell évaluant des expressions dans des chaînes
Cet exemple est assez simple, mais en fait, n'importe quelle commande PowerShell peut être insérée entre les parenthèses et sera évaluée, comme $(Start-Process cmd), $(Invoke-Expression exp) et d'autres traitements PowerShell.
Un pirate peut utiliser cette évaluation subPath à mauvais escient pour atteindre le code vulnérable et exécuter la commande qu'il souhaite avec des privilèges SYSTÈME (contexte propre à kubelet) à partir de nœuds distants,et prendre le contrôle de tous les nœuds Windows du cluster. La figure 4 illustre une valeur subPath malveillante.
Démonstration présentant CVE-2023-3676
La démonstration est simplement un fichier YAML qui contient l'évaluation de la commande PowerShell. Vous pouvez trouver ce fichier, ainsi qu'une vidéo présentant le terminal en cours de démarrage, dans notre référentiel GitHub.
Cette CVE a conduit à la découverte et à la correction d'autres vulnérabilités d'injection de commandes. Elles ont reçu collectivement les numéros CVE-2023-3955 et CVE-2023-3893.
Analyse des correctifs
L'équipe Kubernetes a choisi de corriger cette classe de vulnérabilités en transmettant des paramètres à partir de variables d'environnement plutôt qu'à partir d'entrées utilisateur (Figure 5). Avec cette méthode de transmission des valeurs, les paramètres sont traités comme des chaînes. Par conséquent, ils ne sont pas évalués comme des expressions par PowerShell.
Suis-je vulnérable ?
Comme nous l'avons mentionné ci-dessus, toutes les versions de Kubernetes inférieures à 1.28 sont vulnérables à cette CVE. Il existe plusieurs méthodes pour déterminer si l'un des nœuds de votre cluster est un nœud Windows. Une méthode consiste à exécuter la commande de la figure 6.
kubectl get nodes -o wide --show-labels | grep “os=windows” Résultat : akswin000000 Ready agent 4d17h v1.26.6 agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows… akswin000001 Ready agent 4d17h v1.26.6 agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows… |
Figure 6 : Commande kubectl pour déterminer si l'un des nœuds de votre cluster est un nœud Windows
Protection
L'application de correctifs est le moyen le plus fiable de vous protéger contre cette vulnérabilité. Dans les cas où l'application de correctifs n'est pas possible, nous avons décrit un certain nombre de moyens potentiels de vous protéger contre cette vulnérabilité. Vous pouvez choisir celui qui convient le mieux à votre environnement.
Solutions précédentes
Pour CVE-2023-3676, les administrateurs Kubernetes peuvent désactiver l'utilisation de Volume.Subpath. Cela garantira que votre cluster est protégé contre cette vulnérabilité, mais désactivera un mécanisme parfois important pour les clusters en production.
OPA
Open Policy Agent (OPA) est un agent open source qui permet aux utilisateurs de recevoir des données sur le trafic entrant et sortant des nœuds, et d'effectuer des actions basées sur des règles sur les données reçues. OPA utilise Rego en tant que langage pour le moteur. Les administrateurs peuvent ainsi créer des règles pour bloquer l'implémentation de certains fichiers YAML. La figure 7 illustre une règle refusant la création de pods avec un subPath malveillant.
package kubernetes.admission
deny[msg] {
input.request.kind.kind == "Pod"
path := input.request.object.spec.containers.volumeMounts.subPath
not startswith(path, "$(")
msg := sprintf("malicious path: %v was found", [path])
}
Figure 7 : Règle bloquant la création de pods avec un subPath malveillant
RBAC
Le contrôle d'accès basé sur les rôles (RBAC) est une méthode qui segmente les opérations utilisateur en fonction de l'identité de l'utilisateur. Par exemple, chaque utilisateur ne peut créer des pods que dans son propre espace de noms ou ne peut afficher les informations que pour les espaces de noms autorisés. Cela peut contribuer à limiter le nombre d'utilisateurs pouvant effectuer des actions sur un cluster et à concentrer l'attention sur ceux qui ont les privilèges appropriés pour l'exploitation.
Conclusion
CVE-2023-3676 nécessite des privilèges faibles et simplifie donc la tâche des pirates : il leur suffit d'avoir accès à un nœud et à des privilèges apply . Comme nous l'avons vu dans cet article de blog, l'exploitation réussie de cette vulnérabilité entraîne l'exécution de code à distance sur n'importe quel nœud Windows de la machine avec des privilèges SYSTÈME.
L'association entre impact élevé et exploitation facile implique un fort risque de voir les entreprises touchées par cette attaque (et des attaques similaires). En fait, le seul facteur limitant de cette vulnérabilité est sa portée, restreinte aux nœuds Windows, qui ne sont pas très populaires aujourd'hui.
Il est important que les administrateurs corrigent leurs clusters Kubernetes avec la dernière version disponible pour empêcher l'exploitation de ces vulnérabilités. Si vous n'avez pas immédiatement accès au correctif, nous vous recommandons d'utiliser l'une des méthodes décrites ci-dessus pour vous défendre contre cette vulnérabilité.
Nous tenons à remercier l'équipe Kubernetes pour sa réponse très rapide et sa communication fluide.
Calendrier de divulgation
13/07/2023 — Vulnérabilité révélée à l'équipe Kubernetes
19/07/2023 — CVE attribuées par l'équipe Kubernetes
23/08/2023 — Correctifs CVE publiés par Kubernetes
13/09/2023 — Article de blog publié