Questo documento descrive le mitigazioni e le risposte comuni a 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 utente e attività comuni di GKE Enterprise.
I suggerimenti riportati in Rafforzamento della sicurezza del cluster possono migliorare la sicurezza dei tuoi workload GKE. Tuttavia, gli incidenti di sicurezza possono verificarsi anche quando sono in atto misure per proteggere i 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. Dopodiché, 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, gli avvisi relativi all'utilizzo elevato della CPU sui nodi GKE potrebbero indicare che sono compromessi per il mining di criptovalute.
Gli avvisi devono essere generati nel punto in cui vengono aggregati log e 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 logging di controllo.
Rispondere a un incidente di sicurezza
Dopo aver ricevuto una notifica relativa a un incidente, intervieni. 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 descrive 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à:
- Crea uno snapshot del disco della VM host. Uno snapshot ti consente di eseguire alcune analisi forensi sullo stato della VM al momento dell'anomalia dopo il redeployment o l'eliminazione del workload.
Ispeziona la VM mentre il workload continua a essere eseguito. La connessione alla VM host o al container del workload può fornire informazioni sulle azioni dell'autore dell'attacco. Ti consigliamo di ridurre l'accesso prima di ispezionare la VM live.
Esegui nuovamente il deployment di un container. La riesecuzione del deployment termina i processi attualmente in esecuzione nel contenitore interessato e li riavvia.
Elimina un workload. L'eliminazione del workload termina i processi attualmente in esecuzione nel contenitore interessato senza riavvio.
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 delle azioni, valuta se ci sarà una reazione negativa da parte dell'aggressore se viene scoperto. L'attaccante potrebbe decidere di eliminare i dati o distruggere i carichi di lavoro. Se il rischio è troppo elevato, valuta mitigazioni più drastiche, come l'eliminazione di un carico di lavoro prima di eseguire ulteriori indagini.
Crea uno snapshot del disco della VM
La creazione di uno snapshot del disco della VM consente l'analisi forense dopo il redeploy o l'eliminazione del workload. Gli snapshot possono essere creati mentre i dischi sono collegati alle istanze in esecuzione.
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])"
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
.Per completare lo snapshot, esegui il comando seguente:
gcloud compute disks snapshot DISK_NAME
Per saperne di più, consulta la sezione Creazione di disco permanente permanenti nella documentazione di Compute Engine.
Ispeziona la VM
Prima di intraprendere qualsiasi azione, valuta l'accesso che potrebbe avere un utente malintenzionato. Se sospetti che un container sia stato compromesso e ti preoccupa informare l'autore dell'attacco, puoi connetterti al container e ispezionarlo senza interrompere i tuoi 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 carichi di lavoro 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 live
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 carichi di lavoro
L'isolamento e lo svuotamento di un nodo sposta i carichi di lavoro collocati insieme al container compromesso su 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).
Utilizza
kubectl
per isolare il nodo e assicurarti che non vengano pianificati altri pod su di esso:kubectl cordon NODE_NAME
Dopo aver isolato il nodo, svuotalo dagli altri pod.
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.Svuota il nodo dei pod che non sono etichettati con
quarantine
:kubectl drain NODE_NAME --pod-selector='!quarantine'
Limita l'accesso di rete al nodo
Ti consigliamo di bloccare l'accesso alla VM host sia per il traffico interno che per quello 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'abbandono 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
Configura il firewall della VM
Creare 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 di ingresso.
Per isolare la VM dalle altre istanze, segui questi passaggi per il nodo che ospita il pod che vuoi mettere in quarantena:
Tagga l'istanza in modo da poter applicare una nuova regola firewall.
gcloud compute instances add-tags NODE_NAME \ --zone COMPUTE_ZONE \ --tags quarantine
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
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
di1
, 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 al di fuori del VPC.
Per rimuovere l'indirizzo esterno di una VM:
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
enatIP
. Hanno un aspetto simile a questo:networkInterfaces[0].accessConfigs[0].name: ACCESS_CONFIG_NAME networkInterfaces[0].accessConfigs[0].natIP: EXTERNAL_IP_ADDRESS
Trova il valore di
natIP
che corrisponde all'IP esterno che vuoi rimuovere. Prendi nota del nome della configurazione di accesso.Per rimuovere l'IP esterno, esegui questo comando:
gcloud compute instances delete-access-config NODE_NAME \ --access-config-name "ACCESS_CONFIG_NAME"
Accedi 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. Per il resto di questa sezione, ci riferiremo 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ù, consulta la pagina Gestione delle chiavi SSH.
Connessione alla VM host
- 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.
Aggiungi un tag alla VM intermedia.
gcloud compute instances add-tags INTERMEDIATE_NODE_NAME \ --zone COMPUTE_ZONE \ --tags intermediate
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 unpriority
di0
.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 tua chiave privata SSH.USER
: l'indirizzo email del tuo account Google Cloud .QUARANTINED_VM_INTERNAL_IP
: l'indirizzo IP interno.
Eseguire nuovamente il deployment di un container
Se esegui nuovamente 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.
Il nuovo deployment ha senso quando:
- Conosci già la causa della vulnerabilità.
- Ritieni che un malintenzionato debba impiegare molto tempo o sforzo 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 limitare l'impatto.
Quando esegui di nuovo il deployment del carico di lavoro, se la possibilità di un altro compromesso è elevata, valuta la possibilità di inserire il carico di lavoro in un ambiente sandbox come GKE Sandbox. La sandbox limita l'accesso al kernel del nodo host se l'attaccante compromette nuovamente il container.
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 eseguiti, puoi eliminare il workload.
Per eseguire nuovamente il deployment del container all'interno di una sandbox, segui le istruzioni riportate in Protezione dell'isolamento del carico di lavoro con GKE Sandbox.
Eliminare un workload
L'eliminazione di un workload, ad esempio un deployment o un DaemonSet, comporta l'eliminazione di tutti i suoi 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 mettere offline il carico di lavoro.
- 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 lo strumento CLI dei runtime dei container, in genere docker
. Se i tuoi nodi eseguono
containerd, utilizza crictl
.
Docker
Per arrestare un container utilizzando il runtime del container Docker, puoi utilizzare docker stop
o docker kill
.
docker stop
arresta il container inviando un segnale SIGTERM
al processo root e attende 10 secondi per l'uscita del processo per impostazione predefinita. Se il
processo non è terminato in questo periodo di tempo, invia un segnale SIGKILL
.
Puoi specificare questo periodo di tolleranza con l'opzione --time
.
docker stop --time TIME_IN_SECONDS CONTAINER
docker kill
è il metodo più veloce per arrestare un contenitore. Invia immediatamente il segnale
SIGKILL
.
docker kill CONTAINER
Puoi anche arrestare e rimuovere un container con un unico comando con docker rm -f
:
docker rm -f CONTAINER
containerd
Se utilizzi il runtime containerd
in GKE, arresta o rimuovi i container con crictl
.
Per arrestare un container in containerd
, esegui questo comando:
crictl stop CONTAINER
Per rimuovere un contenitore in containerd
, esegui questo comando:
crictl rm -f CONTAINER
Elimina la VM host
Se non riesci a eliminare o rimuovere il container, 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
- Esecuzione di analisi forense sui container
- Rafforzamento della sicurezza del cluster
- Analisi forense per le applicazioni GKE