Mitigare gli incidenti di sicurezza

Questo documento descrive le mitigazioni e le risposte comuni ai potenziali incidenti di sicurezza nei cluster e nei container Google Kubernetes Engine (GKE).

Questo documento è destinato a specialisti della sicurezza che cercano indicazioni per rispondere agli incidenti di sicurezza di GKE. Per scoprire di più sui ruoli comuni e sulle attività di esempio a cui facciamo riferimento nei contenuti di Google Cloud , consulta Ruoli e attività comuni degli utenti GKE.

I suggerimenti in Rafforzamento della sicurezza del cluster possono migliorare la sicurezza dei workload GKE. Tuttavia, gli incidenti di sicurezza possono verificarsi anche quando sono in atto misure per proteggere i tuoi carichi di lavoro.

Rilevare gli incidenti

Per rilevare potenziali incidenti, ti consigliamo di configurare un processo che raccolga e monitori i log del tuo workload. Quindi, configura gli avvisi in base agli eventi anomali rilevati dai log. Gli avvisi notificano al tuo team di sicurezza quando viene rilevato qualcosa di insolito. Il tuo team di sicurezza può quindi esaminare il potenziale incidente.

Puoi personalizzare gli avvisi in base a metriche o azioni specifiche. Ad esempio, un avviso sull'utilizzo elevato della CPU sui nodi GKE potrebbe indicare che sono stati compromessi per il cryptomining.

Gli avvisi devono essere generati nel punto in cui aggreghi log e metriche. Ad esempio, puoi utilizzare Audit Logging di GKE in combinazione con gli avvisi basati sui log in Cloud Logging.

Per saperne di più sulle query pertinenti alla sicurezza, consulta la documentazione relativa al logging di controllo.

Rispondere a un incidente di sicurezza

Dopo aver ricevuto una notifica relativa a un incidente, passa all'azione. Correggi la vulnerabilità, se puoi. Se non conosci la causa principale della vulnerabilità o non hai una correzione pronta, applica le mitigazioni.

Le misure di mitigazione che potresti adottare dipendono dalla gravità dell'incidente e dalla certezza di aver identificato il problema.

Questa guida illustra le azioni che puoi intraprendere dopo aver rilevato un incidente su un carico di lavoro in esecuzione su GKE. Potresti, in ordine crescente di gravità:

Queste mitigazioni sono descritte nelle sezioni seguenti.

Prima di iniziare

I metodi utilizzati in questo argomento utilizzano le seguenti informazioni:

  • Il nome dei Pod che ritieni siano stati compromessi o POD_NAME.
  • Il nome della VM host che esegue il container o i pod oppure NODE_NAME.

Inoltre, prima di intraprendere una qualsiasi azione, valuta se ci sarà una reazione negativa da parte dell'aggressore se viene scoperto. L'autore dell'attacco potrebbe decidere di eliminare i dati o distruggere i workload. Se il rischio è troppo elevato, valuta mitigazioni più drastiche, come l'eliminazione di un workload prima di eseguire ulteriori indagini.

Crea lo snapshot del disco della VM

La creazione di uno snapshot del disco della VM consente l'indagine forense dopo che è stato eseguito il deployment o l'eliminazione del workload. Gli snapshot possono essere creati mentre i dischi sono collegati a istanze in esecuzione.

  1. Per creare uno snapshot del disco permanente, individua innanzitutto i dischi collegati alla VM. Esegui questo comando e guarda il campo source:

    gcloud compute instances describe NODE_NAME --zone COMPUTE_ZONE \
        --format="flattened([disks])"
    
  2. Cerca le righe che contengono disks[NUMBER].source. L'output è simile al seguente:

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

    Il nome del disco è la parte del nome dell'origine dopo l'ultima barra. Ad esempio, il nome del disco è gke-cluster-pool-1-abcdeffff-zgt8.

  3. Per completare lo snapshot, esegui questo comando:

    gcloud compute disks snapshot DISK_NAME
    

Per saperne di più, consulta la sezione Creazione di disco permanente Disk nella documentazione di Compute Engine.

Controlla la VM

Prima di intraprendere qualsiasi azione, valuta l'accesso che potrebbe avere un malintenzionato. Se sospetti che un container sia stato compromesso e temi di informare l'utente malintenzionato, puoi connetterti al container e ispezionarlo senza interrompere i carichi di lavoro. L'ispezione è utile per un'indagine rapida prima di intraprendere azioni più distruttive. L'ispezione è anche l'approccio meno disruptive al carico di lavoro, ma non interrompe l'incidente.

In alternativa, per evitare di accedere a una macchina con una credenziale privilegiata, puoi analizzare i tuoi workload configurando l'analisi forense live (ad esempio GRR Rapid Response), agenti on-node o il filtro di rete.

Riduci l'accesso prima di ispezionare la VM attiva

Isolando, svuotando e limitando l'accesso alla rete alla VM che ospita un container compromesso, puoi isolare parzialmente il container compromesso dal resto del cluster. Limitare l'accesso alla VM riduce il rischio, ma non impedisce a un utente malintenzionato di spostarsi lateralmente nel tuo ambiente se sfrutta una vulnerabilità critica.

Isola il nodo e svuota gli altri workload

L'isolamento e lo svuotamento di un nodo sposta i carichi di lavoro collocati insieme al container compromesso in altre VM del cluster. L'isolamento e lo svuotamento riducono la capacità di un malintenzionato di influire su altri workload sullo stesso nodo. Non impedisce necessariamente di ispezionare lo stato persistente di un workload (ad esempio, ispezionando i contenuti dell'immagine container).

  1. Utilizza kubectl per isolare il nodo e assicurarti che non vengano pianificati altri pod:

    kubectl cordon NODE_NAME
    

    Dopo aver isolato il nodo, svuotalo dagli altri pod.

  2. Etichetta il pod che stai mettendo in quarantena:

    kubectl label pods POD_NAME quarantine=true
    

    Sostituisci POD_NAME con il nome del pod che vuoi mettere in quarantena.

  3. Svuota il nodo dei pod che non sono etichettati con quarantine:

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

Limitare l'accesso di rete al nodo

Consigliamo di bloccare l'accesso alla VM host per il traffico interno ed esterno. Successivamente, consenti le connessioni in entrata da una VM specifica sulla tua rete o VPC per connettersi alla VM in quarantena.

Il primo passaggio consiste nell'abbandonare la VM dal gruppo di istanze gestite che la possiede. L'interruzione della VM impedisce che il nodo venga contrassegnato come non integro e riparato automaticamente (ricreato) prima del completamento dell'indagine.

Per abbandonare la VM, esegui questo comando:

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

Firewall della VM

La creazione di un firewall tra il container interessato e altri carichi di lavoro nella stessa rete aiuta a impedire a un malintenzionato di spostarsi in altre parti del tuo ambiente mentre conduci ulteriori analisi. Poiché hai già svuotato la VM di altri container, questa operazione influisce solo sul container messo in quarantena.

Le seguenti istruzioni sul firewalling della VM impediscono:

  • Nuove connessioni in uscita ad altre VM nel cluster utilizzando una regola di uscita.
  • Connessioni in entrata alla VM compromessa utilizzando una regola in entrata.

Per proteggere la VM dalle altre istanze con un firewall, segui questi passaggi per il nodo che ospita il pod che vuoi mettere in quarantena:

  1. Tagga l'istanza in modo da poter applicare una nuova regola firewall.

    gcloud compute instances add-tags NODE_NAME \
        --zone COMPUTE_ZONE \
        --tags quarantine
    
  2. Crea una regola firewall per negare tutto il traffico TCP in uscita dalle istanze con il 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. Crea una regola firewall per negare tutto il traffico TCP in entrata alle istanze con il tag quarantine. Assegna a questa regola in entrata una priorità priority di 1, che ti consente di sostituirla con un'altra regola che consente SSH da una VM specificata.

    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
    

Rimuovi l'indirizzo IP esterno della VM

La rimozione dell'indirizzo IP esterno della VM interrompe tutte le connessioni di rete esistenti all'esterno del VPC.

Per rimuovere l'indirizzo esterno di una VM:

  1. Individua ed elimina la configurazione di accesso che associa l'IP esterno alla VM. Innanzitutto, trova la configurazione di accesso descrivendo la VM:

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

    Cerca le righe che contengono name e natIP. Hanno un aspetto simile a questo:

    networkInterfaces[0].accessConfigs[0].name:              ACCESS_CONFIG_NAME
    networkInterfaces[0].accessConfigs[0].natIP:             EXTERNAL_IP_ADDRESS
    
  2. Trova il valore di natIP corrispondente all'IP esterno che vuoi rimuovere. Prendi nota del nome della configurazione di accesso.

  3. Per rimuovere l'IP esterno, esegui questo comando:

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

Accedere tramite SSH alla VM host tramite una VM intermedia

Dopo aver rimosso l'IP esterno della VM host, non puoi connetterti tramite SSH dall'esterno del tuo VPC. Vi accedi da un'altra VM nella stessa rete. Nel resto di questa sezione, faremo riferimento a questa VM come VM intermedia.

Prerequisiti

  • Una VM intermedia con accesso alla subnet della VM host. Se non ne hai già una, crea una VM a questo scopo.
  • L'indirizzo IP interno della VM intermedia.
  • Una chiave pubblica SSH della VM intermedia. Per saperne di più, vedi Gestione delle chiavi SSH

Connessione alla VM host

  1. Aggiungi la chiave pubblica della VM intermedia alla VM host. Per saperne di più, consulta Aggiunta e rimozione delle chiavi SSH nella documentazione di Compute Engine.
  2. Aggiungi un tag alla VM intermedia.

    gcloud compute instances add-tags INTERMEDIATE_NODE_NAME \
      --zone COMPUTE_ZONE \
      --tags intermediate
    
  3. Aggiungi una regola di autorizzazione in entrata per eseguire l'override della regola di negazione aggiunta in precedenza. Per aggiungere la regola, esegui questo comando.

    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
    

    Questa regola consente il traffico in entrata sulla porta 22 (SSH) dalle VM nella tua rete con il tag intermediate. Esegue l'override della regola di negazione con un priority di 0.

  4. Connettiti alla VM in quarantena utilizzando il suo IP interno:

    ssh -i KEY_PATH USER@QUARANTINED_VM_INTERNAL_IP
    

    Sostituisci quanto segue:

    • KEY_PATH: il percorso della chiave privata SSH.
    • USER: l'indirizzo email del tuo account Google Cloud .
    • QUARANTINED_VM_INTERNAL_IP: l'indirizzo IP interno.

Rifai il deployment di un container

Rifacendo il deployment del container, avvii una nuova copia del container ed elimini il container compromesso.

Per eseguire nuovamente il deployment di un container, elimina il pod che lo ospita. Se il pod è gestito da un costrutto Kubernetes di livello superiore (ad esempio un Deployment o un DaemonSet), l'eliminazione del pod pianifica un nuovo pod. Questo pod esegue nuovi container.

Rifare il deployment ha senso quando:

  • Conosci già la causa della vulnerabilità.
  • Ritieni che un malintenzionato debba impiegare molto tempo o energie per compromettere di nuovo il tuo container.
  • Ritieni che il container possa essere compromesso di nuovo rapidamente e non vuoi metterlo offline, quindi prevedi di inserirlo in una sandbox per limitarne l'impatto.

Quando esegui di nuovo il deployment del workload, se la possibilità di un altro compromesso è elevata, valuta la possibilità di inserire il workload in un ambiente sandbox come GKE Sandbox. La sandbox limita l'accesso al kernel del nodo host se l'utente malintenzionato compromette nuovamente il container.

Per rifare il deployment di un container in Kubernetes, elimina il pod che lo contiene:

kubectl delete pods POD_NAME --grace-period=10

Se i container nel pod eliminato continuano a essere eseguiti, puoi eliminare il workload.

Per rifare il deployment del container all'interno di una sandbox, segui le istruzioni riportate in Rafforza l'isolamento dei workload con GKE Sandbox.

Elimina un workload

L'eliminazione di un workload, ad esempio un deployment o un DaemonSet, comporta l'eliminazione di tutti i relativi pod membri. Tutti i container all'interno di questi pod smettono di essere eseguiti. L'eliminazione di un carico di lavoro può essere utile quando:

  • Vuoi interrompere un attacco in corso.
  • Sei disposto a portare offline il workload.
  • Interrompere immediatamente l'attacco è più importante dell'uptime dell'applicazione o dell'analisi forense.

Per eliminare un carico di lavoro, utilizza kubectl delete CONTROLLER_TYPE. Ad esempio, per eliminare un deployment, esegui questo comando:

kubectl delete deployments DEPLOYMENT

Se l'eliminazione del workload non comporta l'eliminazione di tutti i pod o i container associati, puoi eliminare manualmente i container utilizzando crictl, lo strumento CLI del runtime del container.

Arresta o rimuovi i container con crictl.

Per arrestare un container in containerd, esegui questo comando:

crictl stop CONTAINER

Per rimuovere un container in containerd, esegui questo comando:

crictl rm -f CONTAINER

Elimina la VM host

Se non riesci a eliminare o rimuovere il contenitore, puoi eliminare la macchina virtuale che lo ospita.

Se il pod è ancora visibile, puoi trovare il nome della VM host con il seguente comando:

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

Per eliminare la VM host, esegui questo comando gcloud:

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

L'abbandono dell'istanza dal gruppo di istanze gestite riduce le dimensioni del gruppo di una VM. Puoi aggiungere manualmente un'istanza al gruppo con il seguente comando:

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

Passaggi successivi