Auteurs : Jim Angel (Google), Pushkar Joglekar (VMware) et Savitha Raghunathan (Red Hat)
Contexte
L’Agence de sécurité nationale (NSA) des États-Unis et l’Agence de cybersécurité et de sécurité des infrastructures (CISA) ont publié le “Guide de renforcement de Kubernetes” le 3 août 2021. Le guide détaille les menaces pesant sur les environnements Kubernetes et fournit des conseils de configuration sécurisée pour minimiser les risques.
Les sections suivantes de ce blog sont en corrélation avec les sections du guide de la NSA/CISA. Les sections manquantes sont omises en raison des possibilités limitées d’ajouter du nouveau contenu.
Note : Cet article de blog ne remplace pas la lecture du guide. Il est recommandé de lire le guide publié avant de continuer, car le contenu suivant est complémentaire.
Introduction et modèle de menace
Il convient de noter que les menaces identifiées comme importantes par la NSA/CISA ou le public visé par ce guide peuvent différer des menaces considérées comme importantes par d’autres utilisateurs d’entreprises utilisant Kubernetes. Cette section est néanmoins utile pour les organisations qui se soucient des données, du vol de ressources et de l’indisponibilité des services.
Le guide met en évidence les trois sources de compromission suivantes :
- Risques liés à la chaîne d’approvisionnement
- Acteurs de menace malveillants
- Menaces internes (administrateurs, utilisateurs ou fournisseurs de services cloud)
Le modèle de menace tente de prendre du recul et d’examiner les menaces qui existent non seulement à l’intérieur de la limite d’un cluster Kubernetes, mais aussi dans l’infrastructure sous-jacente et les charges de travail environnantes que Kubernetes ne gère pas.
Par exemple, lorsqu’une charge de travail en dehors du cluster partage le même réseau physique, elle a accès au kubelet et aux composants du plan de contrôle : etcd, gestionnaire de contrôle, planificateur et serveur API. Par conséquent, le guide recommande d’avoir une isolation au niveau du réseau séparant les clusters Kubernetes des autres charges de travail qui n’ont pas besoin de se connecter aux nœuds du plan de contrôle Kubernetes. Plus précisément, le planificateur, le gestionnaire de contrôle et etcd doivent être accessibles uniquement au serveur API. Toute interaction avec Kubernetes depuis l’extérieur du cluster peut se faire en fournissant un accès au port du serveur API.
La liste des ports et des protocoles pour chacun de ces composants est définie dans les ports et les protocoles de la documentation Kubernetes.
Note spéciale : kube-scheduler et kube-controller-manager utilisent des ports différents de ceux mentionnés dans le guide.
La section sur la modélisation des menaces du Cloud Native Security Whitepaper + Map de la CNCF offre une autre perspective pour aborder la modélisation des menaces de Kubernetes, à travers un lens cloud-native.
Sécurité des pods Kubernetes
Par défaut, Kubernetes ne garantit pas une isolation stricte des charges de travail entre les pods s’exécutant sur le même nœud d’un cluster. Cependant, le guide propose plusieurs techniques pour renforcer l’isolement existant et réduire la surface d’attaque en cas de compromission.
Conteneurs “non-root” et moteurs de conteneurs “rootless”
Plusieurs meilleures pratiques liées au principe de sécurité de moindre privilège – fournir uniquement les autorisations nécessaires, ni plus, ni moins – valent la peine d’être examinées.
Le guide recommande de définir un utilisateur “non-root” lors de la construction de l’image du conteneur plutôt que de se fier à la définition de runAsUser au moment de l’exécution dans votre spécification Pod. Il s’agit d’une bonne pratique qui offre un certain niveau de défense en profondeur. Par exemple, si l’image du conteneur est construite avec l’utilisateur 10001 et que la spécification Pod omet d’ajouter le champ runAsuser dans son objet Déploiement. Dans ce cas, il existe certains cas particuliers qui valent la peine d’être explorés pour des raisons de sensibilisation :
Les pods peuvent échouer au démarrage si l’utilisateur défini au moment de la construction est différent de celui défini dans la spécification du pod et que certains fichiers sont donc inaccessibles.
Les pods peuvent finir par partager des identifiants d’utilisateur involontairement. Cela peut poser problème même si les identifiants d’utilisateur ne sont pas nuls, dans une situation où une échappée de conteneur vers le système de fichiers hôte est possible. Une fois que l’attaquant a accès au système de fichiers hôte, il a accès à toutes les ressources de fichiers qui sont propriétaires d’autres pods non liés qui partagent le même UID.
Les pods peuvent finir par partager des identifiants d’utilisateur avec d’autres processus au niveau du nœud qui ne sont pas gérés par Kubernetes, par exemple des démons au niveau du nœud pour l’audit, la recherche de vulnérabilités, la télémétrie. La menace est similaire à celle décrite ci-dessus, où l’accès au système de fichiers hôte peut donner à un attaquant un accès complet à ces démons au niveau du nœud sans avoir besoin d’être root sur le nœud.
Cependant, aucun de ces cas n’aura un impact aussi grave qu’un conteneur s’exécutant en tant que root et capable de s’échapper en tant qu’utilisateur root sur l’hôte, ce qui peut donner à un attaquant un contrôle total du nœud de travail, lui permettant ensuite de se déplacer latéralement vers d’autres nœuds de travail ou de contrôle.
Kubernetes 1.22 a introduit une fonctionnalité alpha qui réduit spécifiquement l’impact d’un composant du plan de contrôle s’exécutant en tant qu’utilisateur root vers un utilisateur non-root via les espaces de noms utilisateur.
Cette prise en charge (en phase alpha) des espaces de noms utilisateur / mode sans privilège est disponible avec les runtime de conteneurs suivants :
- Docker Engine
- Podman
Certaines distributions prennent en charge l’exécution en mode non-root, comme les suivantes :
- kind
- k3s
- Usernetes
Systèmes de fichiers de conteneur immuables
Le guide de renforcement de Kubernetes recommande également de ne pas négliger une fonctionnalité souvent négligée, le readOnlyRootFileSystem, avec un exemple de travail dans l’annexe B. Cet exemple limite l’exécution et la manipulation des conteneurs à l’exécution. Toute activité de lecture/écriture peut ensuite être limitée à quelques répertoires en utilisant des montages de volumes tmpfs.
Cependant, certaines applications qui modifient le système de fichiers du conteneur à l’exécution, comme l’explosion d’un fichier WAR ou JAR au démarrage du conteneur, pourraient rencontrer des problèmes lors de l’activation de cette fonctionnalité. Pour éviter ce problème, envisagez d’apporter des modifications minimales au système de fichiers à l’exécution lorsque cela est possible.
Construction d’images de conteneur sécurisées
Le guide de renforcement de Kubernetes recommande également d’exécuter un analyseur au moment du déploiement en tant que contrôleur d’admission pour empêcher l’exécution de pods vulnérables ou mal configurés dans le cluster. Théoriquement, cela semble être une bonne approche, mais il existe plusieurs précautions à prendre en compte avant de pouvoir l’implémenter dans la pratique :
En fonction de la bande passante réseau, des ressources disponibles et du scanner choisi, l’analyse des vulnérabilités d’une image peut prendre un temps indéterminé. Cela peut entraîner des temps de démarrage des pods plus lents ou imprévisibles, ce qui peut entraîner des pics d’indisponibilité lorsque les applications sont soumises à une charge de pointe.
Si la politique qui permet ou refuse le démarrage d’un pod est établie à l’aide de données incorrectes ou incomplètes, cela peut entraîner plusieurs résultats faux positifs ou faux négatifs, comme les exemples suivants :
- Dans une image de conteneur, le package openssl est détecté comme vulnérable. Cependant, l’application est écrite en Golang et utilise le package Go crypto pour TLS. Par conséquent, cette vulnérabilité n’est pas dans le chemin d’exécution du code et a donc un impact minimal si elle n’est pas corrigée.
- Une vulnérabilité est détectée dans le package openssl pour une image de base Debian. Cependant, la communauté Debian considère cette vulnérabilité comme mineure et ne publie donc pas de correctif pour cette vulnérabilité. Le propriétaire de cette image est maintenant confronté à une vulnérabilité qui ne peut pas être corrigée et à un cluster qui n’autorise pas l’exécution de l’image en raison d’une politique prédéfinie qui ne tient pas compte de la disponibilité ou non de la correction d’une vulnérabilité.
- Une application Golang est construite sur une image distroless, mais elle est compilée avec une version vulnérable de la bibliothèque standard Golang. Le scanner n’a pas de visibilité sur la version de Golang, mais seulement sur les packages du niveau du système d’exploitation. Il permet donc au pod de s’exécuter dans le cluster malgré le fait que l’image contienne un binaire d’application construit sur un Golang vulnérable.
Pour être clair, il est absolument recommandé de s’appuyer sur des scanners de vulnérabilités, mais les définitions des politiques doivent être suffisamment flexibles pour permettre :
- La création de listes d’exceptions pour les images ou les vulnérabilités à l’aide de balises
- La substitution de la gravité par un score de risque basé sur l’impact d’une vulnérabilité
- L’application des mêmes politiques au moment de la construction pour détecter les images vulnérables avec des vulnérabilités pouvant être corrigées avant leur déploiement dans les clusters Kubernetes
Des considérations spéciales telles que la récupération hors ligne de la base de données des vulnérabilités peuvent également être nécessaires si les clusters s’exécutent dans un environnement isolé et que les scanners nécessitent un accès Internet pour mettre à jour la base de données des vulnérabilités.
Politiques de sécurité des pods
Depuis Kubernetes v1.21, l’API de la politique de sécurité des pods et les fonctionnalités associées sont obsolètes, mais certaines des recommandations de cette section s’appliqueront encore pendant quelques années, jusqu’à ce que les opérateurs de clusters mettent à jour leurs clusters vers les versions plus récentes de Kubernetes.
Le projet Kubernetes travaille sur un remplacement pour la politique de sécurité des pods. Kubernetes v1.22 inclut une fonctionnalité alpha appelée Admission de sécurité des pods qui permet d’imposer un niveau minimal d’isolation entre les pods.
Les niveaux d’isolation intégrés de l’Admission de sécurité des pods sont dérivés des normes de sécurité des pods, qui sont un ensemble de tous les composants mentionnés dans le tableau I de la page 10 du guide.
Des informations sur la migration de la politique de sécurité des pods vers la fonctionnalité Admission de sécurité des pods intégrée sont disponibles dans la documentation “Migrate from PodSecurityPolicy to the Built-In PodSecurity Admission Controller”.
Un comportement important mentionné dans le guide qui reste le même entre la politique de sécurité des pods et son remplacement est que l’application de l’une ou l’autre d’entre elles n’affecte pas les pods qui sont déjà en cours d’exécution. Avec la politique de sécurité des pods et l’Admission de sécurité des pods, l’application se fait lors de la création du pod.
Durcissement des moteurs de conteneurs
Certaines charges de travail de conteneurs sont moins fiables que d’autres mais peuvent avoir besoin de s’exécuter dans le même cluster. Dans ces cas, les exécuter sur des nœuds dédiés incluant des runtimes de conteneurs renforcés offrant des frontières d’isolation plus strictes peut agir comme un contrôle de sécurité utile.
Kubernetes prend en charge une API appelée RuntimeClass, qui est en version stable/GA (et donc activée par défaut) depuis Kubernetes v1.20. RuntimeClass vous permet de vous assurer que les pods nécessitant une isolation renforcée sont planifiés sur des nœuds pouvant l’offrir.
Certains projets tiers que vous pouvez utiliser en conjonction avec RuntimeClass sont :
- kata containers
- gvisor
Comme discuté ici et dans le guide, de nombreuses fonctionnalités et outils existent dans Kubernetes et autour de Kubernetes pour améliorer les frontières d’isolation entre les pods. En fonction des menaces pertinentes et de la posture de risque, vous devez choisir parmi ces fonctionnalités et outils, plutôt que d’essayer d’appliquer toutes les recommandations. Cependant, l’isolation au niveau du cluster, c’est-à-dire l’exécution des charges de travail dans des clusters dédiés, reste le mécanisme d’isolation des charges de travail le plus strict, en dépit des améliorations mentionnées précédemment ici et dans le guide.
Séparation et durcissement des réseaux
La mise en réseau de Kubernetes peut être délicate, et cette section met l’accent sur la sécurisation et le durcissement des configurations pertinentes. Le guide identifie les points clés suivants :
- Utilisation de NetworkPolicies pour créer une isolation entre les ressources.
- Sécurisation du plan de contrôle.
- Chiffrement du trafic et des données sensibles.
Network Policies
Les politiques réseau peuvent être créées à l’aide de plugins réseau. Pour faciliter la création et la visualisation pour les utilisateurs, Cilium prend en charge un outil graphique web. Cet outil web vous permet de créer des NetworkPolicies Kubernetes (une API générique qui nécessite néanmoins un plugin CNI compatible) et/ou des politiques réseau Cilium (CiliumClusterwideNetworkPolicy et CiliumNetworkPolicy, qui ne fonctionnent que dans les clusters utilisant le plugin CNI Cilium). Vous pouvez utiliser ces API pour restreindre le trafic réseau entre les pods et ainsi réduire le vecteur d’attaque.
Un autre scénario qui mérite d’être exploré est l’utilisation des adresses IP externes. Certains services, lorsqu’ils sont mal configurés, peuvent créer des adresses IP externes aléatoires. Un attaquant peut profiter de cette mauvaise configuration et intercepter facilement le trafic. Cette vulnérabilité a été signalée dans CVE-2020-8554. L’utilisation de l’externalip-webhook peut atténuer cette vulnérabilité en empêchant les services d’utiliser des adresses IP externes aléatoires. externalip-webhook permet uniquement la création de services qui n’ont pas besoin d’adresses IP externes ou dont les adresses IP externes se trouvent dans la plage spécifiée par l’administrateur.
Politiques de ressources
En plus de configurer les quotas de ressources et les limites, envisagez de limiter le nombre d’identifiants de processus (PIDs) qu’un pod donné peut utiliser et de réserver certains PIDs pour une utilisation au niveau du nœud afin d’éviter l’épuisement des ressources. Vous trouverez plus de détails pour appliquer ces limites dans les limites et les réservations d’identifiants de processus.
Durcissement du plan de contrôle
Dans la section suivante, le guide aborde le durcissement du plan de contrôle. Il convient de noter qu’à partir de Kubernetes 1.20, le port non sécurisé de l’API server a été supprimé.
Etcd
En règle générale, le serveur etcd doit être configuré pour faire confiance uniquement aux certificats attribués au serveur API. Cela limite la surface d’attaque et empêche un attaquant malveillant d’accéder au cluster. Il peut être bénéfique d’utiliser une autorité de certification distincte pour etcd, car elle fait par défaut confiance à tous les certificats délivrés par l’autorité de certification racine.
Fichiers kubeconfig
En plus de spécifier directement le jeton et les certificats, .kubeconfig prend en charge la récupération dynamique de jetons temporaires en utilisant des plug-ins fournisseurs d’authentification. Méfiez-vous de la possibilité d’exécution de code shell malveillant dans un fichier kubeconfig. Une fois que les attaquants ont accès au cluster, ils peuvent voler des clés SSH/secrets ou autres.
Secrets
Kubernetes Secrets est le moyen natif de gérer les secrets en tant qu’objet API Kubernetes. Cependant, dans certains scénarios, tels que le désir d’avoir une seule source de vérité pour tous les secrets de l’application, qu’ils s’exécutent sur Kubernetes ou non, les secrets peuvent être gérés de manière peu couplée avec Kubernetes et consommés par des sidecars ou des conteneurs init avec une utilisation minimale de l’API Secrets Kubernetes.
Des fournisseurs de secrets externes et csi-secrets-store sont quelques-unes de ces alternatives aux Secrets Kubernetes.
Audit des logs
Le guide de la NSA/CISA insiste sur la surveillance et l’alerte basées sur les journaux. Les points clés comprennent l’enregistrement au niveau de l’hôte, au niveau de l’application et dans le cloud. Lors de l’exécution de Kubernetes en production, il est important de comprendre qui est responsable et qui est responsable de chaque couche de journalisation.
Audit de l’API Kubernetes
Un domaine qui mérite plus d’attention est ce qui devrait exactement déclencher une alerte ou être enregistré. Le document décrit une politique d’exemple dans l’annexe L : Politique d’audit qui enregistre toutes les requêtes-réponses, y compris les métadonnées et les corps des requêtes/réponses. Bien que cela soit utile pour une démonstration, cela peut ne pas être pratique pour la production.
Chaque organisation doit évaluer son propre modèle de menace et créer une politique d’audit qui complète ou aide à la résolution des problèmes de la réponse en cas d’incident. Réfléchissez à la manière dont quelqu’un pourrait attaquer votre organisation et à la piste d’audit qui pourrait l’identifier. Examinez des options plus avancées pour ajuster les journaux d’audit dans la documentation officielle de journalisation d’audit. Il est essentiel d’ajuster vos journaux d’audit pour n’inclure que les événements qui correspondent à votre modèle de menace. Une politique d’audit minimale qui enregistre tout au niveau des métadonnées peut également constituer un bon point de départ.
Les configurations de journalisation d’audit peuvent également être testées avec kind en suivant ces instructions.
Journaux en continu et audit
La journalisation est importante pour la détection des menaces et des anomalies. Comme le document le souligne, il est préférable de numériser et d’alerter sur les journaux aussi près que possible du temps réel et de protéger les journaux contre la manipulation en cas de compromission. Il est important de réfléchir aux différents niveaux de journalisation et d’identifier les domaines critiques tels que les points d’accès de l’API.
La journalisation de l’audit de l’API Kubernetes peut être diffusée vers un webhook et un exemple est présenté dans l’annexe N : Configuration du webhook. L’utilisation d’un webhook pourrait être une méthode qui stocke les journaux en dehors du cluster et/ou centralise tous les journaux d’audit. Une fois que les journaux sont gérés de manière centralisée, il est possible d’activer l’alerte en fonction des événements critiques. Assurez-vous également de comprendre quelle est la référence pour les activités normales.
Identification des alertes
Bien que le guide souligne l’importance des notifications, il n’y a pas de liste d’événements génériques pour lesquels déclencher une alerte. Les exigences en matière d’alerte varient en fonction de vos propres besoins et de votre modèle de menace. Voici quelques exemples d’événements :
- Modifications du securityContext d’un pod
- Mises à jour des configurations du contrôleur d’admission
- Accès à certains fichiers/URL
Ressources supplémentaires sur les journaux
- Seccomp Security Profiles and You: A Practical Guide – Duffie Cooley
- TGI Kubernetes 119: Gatekeeper and OPA
- Abusing The Lack of Kubernetes Auditing Policies
- Enable seccomp for all workloads with a new v1.22 alpha feature
- This Week in Cloud Native: Auditing / Pod Security
Pratiques de mise à niveau et de sécurité des applications
Kubernetes publie trois versions par an, il est donc courant que les personnes utilisant des clusters de production se heurtent à des problèmes liés aux mises à niveau. En plus de cela, les opérateurs doivent régulièrement mettre à jour le système d’exploitation des nœuds sous-jacents et les applications en cours d’exécution. Il s’agit d’une pratique recommandée pour garantir un support continu et réduire la probabilité de bugs ou de vulnérabilités.
Kubernetes prend en charge les trois versions stables les plus récentes. Bien que chaque version de Kubernetes fasse l’objet de nombreux tests avant sa publication, certaines équipes ne sont pas à l’aise pour exécuter la dernière version stable tant qu’un certain temps ne s’est pas écoulé. Quelle que soit la version que vous utilisez, assurez-vous que les mises à niveau de correctifs se produisent fréquemment ou automatiquement. Vous trouverez plus d’informations dans les pages de la politique de version de décalage.
Lorsque vous réfléchissez à la manière dont vous gérerez les mises à niveau du système d’exploitation des nœuds, envisagez les nœuds éphémères. La possibilité de détruire et d’ajouter des nœuds permet à votre équipe de réagir plus rapidement aux problèmes de nœud. De plus, le fait d’avoir des déploiements tolérants à l’instabilité des nœuds (et une culture qui encourage les déploiements fréquents) facilite les mises à niveau du cluster.
De plus, il est utile de rappeler à partir du guide que des analyses de vulnérabilités périodiques et des tests de pénétration peuvent être effectués sur les différents composants système pour rechercher proactivement des configurations non sécurisées et des vulnérabilités.
Recherche d’informations sur les versions et la sécurité
Pour trouver les versions de Kubernetes prises en charge les plus récentes, consultez https://k8s.io/releases, qui comprend les versions mineures. Il est bon de rester à jour avec les correctifs de votre version mineure.
Si vous utilisez une offre Kubernetes gérée, recherchez leur documentation de publication et recherchez leurs différents canaux de sécurité.
Abonnez-vous à la liste de diffusion Kubernetes Announce. La liste de diffusion Kubernetes Announce est consultable pour des termes tels que “Security Advisories”. Vous pouvez configurer des alertes et des notifications par e-mail tant que vous savez quels mots clés alerter.
Conclusion
En résumé, il est fantastique de voir les praticiens de la sécurité partager ce niveau de détails dans le domaine public. Ce guide met en évidence davantage l’adoption croissante de Kubernetes et la nécessité continue de se concentrer sur la sécurisation des clusters Kubernetes et des conteneurs d’application s’exécutant sur Kubernetes. Quelques semaines seulement après la publication du guide, un outil open source appelé kubescape, permettant de valider un cluster par rapport à ce guide, est devenu disponible.
Cet outil peut constituer un excellent point de départ pour vérifier l’état actuel de vos clusters, après quoi vous pouvez utiliser les informations de cet article de blog et du guide pour évaluer les améliorations possibles.
Enfin, il convient de rappeler que tous les contrôles de ce guide n’ont pas la même pertinence pour tous les praticiens. La meilleure façon de savoir quels contrôles sont importants est de s’appuyer sur le modèle de menace de votre propre environnement Kubernetes.
Un clin d’œil spécial et des remerciements à Rory McCune (@raesene) pour ses contributions à cet article de blog.
← Précédent Suivant →