Limiter les incidents de sécurité


Ce document décrit les mesures d'atténuation et les solutions courantes à appliquer en cas d'incidents de sécurité potentiels affectant vos clusters et conteneurs Google Kubernetes Engine (GKE).

Les suggestions de la section Renforcer la sécurité du cluster peuvent améliorer la sécurité de vos charges de travail GKE. Toutefois, des incidents de sécurité peuvent se produire même lorsque des mesures de protection de vos charges de travail sont en place.

Détecter les incidents

Pour détecter les incidents potentiels, nous vous recommandons de configurer un processus qui collecte et surveille les journaux de vos charges de travail. Configurez ensuite des alertes en fonction des événements anormaux détectés dans les journaux. Les alertes informent votre équipe de sécurité lorsqu'un événement inhabituel est détecté. Votre équipe en charge de la sécurité peut alors examiner l'incident potentiel.

Générer des alertes à partir des journaux

Vous pouvez personnaliser les alertes en fonction de métriques ou d'actions spécifiques. Par exemple, une alerte d'utilisation élevée du processeur sur vos nœuds GKE peut indiquer que ceux-ci sont exploités pour miner de la cryptomonnaie.

Les alertes doivent être générées là où vous regroupez vos journaux et vos métriques. Par exemple, vous pouvez utiliser les journaux d'audit GKE avec les alertes basées sur les journaux dans Cloud Logging.

Pour en savoir plus sur les requêtes liées à la sécurité, consultez la documentation sur Audit Logging.

Répondre à un incident de sécurité

Après avoir été informé d'un incident, prenez les mesures nécessaires. Si possible, corrigez la faille. Si vous ne connaissez pas l'origine de la faille ou si vous ne disposez pas de correctif, appliquez des mesures d'atténuation.

Les mesures d'atténuation possibles dépendent de la gravité de l'incident et varient selon que vous êtes sûr ou pas d'avoir identifié le problème.

Ce guide décrit les actions que vous pouvez entreprendre après avoir détecté un incident sur une charge de travail exécutée sur GKE. Vous pouvez appliquer les mesures suivantes, selon une échelle croissante de gravité :

  • Prendre un Instantané du disque de la VM hôte. Un instantané vous permet d'effectuer des analyses forensiques de l'état de la VM au moment de l'anomalie, après que la charge de travail a été redéployée ou supprimée.
  • Inspecter la VM pendant que la charge de travail s'exécute. En vous connectant à la VM hôte ou au conteneur de la charge de travail, vous pouvez obtenir des informations sur les agissements du pirate. Nous vous recommandons de limiter les accès avant d'inspecter la VM en cours d'exécution.

  • Redéployer un conteneur. Le redéploiement du conteneur concerné termine les processus qui s'y exécutent, puis les redémarre.

  • Supprimer une charge de travail. La suppression de la charge de travail termine les processus en cours d'exécution dans le conteneur concerné, et ne les redémarre pas.

Ces mesures d'atténuation sont décrites dans les sections suivantes.

Avant de commencer

Les méthodes utilisées dans cette section s'appuient sur les éléments ci-dessous :

  • Les noms des pods qui, selon vous, ont été piratés, ou POD_NAME
  • Le nom de la VM hôte qui exécute le conteneur ou les pods, ou NODE_NAME

Avant d'intervenir, évaluez le risque de réaction négative du pirate s'il se sait découvert. Il pourrait décider d'effacer les données ou de supprimer les charges de travail. Si le risque est trop élevé, envisagez des solutions plus radicales, comme supprimer une charge de travail, avant de chercher à en savoir plus.

Prendre un instantané du disque de la VM

Créer un instantané du disque de la VM permet d'effectuer une analyse forensique après que la charge de travail a été redéployée ou supprimée. Les instantanés peuvent être créés alors que des disques sont joints à des instances en cours d'exécution.

  1. Pour prendre un instantané de votre disque persistant, localisez d'abord les disques joints à votre VM. Exécutez la commande suivante et examinez le champ source :

    gcloud compute instances describe NODE_NAME --zone COMPUTE_ZONE \
        --format="flattened([disks])"
    
  2. Recherchez les lignes contenant disks[NUMBER].source. Le résultat ressemble à ce qui suit :

    disks[0].source: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/zones/COMPUTE_ZONE/disks/DISK_NAME
    

    Le nom du disque correspond à la section du nom de la source après la barre oblique finale. Par exemple, le nom du disque est gke-cluster-pool-1-abcdeffff-zgt8.

  3. Pour effectuer l'instantané, exécutez la commande suivante :

    gcloud compute disks snapshot DISK_NAME
    

Pour plus d'informations, consultez la section Créer des instantanés de disques persistants dans la documentation de Compute Engine.

Inspecter la VM pendant que la charge de travail continue de s'exécuter

Avant d'agir, pensez également aux divers moyens d'accès dont un pirate peut disposer. Si vous pensez qu'un conteneur est compromis et voulez éviter d'alerter le pirate, vous pouvez vous connecter au conteneur afin de l'inspecter. L'inspection permet d'effectuer une investigation rapide avant de prendre des mesures plus radicales. Cette l'approche est aussi la moins perturbatrice pour la charge de travail, mais elle ne permet pas de mettre fin à l'incident.

De même, pour éviter de vous connecter à une machine avec un identifiant d'accès privilégié, vous pouvez configurer une analyse forensique à chaud (comme GRR Rapid Response), des agents sur le nœud ou un filtrage du réseau.

Limiter les accès avant d'inspecter la VM en cours d'exécution

Afin d'isoler partiellement le conteneur compromis du reste de votre cluster, vous pouvez périmétrer et vider la VM qui l'héberge, et en limiter l'accès réseau. Limiter l'accès à la VM réduit les risques, mais n'empêche pas un pirate informatique de se déplacer latéralement dans votre environnement s'il exploite une faille critique.

Confiner le nœud et le vider des autres charges de travail

Le fait de périmétrer et vider le nœud permet de déplacer les charges de travail cohabitant avec le conteneur compromis vers d'autres VM de votre cluster. Cette méthode réduit la capacité d'un pirate à affecter les autres charges de travail sur le même nœud. Cela ne l'empêche pas nécessairement d'inspecter l'état persistant d'une charge de travail (par exemple, en examinant le contenu de l'image du conteneur).

  1. Utilisez la commande kubectl pour périmétrer le nœud et vérifier qu'aucun autre pod n'est programmé sur celui-ci :

    kubectl cordon NODE_NAME
    

    Une fois le nœud périmétré, videz le nœud des autres pods.

  2. Étiquetez le pod que vous mettez en quarantaine :

    kubectl label pods POD_NAME quarantine=true
    

    Remplacez POD_NAME par le nom du pod que vous souhaitez placer en quarantaine.

  3. Videz le nœud des pods qui ne portent pas l'indication quarantine :

    kubectl drain NODE_NAME --pod-selector='!quarantine'
    

Limiter l'accès réseau au nœud

Nous vous recommandons d'empêcher que le trafic interne et externe accède à la VM hôte. Ensuite, autorisez les connexions entrantes provenant d'une VM spécifique de votre réseau ou de votre VPC à se connecter à la VM en quarantaine.

La première étape consiste à abandonner la VM à l'intérieur du groupe d'instances géré dont elle fait partie. Abandonner la VM permet d'éviter que le nœud soit marqué comme non sain et réparé automatiquement (recréé) avant que l'investigation soit terminée.

Pour abandonner la VM, exécutez la commande suivante :

gcloud compute instance-groups managed abandon-instances INSTANCE_GROUP_NAME \
    --instances=NODE_NAME

Mettre en place un pare-feu sur la VM

En créant un pare-feu entre le conteneur concerné et les autres charges de travail du même réseau, vous empêchez qu'un pirate informatique se déplace dans d'autres parties de votre environnement pendant que vous poursuivez votre analyse. Puisque vous avez déjà vidé la VM de ses autres conteneurs, seul celui en quarantaine est concerné.

En protégeant la VM selon les instructions suivantes, vous empêchez :

  • de nouvelles connexions sortantes vers d'autres VM de votre cluster à l'aide d'une règle de sortie ;
  • les connexions entrantes vers la VM compromise à l'aide d'une règle d'entrée.

Pour configurer un pare-feu entre la VM et vos autres instances, procédez comme suit pour le nœud qui héberge le pod que vous souhaitez mettre en quarantaine :

  1. Ajoutez un tag à l'instance afin de pouvoir appliquer une nouvelle règle de pare-feu.

    gcloud compute instances add-tags NODE_NAME \
        --zone COMPUTE_ZONE \
        --tags quarantine
    
  2. Créez une règle de pare-feu pour refuser la totalité du trafic TCP sortant depuis les instances comportant le tag quarantine :

    gcloud compute firewall-rules create quarantine-egress-deny \
        --network NETWORK_NAME \
        --action deny \
        --direction egress \
        --rules tcp \
        --destination-ranges 0.0.0.0/0 \
        --priority 0 \
        --target-tags quarantine
    
  3. Créez une règle de pare-feu pour refuser la totalité du trafic TCP entrant vers les instances comportant le tag quarantine. Attribuez à cette règle d'entrée une priority de 1. Vous pourrez ainsi la remplacer par une autre règle autorisant la connexion SSH à partir d'une VM spécifiée.

    gcloud compute firewall-rules create quarantine-ingress-deny \
        --network NETWORK_NAME \
        --action deny \
        --direction ingress \
        --rules tcp \
        --source-ranges 0.0.0.0/0 \
        --priority 1 \
        --target-tags quarantine
    

Supprimer l'adresse IP externe de la VM

En supprimant l'adresse IP externe de la VM, vous interrompez toutes les connexions réseau existantes en dehors de votre VPC.

Pour supprimer l'adresse externe d'une VM, procédez comme suit :

  1. Recherchez et supprimez la configuration d'accès qui associe l'adresse IP externe à la VM. Commencez par rechercher la configuration d'accès en décrivant la VM :

    gcloud compute instances describe NODE_NAME \
        --zone COMPUTE_ZONE --format="flattened([networkInterfaces])"
    

    Recherchez les lignes contenant name et natIP. Ces lignes se présentent comme ceci :

    networkInterfaces[0].accessConfigs[0].name:              ACCESS_CONFIG_NAME
    networkInterfaces[0].accessConfigs[0].natIP:             EXTERNAL_IP_ADDRESS
    
  2. Recherchez la valeur de natIP correspondant à l'adresse IP externe que vous souhaitez supprimer. Notez le nom de la configuration d'accès.

  3. Pour supprimer l'adresse IP externe, exécutez la commande suivante :

    gcloud compute instances delete-access-config NODE_NAME \
        --access-config-name "ACCESS_CONFIG_NAME"
    

Connexion SSH vers la VM hôte via une VM intermédiaire

Une fois que vous avez supprimé l'adresse IP externe de la VM hôte, vous ne pouvez pas utiliser SSH en dehors de votre VPC. Vous y accédez depuis une autre VM du même réseau. Celle-ci sera dénommée VM intermédiaire dans le reste de cette section.

Prérequis

  • VM intermédiaire avec accès au sous-réseau de la VM hôte. Si vous n'en avez pas encore, créez une VM à cette fin.
  • Adresse IP interne de la VM intermédiaire.
  • Clé publique SSH de la VM intermédiaire. Pour en savoir plus, reportez-vous à la section Gérer des clés SSH

Se connecter à la VM hôte

  1. Ajoutez la clé publique de la VM intermédiaire à la VM hôte. Pour plus d'informations, consultez la section Ajouter et supprimer des clés SSH dans la documentation de Compute Engine.
  2. Ajoutez un tag à la VM intermédiaire.

    gcloud compute instances add-tags INTERMEDIATE_NODE_NAME \
      --zone COMPUTE_ZONE \
      --tags intermediate
    
  3. Ajoutez une règle d'autorisation d'entrée pour remplacer la règle de refus que vous avez ajoutée précédemment. Pour ajouter la règle, exécutez la commande suivante :

    gcloud compute firewall-rules create quarantine-ingress-allow \
        --network NETWORK_NAME \
        --action allow \
        --direction ingress \
        --rules tcp:22 \
        --source-tags intermediate \
        --priority 0 \
        --target-tags quarantine
    

    Cette règle autorise le trafic entrant sur le port 22 (SSH) depuis les VM de votre réseau comportant le tag intermediate. Elle remplace la règle de refus, avec une priority de 0.

  4. Connectez-vous à la VM en quarantaine via son adresse IP interne :

    ssh -i KEY_PATH USER@QUARANTINED_VM_INTERNAL_IP
    

    Remplacez l'élément suivant :

    • KEY_PATH : chemin d'accès à votre clé privée SSH.
    • USER : adresse e-mail de votre compte Google Cloud.
    • QUARANTINED_VM_INTERNAL_IP : adresse IP interne.

Redéployer un conteneur

Lors d'un redéploiement, le conteneur compromis est supprimé, et une copie toute neuve le remplace.

Pour redéployer un conteneur, vous devez supprimer le pod qui l'héberge. Si le pod est géré par une construction Kubernetes de niveau supérieur (par exemple, un déploiement ou un DaemonSet) et qu'il est supprimé, un nouveau pod est programmé. Ce pod exécute de nouveaux conteneurs.

Le redéploiement est utile dans les cas suivants :

  • Vous connaissez déjà la cause de cette faille.
  • Vous pensez qu'il faudra beaucoup de temps ou d'efforts à un pirate informatique pour compromettre à nouveau votre conteneur.
  • Vous pensez que le conteneur peut rapidement être compromis à nouveau et vous ne souhaitez pas le déconnecter. Vous prévoyez donc de le placer dans un bac à sable pour limiter l'impact.

Lors du redéploiement de la charge de travail, en cas de forte probabilité d'un autre piratage, envisagez de placer la charge de travail dans un environnement de bac à sable tel que GKE Sandbox. Le mode bac à sable limite l'accès au kernel du nœud hôte dans le cas où le pirate informatique parvient à nouveau à lancer une attaque sur le conteneur.

Pour redéployer un conteneur dans Kubernetes, supprimez le pod qui le contient :

kubectl delete pods POD_NAME --grace-period=10

Si les conteneurs du pod supprimé continuent de s'exécuter, vous pouvez supprimer la charge de travail.

Pour redéployer le conteneur dans un bac à sable, suivez les instructions de la section Renforcer l'isolation d'une charge de travail avec GKE Sandbox.

Supprimer une charge de travail

La suppression d'une charge de travail, telle qu'un déploiement ou un DaemonSet, entraîne la suppression de tous les pods associés. Tous les conteneurs de ces pods cessent de fonctionner. Supprimer une charge de travail peut être utile dans les cas suivants :

  • Vous voulez arrêter une attaque en cours.
  • Vous êtes prêt à placer la charge de travail hors connexion.
  • La priorité est de stopper immédiatement l'attaque, et la disponibilité des applications ou l'analyse forensique passent après.

Pour supprimer une charge de travail, utilisez la commande kubectl delete CONTROLLER_TYPE. Par exemple, pour supprimer un déploiement, exécutez la commande suivante :

kubectl delete deployments DEPLOYMENT

Si la suppression de la charge de travail ne supprime pas tous les pods ou conteneurs associés, vous pouvez supprimer manuellement chaque conteneur à l'aide de l'outil CLI de son environnement d'exécution, généralement docker. Si vos nœuds exécutent containerd, utilisez crictl.

Docker

Pour arrêter un conteneur à l'aide de l'environnement d'exécution de conteneur Docker, vous pouvez utiliser docker stop ou docker kill.

docker stop arrête le conteneur en envoyant un signal SIGTERM au processus racine et attend, par défaut, 10 secondes que le processus se termine. Si le processus n'a pas été interrompu pendant ce laps de temps, il envoie un signal SIGKILL. L'option --time permet de spécifier ce délai.

docker stop --time TIME_IN_SECONDS CONTAINER

docker kill est la méthode la plus rapide pour arrêter un conteneur. Le signal SIGKILL est envoyé immédiatement.

docker kill CONTAINER

La commande docker rm -f permet également d'arrêter et de supprimer un conteneur en une seule opération :

docker rm -f CONTAINER

containerd

Si vous utilisez l'environnement d'exécution containerd dans GKE, vous devez utiliser la commande crictl pour arrêter ou supprimer des conteneurs.

Pour arrêter un conteneur dans containerd, exécutez la commande suivante :

crictl stop CONTAINER

Pour supprimer un conteneur dans containerd, exécutez la commande suivante :

crictl rm -f CONTAINER

Supprimer la VM hôte

Si vous ne parvenez pas à arrêter ou supprimer le conteneur, vous pouvez supprimer la machine virtuelle qui l'héberge.

Si le pod est toujours visible, exécutez la commande suivante pour identifier le nom de la VM hôte :

kubectl get pods --all-namespaces \
  -o=custom-columns=POD_NAME:.metadata.name,INSTANCE_NAME:.spec.nodeName \
  --field-selector=metadata.name=POD_NAME

Pour supprimer la VM hôte, exécutez la commande gcloud suivante :

gcloud compute instance-groups managed delete-instances INSTANCE_GROUP_NAME \
    --instances=NODE_NAME

L'abandon de l'instance à l'intérieur du groupe d'instances géré réduit la taille du groupe d'une VM. Vous pouvez rétablir manuellement une instance dans le groupe à l'aide de la commande suivante :

gcloud compute instance-groups managed resize INSTANCE_GROUP_NAME \
    --size=SIZE

Étape suivante