Security musings

Catégories

Tags

🔍 Licence d'Utilisation 🔍

Sauf mention contraire, le contenu de ce blog est sous licence CC BY-NC-ND 4.0.

© 2025 à 2042 Sébastien Gioria. Tous droits réservés.

⏱️
Temps de lecture estimé
~10 minutes

Cet article fait partie de la série OWASP Top 10 Kubernetes 2026. Retrouvez le tableau de bord complet des dix risques et la matrice STRIDE sur la page d’entrée de la série.


K05 parle d’une catégorie de risques qui n’a rien d’exotique : des clusters qui tournent sur des versions de Kubernetes hors support, avec des composants de base mal configurés. Ce n’est pas le risque le plus spectaculaire de la liste, mais c’est souvent celui qu’on découvre en premier lors d’un audit.

L’API Server reçoit beaucoup d’attention. etcd, lui, est souvent oublié ; il stocke pourtant l’intégralité de l’état du cluster, secrets compris. Le kubelet tourne sur chaque node et expose une API locale rarement auditée. Et les versions de Kubernetes hors support accumulent des CVE documentées, disponibles publiquement, sans correctif disponible.

Un cluster Kubernetes n’est pas un serveur qu’on installe et qu’on oublie. C’est un système distribué avec des composants dont la surface d’attaque évolue à chaque release. Ne pas maintenir la version, c’est choisir de garder des vulnérabilités dont l’exploitation est documentée.

Vecteurs d’attaque

La version figée

On croise régulièrement des clusters en version 1.24, 1.25 ou encore 1.22 dans des environnements de production. La raison est presque toujours la même : la montée de version a été repoussée une fois, puis deux, puis six mois ont passé et ça tourne encore.

Le problème est documenté et mesurable. La liste CVE de Kubernetes est publique. Une version hors support accumule des vulnérabilités connues pour lesquelles aucun patch ne sera jamais publié. Les outils d’attaque automatisés incluent ces versions dans leurs bases de détection. Kube-bench, Kubescape et même des scanners grand public les signalent instantanément.

La surface exploitable n’est pas abstraite. Plusieurs CVE critiques des versions 1.21-1.24 permettent une escalade de privilèges depuis un pod ou un accès node via le kubelet. Ce ne sont pas des scénarios théoriques : les PoC sont publiés sur GitHub, indexés, et parfois intégrés dans des frameworks d’exploitation.

etcd sans chiffrement ni authentification

etcd stocke tout : les Secrets Kubernetes (base64, pas chiffrés), les ConfigMaps, les manifests, les tokens, les certificats. Une lecture directe sur etcd donne accès à l’intégralité de l’état du cluster sans passer par l’API Server et ses contrôles d’accès.

Le vecteur classique : etcd accessible sur 0.0.0.0:2379 sans TLS client, depuis un VLAN interne un peu trop ouvert. Dans les déploiements sur métal nu ou dans certaines configurations cloud “self-managed”, ce cas n’est pas rare.

etcdctl --endpoints=http://<etcd-ip>:2379 get /registry/secrets/production --prefix

Si cette commande retourne du contenu sans certificat client, tous les secrets du namespace production sont lisibles. Sans passer par le RBAC. Sans laisser de trace dans l’audit log de l’API Server.

Et pour ceux qui se disent “mais etcd c’est sur le réseau interne” : oui, et le réseau interne n’est pas un périmètre de sécurité. Chaque breach applicative, chaque pod mal isolé, chaque poste compromis devient un saut possible vers etcd.

Le kubelet trop bavard

Le kubelet expose une API REST sur le port 10250 (HTTPS) et, dans certaines vieilles configurations, sur le port 10255 (HTTP read-only). Cette API permet de lire les logs des pods, d’exécuter des commandes, voire d’interagir avec le runtime des conteneurs.

Une configuration par défaut ou un guide “quick-start” ancien peut laisser --anonymous-auth=true sur le kubelet, ce qui autorise des requêtes sans token. On peut alors lister les pods en cours d’exécution sur le node, lire les logs applicatifs, et dans certains cas exécuter des commandes dans les conteneurs via l’API /exec.

Ce vecteur est moins connu que l’API Server, mais il est présent sur chaque node du cluster. Un attaquant qui compromet un pod peut scanner les nodes et trouver un kubelet non durci.

Et c’est rarement vérifié lors des audits applicatifs qui se concentrent sur l’API Server en oubliant les composants périphériques.

Mitigations en 2026

Maintenir Kubernetes dans une version récente supportée

C’est tout simple et très facile, comme cuire des pates !

Rester sur la branche N ou N-1.

Le vrai coût d’une montée de version non préparée n’est pas la migration elle-même ; c’est le downstream : les Helm charts qui n’ont pas été testés, les opérateurs qui utilisent une API beta supprimée, le CNI qui n’est pas encore compatible. Inventorier les dépendances avant, pas pendant.

Chiffrer etcd at-rest avec KMS

Le chiffrement etcd at-rest est disponible nativement dans Kubernetes via EncryptionConfiguration. Sur les clouds majeurs (GKE, EKS, AKS), le KMS intégré permet de déléguer la gestion des clés au HSM du cloud provider.

Même si quelqu’un obtient un accès direct aux fichiers etcd ou à une snapshot de sauvegarde, le contenu reste chiffré et inutilisable sans la clé KMS. C’est le contrôle complémentaire aux politiques RBAC ; RBAC protège l’API Server, KMS protège le stockage.

kube-bench contrôle ce point (check CIS 1.2.31 et suivants). C’est une vérification rapide à ajouter dans le pipeline d’audit.

Désactiver l’authentification anonyme sur le kubelet

C’est un peu le pendant du problème déja évoqué en K01 sur l’API Server, on bloque de l’extérieur, mais on oublie que cela ne fait pas tout. Un node, un poste de dévelopeur compromis… Et Paf….

Sur chaque node, vérifier que le kubelet est configuré avec authentication.anonymous.enabled: false et authorization.mode: Webhook. L’audit kube-bench couvre ces checks (section 4.2 du benchmark CIS).

Ce n’est pas une configuration complexe ; mais les clusters anciens ne l’ont pas nécessairement. La vérification doit être faite explicitement, node par node, ou via un scan kube-bench .

Détecter les APIs dépréciées avant la migration

Pluto scanne les manifests et les releases Helm déployées pour identifier les ressources utilisant des APIs qui seront supprimées dans les prochaines versions. L’intégrer en CI/CD donne une visibilité précoce ; l’intégrer en gate bloquant évite les surprises lors des migrations.

DevSecOps : intégrer K05 dans la chaîne CI/CD

Phase Outil Action K05
Code Pluto, pre-commit Détecter les APIs dépréciées dans les manifests et alerter sur les Helm charts incompatibles avec la version cible.
Build kubeconform, conftest Valider les manifests contre le schéma de la version cible avant le déploiement.
Test kind, staging dédié Tester les migrations de version sur environnement représentatif avec CNI, opérateurs et webhooks réels.
Operate kube-bench + Kubescape Vérifier le chiffrement etcd at-rest, la config kubelet et la version K8s contre le benchmark CIS en continu.
Monitor Falco, alertes CVE Surveiller les accès directs à etcd, les requêtes kubelet anonymes et les nouvelles CVE sur la version déployée.
🔒 Plus d'éléments en contenu premium
Ce contenu représente de nombreuses heures de travail, d'expérience etc... J'ai remarqué que mon contenu était repris par certaines sociétés/personnes et j'ai donc décidé de donner du contenu minimal sur ce blog. C'est pourquoi je vous invite a me contacter sur LinkedIn en mentionnant cet article pour plus d'informations.

À retenir 📌
  • Rester dans la fenêtre de support : version N ou N-1, avec un processus de migration planifié, testé sur staging, pas géré en urgence.
  • Chiffrer etcd at-rest : avec KMS sur les clouds managés, avec EncryptionConfiguration en self-managed. Sans ça, tous les secrets sont lisibles dans le stockage.
  • Auditer le kubelet : anonymous-auth=false et authorization.mode=Webhook sur chaque node. kube-bench section 4.2 couvre ces checks.
  • Pluto en CI/CD : détecter les APIs dépréciées avant la migration, pas pendant.
  • etcd n'est pas un composant anodin : il mérite le même niveau d'attention que l'API Server, avec des contrôles réseau, d'authentification et de chiffrement explicites.