Qu'est-ce que l'OWASP Kubernetes Top 10 ?

L'OWASP Kubernetes Top 10 identifie les risques de sécurité les plus importants dans les environnements Kubernetes. Kubernetes est devenu la norme de facto pour l'orchestration de conteneurs, mais sa flexibilité et sa complexité introduisent de nombreux défis de sécurité. Ce guide couvre les mauvaises configurations de charges de travail, les problèmes RBAC, la gestion des secrets, la segmentation réseau, et plus encore.

1�E�⃣ K01 - Configurations de Charges de Travail Non Sécurisées

Critical

Vue d'ensemble

Les configurations de charges de travail non sécurisées sont le problème de sécurité Kubernetes le plus courant. Les conteneurs exécutés en tant que root, avec des privilèges excessifs, des systèmes de fichiers en écriture, ou sans limites de ressources créent des surfaces d'attaque importantes. Les configurations par défaut sont souvent non sécurisées et doivent être explicitement renforcées.

Risque

Un conteneur compromis avec des privilèges root et un accès à l'hôte peut s'échapper du sandbox du conteneur, accéder au système de fichiers de l'hôte et pivoter vers d'autres charges de travail. L'escalade de privilèges à partir d'un pod mal configuré peut conduire à la compromission complète du cluster.

Exemple de Code Vulnérable

YAML (Kubernetes Pod) ❁EBad
apiVersion: v1
kind: Pod
metadata:
  name: insecure-app
spec:
  containers:
  - name: app
    image: myapp:latest          # Mutable tag!
    securityContext:
      privileged: true            # Full host access!
      runAsUser: 0                # Running as root!
    volumeMounts:
    - mountPath: /host
      name: host-fs
  volumes:
  - name: host-fs
    hostPath:
      path: /                    # Entire host filesystem!

Exemple de Code Sécurisé

YAML (Kubernetes Pod) ✁EGood
apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp@sha256:abc123...  # Immutable digest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      runAsUser: 1000
      capabilities:
        drop: ["ALL"]
    resources:
      limits:
        cpu: "500m"
        memory: "256Mi"
      requests:
        cpu: "100m"
        memory: "128Mi"

Liste de Contrôle d'Atténuation

2�E�⃣ K02 - Configurations d'Autorisation Trop Permissives

Critical

Vue d'ensemble

Le RBAC (Role-Based Access Control) de Kubernetes est puissant mais complexe. Les rôles trop permissifs  Een particulier les liaisons cluster-admin, les permissions génériques et les privilèges excessifs des comptes de service  Epermettent un accès non autorisé aux ressources du cluster, aux secrets et aux charges de travail.

Risque

Un attaquant qui obtient l'accès à un compte de service sur-privilégié peut lister les secrets, créer des pods privilégiés, modifier les déploiements et escalader vers cluster-admin. Les règles RBAC génériques sont l'équivalent Kubernetes de l'octroi d'un accès root.

Exemple de Code Vulnérable

YAML (Kubernetes RBAC) ❁EBad
# ClusterRoleBinding granting cluster-admin to a service account
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: app-admin-binding
subjects:
- kind: ServiceAccount
  name: my-app            # App SA with cluster-admin!
  namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-admin      # Full cluster control!
  apiGroup: rbac.authorization.k8s.io

Exemple de Code Sécurisé

YAML (Kubernetes RBAC) ✁EGood
# Scoped Role with minimum required permissions
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-role
  namespace: my-app-ns
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list"]     # Read-only, specific resources
  resourceNames: ["app-config"]  # Named resource only
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-role-binding
  namespace: my-app-ns
subjects:
- kind: ServiceAccount
  name: my-app
  namespace: my-app-ns
roleRef:
  kind: Role
  name: app-role
  apiGroup: rbac.authorization.k8s.io

Liste de Contrôle d'Atténuation

3�E�⃣ K03 - Échecs de Gestion des Secrets

Critical

Vue d'ensemble

Les Secrets Kubernetes sont uniquement encodés en base64 par défaut, et non chiffrés. Stocker des données sensibles (clés API, mots de passe de base de données, certificats TLS) dans des ConfigMaps ordinaires, des variables d'environnement ou des Secrets non chiffrés les expose à toute personne ayant accès à l'API. Les secrets sont également visibles dans etcd si le chiffrement au repos n'est pas activé.

Risque

Les secrets exposés permettent aux attaquants d'accéder aux bases de données, aux comptes cloud et aux services externes. Les secrets stockés dans etcd sans chiffrement peuvent être lus par toute personne ayant accès à etcd. Les secrets de variables d'environnement sont visibles dans les spécifications de pods et les listes de processus.

Exemple de Code Vulnérable

YAML (Kubernetes) ❁EBad
# Secret in plain ConfigMap  Evisible to anyone
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DB_PASSWORD: "SuperSecret123!"   # Plaintext password!
  API_KEY: "sk-live-abc123xyz"      # API key in ConfigMap!
---
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: myapp:latest
    envFrom:
    - configMapRef:
        name: app-config    # All values as env vars!

Exemple de Code Sécurisé

YAML (Kubernetes + External Secrets) ✁EGood
# Use External Secrets Operator with a vault backend
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secrets
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: app-secrets
  data:
  - secretKey: db-password
    remoteRef:
      key: secret/myapp/db
      property: password
---
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: myapp@sha256:abc123...
    volumeMounts:
    - name: secrets
      mountPath: /etc/secrets
      readOnly: true          # Mount as read-only files
  volumes:
  - name: secrets
    secret:
      secretName: app-secrets

Liste de Contrôle d'Atténuation

4�E�⃣ K04 - Manque d'Application de Politiques au Niveau du Cluster

High

Vue d'ensemble

Sans politiques au niveau du cluster, il n'y a aucune barrière empêchant le déploiement de charges de travail non sécurisées. Les Pod Security Standards (PSS), les contrôleurs d'admission et les moteurs de politiques comme OPA Gatekeeper ou Kyverno sont essentiels pour appliquer des bases de sécurité dans tous les espaces de noms.

Risque

Sans application de politiques, tout développeur peut déployer des conteneurs privilégiés, utiliser des volumes hostPath ou désactiver les contrôles de sécurité. Une seule charge de travail mal configurée peut compromettre l'ensemble du cluster. La révision manuelle ne peut pas évoluer pour détecter toutes les violations.

Exemple de Code Vulnérable

Bash ❁EBad
#!/bin/bash
# No admission control  Eany pod spec is accepted
# No Pod Security Standards configured

# Anyone can deploy a privileged container
kubectl run hacker-pod --image=alpine \
  --overrides='{"spec":{"containers":[{
    "name":"hack",
    "image":"alpine",
    "securityContext":{"privileged":true},
    "command":["nsenter","--target","1","--mount","--uts","--ipc","--net","--pid","--","bash"]
  }]}}'

# No policy blocks this  Enow has host root access!

Exemple de Code Sécurisé

YAML (Kyverno ClusterPolicy) ✁EGood
# Enforce Pod Security Standards with Kyverno
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged
spec:
  validationFailureAction: Enforce
  background: true
  rules:
  - name: deny-privileged
    match:
      any:
      - resources:
          kinds: ["Pod"]
    validate:
      message: "Privileged containers are not allowed."
      pattern:
        spec:
          containers:
          - securityContext:
              privileged: "false"
  - name: require-run-as-non-root
    match:
      any:
      - resources:
          kinds: ["Pod"]
    validate:
      message: "Containers must run as non-root."
      pattern:
        spec:
          securityContext:
            runAsNonRoot: true

Liste de Contrôle d'Atténuation

5�E�⃣ K05 - Contrôles de Segmentation Réseau Manquants

High

Vue d'ensemble

Par défaut, tous les pods d'un cluster Kubernetes peuvent communiquer entre eux sans aucune restriction. Cette architecture réseau plate signifie qu'un pod compromis peut atteindre n'importe quel autre pod, service, ou même le serveur API Kubernetes. Les NetworkPolicies sont essentielles pour mettre en œuvre la micro-segmentation.

Risque

Sans segmentation réseau, les déplacements latéraux sont triviaux. Un pod frontend compromis peut accéder directement aux bases de données backend, aux services internes et à l'API de métadonnées (169.254.169.254). Cela viole le principe du moindre privilège au niveau de la couche réseau.

Exemple de Code Vulnérable

YAML (Kubernetes) ❁EBad
# No NetworkPolicy  Eall pods can communicate freely
apiVersion: v1
kind: Namespace
metadata:
  name: production
  # No default deny policy
  # No network policies at all
  # Any pod can reach:
  #   - Other pods in any namespace
  #   - Kubernetes API server
  #   - Cloud metadata API (169.254.169.254)
  #   - External internet

Exemple de Code Sécurisé

YAML (Kubernetes NetworkPolicy) ✁EGood
# Default deny all ingress and egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes: ["Ingress", "Egress"]
---
# Allow only frontend to backend communication
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes: ["Ingress"]
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - port: 8080
      protocol: TCP

Liste de Contrôle d'Atténuation

6�E�⃣ K06 - Composants Kubernetes Trop Exposés

High

Vue d'ensemble

Les composants du plan de contrôle Kubernetes (serveur API, etcd, kubelet, tableau de bord) et les services applicatifs peuvent être exposés par inadvertance à Internet ou à des réseaux non fiables. Les tableaux de bord exposés, les kubelets non authentifiés et les serveurs API accessibles publiquement sont des vecteurs d'attaque courants.

Risque

Les composants Kubernetes exposés fournissent un accès direct à la gestion du cluster. Une API kubelet non authentifiée permet l'exécution de conteneurs. Un tableau de bord exposé avec des identifiants par défaut accorde un accès cluster-admin. L'accès public à etcd expose toutes les données du cluster, y compris les secrets.

Exemple de Code Vulnérable

YAML (Kubernetes Service) ❁EBad
# Kubernetes Dashboard exposed via LoadBalancer
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: LoadBalancer        # Public internet access!
  ports:
  - port: 443
    targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard
# Dashboard bound to cluster-admin service account
# No authentication required  Efull cluster access!

Exemple de Code Sécurisé

YAML (Kubernetes) ✁EGood
# Dashboard accessible only via kubectl proxy
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  type: ClusterIP           # Internal only
  ports:
  - port: 443
    targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard
---
# Access via: kubectl proxy, then browse to:
# http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
# Or use kubectl port-forward for secure access

Liste de Contrôle d'Atténuation

7�E�⃣ K07 - Composants de Cluster Mal Configurés et Vulnérables

High

Vue d'ensemble

Les clusters Kubernetes sont constitués de nombreux composants : serveur API, etcd, kubelet, kube-proxy, CoreDNS et modules complémentaires tiers (contrôleurs Ingress, maillages de services, surveillance). Les composants mal configurés ou non corrigés introduisent des vulnérabilités. Les configurations par défaut ne sont souvent pas renforcées.

Risque

Les composants de cluster vulnérables peuvent être exploités pour l'exécution de code à distance, l'escalade de privilèges ou le déni de service. Les CVE dans kubelet, les contrôleurs Ingress ou les plugins CNI peuvent conduire à des échappements de conteneurs et à la prise de contrôle du cluster. Les composants obsolètes accumulent des vulnérabilités connues.

Exemple de Code Vulnérable

YAML (Kubernetes) ❁EBad
# kubelet with insecure configuration
# /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
  anonymous:
    enabled: true              # Anyone can access kubelet API!
  webhook:
    enabled: false             # No authorization!
authorization:
  mode: AlwaysAllow            # All requests permitted!
readOnlyPort: 10255            # Unauthenticated read port open!

Exemple de Code Sécurisé

YAML (Kubernetes) ✁EGood
# Hardened kubelet configuration
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
  anonymous:
    enabled: false             # Deny anonymous access
  webhook:
    enabled: true              # Use API server for auth
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
  mode: Webhook                # API server authorizes requests
readOnlyPort: 0                # Disable read-only port
protectKernelDefaults: true
eventRecordQPS: 5

Liste de Contrôle d'Atténuation

8�E�⃣ K08 - Mouvement Latéral du Cluster vers le Cloud

Critical

Vue d'ensemble

Les clusters Kubernetes exécutés dans des environnements cloud (AWS, GCP, Azure) peuvent accéder aux API de métadonnées cloud et aux rôles IAM attachés aux nœuds. Les attaquants qui compromettent un pod peuvent les utiliser pour escalader les privilèges du cluster vers le compte cloud, accédant aux buckets S3, aux bases de données et à d'autres services cloud.

Risque

Les rôles IAM au niveau des nœuds sont hérités par tous les pods sur ce nœud. Un pod compromis peut interroger l'API de métadonnées (169.254.169.254) pour obtenir des identifiants cloud, puis accéder à toute ressource cloud autorisée par le rôle du nœud. Cela permet un mouvement latéral de Kubernetes vers l'environnement cloud plus large.

Exemple de Code Vulnérable

Terraform (AWS EKS) ❁EBad
# Node IAM role with excessive permissions
resource "aws_iam_role_policy_attachment" "node_admin" {
  role       = aws_iam_role.node_role.name
  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
  # All pods on this node inherit admin access!
}

# No IMDS restrictions  Eany pod can get node credentials
# curl http://169.254.169.254/latest/meta-data/iam/security-credentials/

Exemple de Code Sécurisé

Terraform (AWS EKS with IRSA) ✁EGood
# Use IAM Roles for Service Accounts (IRSA)
resource "aws_iam_role" "app_role" {
  name = "my-app-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = {
        Federated = aws_iam_openid_connect_provider.eks.arn
      }
      Action = "sts:AssumeRoleWithWebIdentity"
      Condition = {
        StringEquals = {
          "${aws_iam_openid_connect_provider.eks.url}:sub" =
            "system:serviceaccount:my-ns:my-app"
        }
      }
    }]
  })
}

# Pod-level scoped IAM via service account annotation
# Only this specific pod gets these specific permissions

Liste de Contrôle d'Atténuation

9�E�⃣ K09 - Mécanismes d'Authentification Défaillants

Critical

Vue d'ensemble

Kubernetes prend en charge plusieurs mécanismes d'authentification : certificats, jetons, OIDC et authentification par webhook. L'authentification défaillante inclut l'utilisation de jetons statiques, le partage de fichiers kubeconfig, la non-rotation des certificats et l'échec d'intégration avec les fournisseurs d'identité. Le montage automatique de jetons de compte de service crée une surface d'attaque inutile.

Risque

Les fichiers kubeconfig et les jetons de compte de service volés ou divulgués fournissent un accès direct au cluster. Les jetons statiques qui n'expirent jamais donnent un accès persistant. Sans gestion centralisée des identités, révoquer l'accès des membres d'équipe partis est difficile et sujet aux erreurs.

Exemple de Code Vulnérable

YAML (Kubernetes) ❁EBad
# Static token file for API server authentication
# /etc/kubernetes/token-auth-file.csv
# token,user,uid,"groups"
# abc123,admin,1,"system:masters"  # Static token, never expires!

# Pod with auto-mounted service account token
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  # automountServiceAccountToken defaults to true!
  # Token mounted at /var/run/secrets/kubernetes.io/serviceaccount/token
  containers:
  - name: app
    image: myapp:latest
    # App doesn't need K8s API access but has a token anyway

Exemple de Code Sécurisé

YAML (Kubernetes) ✁EGood
# Disable auto-mounted token for pods that don't need API access
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
  namespace: my-app-ns
automountServiceAccountToken: false  # No auto-mount
---
# For pods that need API access, use bound tokens with expiry
apiVersion: v1
kind: Pod
metadata:
  name: api-consumer
spec:
  serviceAccountName: api-consumer-sa
  automountServiceAccountToken: false
  containers:
  - name: app
    image: myapp@sha256:abc123...
    volumeMounts:
    - name: token
      mountPath: /var/run/secrets/tokens
      readOnly: true
  volumes:
  - name: token
    projected:
      sources:
      - serviceAccountToken:
          expirationSeconds: 3600  # 1-hour expiry
          audience: api-server

Liste de Contrôle d'Atténuation

🔟 K10 - Journalisation et Surveillance Inadéquates

Medium

Vue d'ensemble

Kubernetes génère des événements d'audit pour les requêtes du serveur API, mais la journalisation d'audit est souvent désactivée ou mal configurée. Sans journalisation et surveillance appropriées, les activités malveillantes  Etelles que l'accès non autorisé aux secrets, les modifications RBAC et les échappements de conteneurs  Epassent inaperçues. La surveillance de sécurité en temps d'exécution au niveau du conteneur et du nœud est essentielle.

Risque

Sans journalisation d'audit, les attaquants opèrent sans être détectés. Ils peuvent créer des comptes de service de porte dérobée, extraire des secrets et modifier des charges de travail sans aucune trace. La réponse aux incidents est sévèrement entravée lorsqu'il n'y a aucune piste d'audit pour déterminer ce qui s'est passé, quand et par qui.

Exemple de Code Vulnérable

YAML (Kubernetes) ❁EBad
# API server with no audit logging configured
# kube-apiserver flags:
#   --audit-log-path=""           # No audit log!
#   --audit-policy-file=""        # No audit policy!

# No runtime security monitoring
# No alerting on suspicious activities
# Container logs not collected centrally
# Default log retention  Elogs lost on pod restart

Exemple de Code Sécurisé

YAML (Kubernetes Audit Policy) ✁EGood
# Comprehensive audit policy
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Log all secret access at Metadata level
- level: Metadata
  resources:
  - group: ""
    resources: ["secrets"]
# Log RBAC changes at RequestResponse level
- level: RequestResponse
  resources:
  - group: rbac.authorization.k8s.io
    resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"]
# Log pod exec/attach (potential attacks)
- level: Request
  resources:
  - group: ""
    resources: ["pods/exec", "pods/attach", "pods/portforward"]
# Default: log at Metadata level
- level: Metadata

Liste de Contrôle d'Atténuation

📊 Tableau Récapitulatif

ID Vulnérabilité Sévérité Atténuation Clé
K01Configurations de Charges de Travail Non SécuriséesCriticalNon-root, FS lecture seule, suppression des capacités, limites de ressources
K02Autorisation Trop PermissiveCriticalRBAC à portée d'espace de noms, pas de génériques, audit des liaisons
K03Échecs de Gestion des SecretsCriticalSecrets externes, chiffrement au repos, montages de fichiers
K04Manque d'Application de PolitiquesHighPod Security Standards, Kyverno/OPA Gatekeeper
K05Segmentation Réseau ManquanteHighNetworkPolicies par défaut refusant tout, micro-segmentation
K06Composants Trop ExposésHighServices ClusterIP, kubectl proxy, règles de pare-feu
K07Composants de Cluster Mal ConfigurésHighCIS Benchmark, désactiver l'authentification anonyme, gestion des correctifs
K08Mouvement Latéral du Cluster vers le CloudCriticalIRSA/Workload Identity, bloquer l'API de métadonnées, IMDSv2
K09Mécanismes d'Authentification DéfaillantsCriticalIntégration OIDC, jetons liés, désactiver le montage automatique
K10Journalisation et Surveillance InadéquatesMediumJournalisation d'audit, Falco/Tetragon, intégration SIEM