Mitigazione degli incidenti di sicurezza


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

I suggerimenti in Rafforzamento della sicurezza del cluster migliorare la sicurezza dei carichi di lavoro GKE. Sicurezza Gli incidenti, tuttavia, possono verificarsi anche quando le misure per proteggere i carichi di lavoro in funzione.

Rilevamento degli incidenti

Per rilevare potenziali incidenti, ti consigliamo di configurare una procedura che raccolga e monitora i log del carico di lavoro. Quindi, configura gli avvisi in base agli eventi anomali rilevato dai log. Gli avvisi informano il team di sicurezza quando viene rilevato qualcosa di insolito. Il team di sicurezza potrà quindi esaminare il potenziale incidente.

Generazione di avvisi dai log

Puoi personalizzare gli avvisi in base a metriche o azioni specifiche. Ad esempio: un avviso sull'utilizzo elevato di CPU sui nodi GKE potrebbe indicare sono compromesse per il cryptomining.

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

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

Rispondere a un incidente di sicurezza

Dopo aver ricevuto un avviso relativo a un incidente, intervieni. Correggi il la vulnerabilità, se puoi. Se non conosci la causa principale della vulnerabilità o non hai a disposizione una correzione, applica le mitigazioni.

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

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

Queste misure di mitigazione sono descritte nelle sezioni seguenti.

Prima di iniziare

I metodi utilizzati in questo argomento utilizzano le seguenti informazioni:

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

Inoltre, prima di intraprendere qualsiasi azione, valuta se l'hacker avrà una reazione negativa se verrà scoperto. L'aggressore può decidere di eliminare i dati o distruggere i carichi di lavoro. Se il rischio è troppo elevato, prendere in considerazione mitigazioni più drastiche come l'eliminazione di un carico di lavoro prima eseguire ulteriori indagini.

Crea uno snapshot del disco della VM

La creazione di uno snapshot del disco della VM consente l'indagine forense dopo il ricollocamento o l'eliminazione del carico di lavoro. Puoi creare snapshot mentre i dischi alle istanze in esecuzione.

  1. Per acquisire lo snapshot del disco permanente, individua prima i dischi collegati alla VM. Esegui il seguente comando e controlla 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 la barra finale. Ad esempio, il nome del disco è gke-cluster-pool-1-abcdeffff-zgt8.

  3. Per completare lo snapshot, esegui il seguente comando:

    gcloud compute disks snapshot DISK_NAME
    

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

Controlla la VM mentre il carico di lavoro continua a essere eseguito

Prima di intraprendere qualsiasi azione, valuta anche quale tipo di accesso potrebbe avere un utente malintenzionato. Se sospetta che un container sia stato compromesso e temono per informare l'aggressore, puoi connetti a il container e lo ispeziona. L'ispezione è utile per effettuare indagini rapide prima di intraprendere azioni più invasive. L'ispezione è anche la meno di disturbo al carico di lavoro, ma l'incidente non viene arrestato.

In alternativa, per evitare di accedere a una macchina con una credenziale privilegiata, puoi analizzare i carichi di lavoro configurando analisi forensi in tempo reale (come Risposta rapida GRR), agenti su nodi o filtri di rete.

Riduci l'accesso prima di ispezionare la VM in esecuzione

Con il contenimento, lo svuotamento, e la limitazione dell'accesso alla rete alla VM che ospita un contenuto compromesso, puoi isolare parzialmente il contenuto compromesso dal resto del cluster. Limitare l'accesso alla VM riduce i rischi, ma non impedire a un aggressore di spostarsi lateralmente nell'ambiente se prende di una vulnerabilità critica.

Isola il nodo e rimuovi gli altri carichi di lavoro

L'isolamento e lo svuotamento di un nodo spostano i carichi di lavoro colocalizzati con il contenitore compromesso su altre VM del cluster. La ridondanza e il drenaggio riducono la capacità dell'aggressore di influire su altri carichi di lavoro sullo stesso nodo. Ciò non impedisce necessariamente di ispezionare lo stato persistente di un carico di lavoro (ad esempio, ispezionando i contenuti delle immagini dei contenitori).

  1. Utilizza kubectl per mettere in isolamento il nodo e assicurarti che nessun altro pod sia pianificato su di esso:

    kubectl cordon NODE_NAME
    

    Dopo aver messo in sicurezza il nodo, rimuovi gli altri pod.

  2. Etichetta il pod in quarantena:

    kubectl label pods POD_NAME quarantine=true
    

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

  3. Scarica il nodo dai pod non etichettati con quarantine:

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

Limita l'accesso di rete al nodo

Ti consigliamo di bloccare l'accesso al traffico sia interno che esterno alla VM host. Successivamente, consenti le connessioni in entrata da una VM specifica sulla tua rete per connetterti alla VM in quarantena.

Il primo passaggio consiste nell'abbandonare la VM Il gruppo di istanze gestite di cui è proprietario. L'abbandono della VM impedisce che il nodo venga contrassegnato come non integro e verrà 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

Configura la VM come firewall

La creazione di un firewall tra il contenitore interessato e gli altri carichi di lavoro nella stessa rete consente di impedire a un malintenzionato di spostarsi in altre parti del tuo ambiente mentre esegui ulteriori analisi. Dal giorno hai già svuotato la VM di altri container, interessa solo il container messo in quarantena.

Le seguenti istruzioni per il firewall della VM impediscono:

  • Nuove connessioni in uscita verso altre VM nel tuo cluster utilizzando un in uscita.
  • Connessioni in entrata nella VM compromessa utilizzando una regola in entrata.

Per bloccare la VM dalle altre istanze tramite il firewall, segui questi passaggi per il nodo che ospita il pod da mettere in quarantena:

  1. Aggiungi un tag all'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 verso le istanze con il tag quarantine. Assegna a questa regola in entrata un valore priority di 1, che consente di eseguirne l'override con un'altra regola che consenta l'accesso tramite SSH 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 le connessioni di rete esistenti al di fuori del VPC.

Per rimuovere l'indirizzo esterno di una VM:

  1. Trova ed elimina la configurazione di accesso che associa l'IP esterno con la VM. Innanzitutto, individua 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. Sono simili seguenti:

    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 il seguente comando:

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

SSH alla VM host tramite una VM intermedia

Dopo aver rimosso l'IP esterno della VM host, non puoi utilizzare l'accesso SSH dall'esterno in un VPC. Accedi da un'altra VM nella stessa rete. Per il resto di questa sezione, la chiameremo VM intermedia.

Prerequisiti

  • Una VM intermedia con accesso alla subnet della VM host. Se non ne hai già uno, crea una VM a questo scopo.
  • L'indirizzo IP interno della VM intermedia.
  • Una chiave pubblica SSH dalla 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 ulteriori informazioni, consulta Aggiunta e rimozione di 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 il seguente 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. Sostituisce la regola di negazione con un valore 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: indirizzo IP interno.

Eseguire nuovamente il deployment di un contenitore

Eseguendo nuovamente il deployment del container, avvierai una nuova copia del container per eliminare il container compromesso.

Esegui il redeployment di un container eliminando il pod che lo ospita. Se il pod è gestite da un costrutto Kubernetes di livello superiore (ad esempio, DaemonSet), l'eliminazione del pod pianifica un nuovo pod. Questo pod esegue nuovi container.

Il ricollocamento è consigliabile quando:

  • Conosci già la causa della vulnerabilità.
  • Pensi che un autore di attacchi richieda un notevole impegno o tempo per compromettere il tuo container.
  • Pensi che il container possa essere nuovamente compromesso rapidamente non vuoi portarlo offline, quindi prevedi di metterlo in sandbox per limitare l'impatto.

Quando reimplementi il carico di lavoro, se la possibilità di un altro compromesso è elevata, considera la possibilità di posizionarlo in un ambiente sandbox come GKE Sandbox. Limitazione tramite sandbox limita l'accesso al kernel del nodo host se l'utente malintenzionato compromette il container di nuovo.

Per eseguire nuovamente 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 in esecuzione, puoi eliminare il carico di lavoro.

Per eseguire nuovamente il deployment del contenitore in una sandbox, segui le istruzioni riportate in Protezione dell'isolamento del carico di lavoro con GKE Sandbox.

Eliminare un carico di lavoro

L'eliminazione di un carico di lavoro, ad esempio un deployment o un DaemonSet, fa sì che tutti i relativi membri di pod da eliminare. Tutti i container all'interno di questi pod interrompono l'esecuzione. L'eliminazione di un workload può essere utile quando:

  • Vuoi interrompere un attacco in corso.
  • Sei disponibile a portare il carico di lavoro offline.
  • Interrompere immediatamente l'attacco è più importante del tempo di attività dell'applicazione o dell'analisi forense.

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

kubectl delete deployments DEPLOYMENT

Se l'eliminazione del carico di lavoro non elimina tutti i pod o i container associati, puoi eliminare manualmente i container utilizzando lo strumento CLI dei runtime dei container, tipicamente docker. Se i nodi vengono eseguiti containerd, utilizza crictl.

Docker

Per impedire a un container di utilizzare il runtime del container Docker, puoi utilizzare docker stop o docker kill.

docker stop arresta il container inviando un segnale SIGTERM alla radice e attende 10 secondi fino alla chiusura del processo per impostazione predefinita. Se Il processo non si è chiuso in quel periodo di tempo, quindi invia un indicatore SIGKILL. Puoi specificare questo periodo di tolleranza con l'opzione --time.

docker stop --time TIME_IN_SECONDS CONTAINER

docker kill è il metodo più rapido per arrestare un contenitore. Invia le Segnale SIGKILL immediatamente.

docker kill CONTAINER

Puoi anche arrestare e rimuovere un container in un solo comando con docker rm -f:

docker rm -f CONTAINER

containerd

Se utilizzi il runtime containerd in GKE, interrompi o rimuovi i container con crictl.

Per interrompere un contenitore in containerd, esegui il seguente comando:

crictl stop CONTAINER

Per rimuovere un container in containerd, esegui questo comando:

crictl rm -f CONTAINER

Eliminazione della VM host

Se non riesci a eliminare o rimuovere il contenitore, puoi eliminare il file che ospita il container interessato.

Se il pod è ancora visibile, puoi trovare il nome della VM host con 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 il seguente 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