Questo documento descrive mitigazioni e risposte a potenziali incidenti di sicurezza per i cluster e i container Google Kubernetes Engine (GKE).
I suggerimenti riportati in Rafforzare la sicurezza del cluster possono migliorare la sicurezza dei carichi di lavoro GKE. Gli incidenti relativi alla sicurezza, tuttavia, possono verificarsi anche quando sono attive misure per proteggere i carichi di lavoro.
Rilevamento incidenti
Per rilevare potenziali incidenti, ti consigliamo di configurare un processo che raccolga e monitori i log del carico di lavoro. Poi, configura avvisi basati sugli eventi anomali rilevati dai log. Gli avvisi avvisano il team addetto alla 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, gli avvisi relativi a un utilizzo elevato della CPU sui nodi GKE potrebbero indicare che sono compromessi per il cryptomining.
Dovresti generare avvisi nel punto in cui aggreghi i log e le metriche. Ad esempio, puoi utilizzare l'audit logging di GKE in combinazione con gli avvisi basati su log in Cloud Logging.
Per ulteriori informazioni sulle query relative alla sicurezza, consulta la documentazione sull'audit logging.
Risposta a un incidente di sicurezza
Intervieni dopo aver ricevuto un avviso relativo a un incidente. Se possibile, correggi la vulnerabilità. Se non conosci la causa principale della vulnerabilità o se non è pronta una correzione, applica le mitigazioni.
Le mitigazioni 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à:
- Esegui uno snapshot del disco della VM host. Uno snapshot consente di eseguire alcune analisi forensi sullo stato della VM al momento dell'anomalia, dopo che è stato eseguito nuovamente il deployment o l'eliminazione del carico di lavoro.
Ispeziona la VM durante l'esecuzione del carico di lavoro. La connessione alla VM host o al container del carico di lavoro può fornire informazioni sulle azioni dell'utente malintenzionato. Ti consigliamo di ridurre l'accesso prima di ispezionare la VM attiva.
Esegui nuovamente il deployment di un container. Il nuovo deployment termina i processi attualmente in esecuzione nel container interessato e li riavvia.
Elimina un carico di lavoro. L'eliminazione del carico di lavoro termina i processi attualmente in esecuzione nel container interessato, senza un 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 pensi 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 qualsiasi azione, valuta se l'utente malintenzionato viene scoperto in una reazione negativa. L'utente malintenzionato potrebbe decidere di eliminare i dati o i carichi di lavoro. Se il rischio è troppo elevato, prima di eseguire ulteriori indagini valuta la possibilità di mitigazioni più drastiche, come l'eliminazione di un carico di lavoro.
Crea snapshot del disco della VM
La creazione di uno snapshot del disco della VM consente un'indagine forense dopo che è stato eseguito nuovamente il deployment o eliminato il carico di lavoro. Puoi creare snapshot mentre i dischi sono collegati a istanze in esecuzione.
Per creare uno snapshot del disco permanente, devi prima trovare i dischi collegati alla VM. Esegui questo comando e osserva 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 di origine che segue la barra finale. Ad esempio, il nome del disco è
gke-cluster-pool-1-abcdeffff-zgt8
.Per completare lo snapshot, esegui questo comando:
gcloud compute disks snapshot DISK_NAME
Per ulteriori informazioni, consulta la sezione sulla creazione di disco permanente permanenti nella documentazione di Compute Engine.
Ispeziona la VM durante l'esecuzione del carico di lavoro
Prima di intervenire, valuta anche di quale accesso può disporre un utente malintenzionato. Se sospetti che un container sia stato compromesso e temi di informare l'utente malintenzionato, puoi collegarti al container ed ispezionarlo. L'ispezione è utile per indagini rapide prima di intraprendere azioni più fastidiose. L'ispezione è anche l'approccio meno invasivo per il carico di lavoro, ma non arresta l'incidente.
In alternativa, per evitare di accedere a una macchina con credenziali privilegiate, puoi analizzare i tuoi carichi di lavoro configurando l'analisi forense in tempo reale (come GRR Rapid Response), agenti on-node o filtri di rete.
Riduci l'accesso prima di ispezionare la VM attiva
Se nascondi, svuota e limiti l'accesso della rete alla VM che ospita un container compromesso, puoi isolare parzialmente il container compromesso dal resto del cluster. Limitare l'accesso alla VM riduce i rischi, ma non impedisce a un utente malintenzionato di spostarsi lateralmente nel tuo ambiente se si avvale di una vulnerabilità critica.
Non pianifica il nodo ed svuota gli altri carichi di lavoro al suo interno
L'eliminazione o lo svuotamento di un nodo sposta i carichi di lavoro che si trovano insieme al container compromesso ad altre VM nel tuo cluster. Lo svuotamento e lo svuotamento riducono la capacità degli utenti malintenzionati di influire su altri carichi di lavoro sullo stesso nodo. Non gli impedisce in alcun modo di ispezionare lo stato permanente di un carico di lavoro (ad esempio, esaminando i contenuti delle immagini container).
Utilizza
kubectl
per contrassegnare il nodo come non pianificabile e assicurarti che non vi siano pianificati altri pod:kubectl cordon NODE_NAME
Dopo aver contrassegnato il nodo come non pianificabile, svuota quello degli altri pod.
Etichetta il pod che metti in quarantena:
kubectl label pods POD_NAME quarantine=true
Sostituisci
POD_NAME
con il nome del pod che vuoi mettere in quarantena.Svuota i nodi dei pod non 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 sia al traffico interno che esterno. Quindi, consenti alle connessioni in entrata da una VM specifica sulla tua rete o VPC di connettersi alla VM in quarantena.
Il primo passaggio consiste nell'abbandonare la VM dal gruppo di istanze gestite a cui appartiene. Se abbandoni la VM, il nodo non verrà 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
Esegui il firewall sulla VM
Creare un firewall tra il container interessato e altri carichi di lavoro nella stessa rete aiuta a impedire a un utente malintenzionato di spostarsi in altre parti dell'ambiente mentre conduci ulteriori analisi. Poiché hai già svuotato la VM di altri container, l'operazione ha effetto solo sul container in quarantena.
Le seguenti istruzioni sul firewall per la VM impediscono:
- Nuove connessioni in uscita verso altre VM nel tuo cluster utilizzando una regola in uscita.
- Connessioni in entrata alla VM compromessa tramite una regola in entrata.
Per limitare la VM alle altre istanze, segui questi passaggi per il nodo che ospita il pod che vuoi mettere in quarantena:
Applica un tag all'istanza per 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 verso le istanze con il tag
quarantine
. Assegna a questa regola in entrata un valorepriority
pari a1
, per 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 comporta l'interruzione di tutte le connessioni di rete esistenti all'esterno del VPC.
Per rimuovere l'indirizzo esterno di una VM, segui questi passaggi:
Trova ed elimina la configurazione di accesso che associa l'IP esterno alla VM. Innanzitutto trova la configurazione dell'accesso descrivendo la VM:
gcloud compute instances describe NODE_NAME \ --zone COMPUTE_ZONE --format="flattened([networkInterfaces])"
Cerca le righe che contengono
name
enatIP
. Hanno il seguente aspetto:networkInterfaces[0].accessConfigs[0].name: ACCESS_CONFIG_NAME networkInterfaces[0].accessConfigs[0].natIP: EXTERNAL_IP_ADDRESS
Trova il valore di
natIP
che corrisponda all'IP esterno che vuoi rimuovere. Prendi nota del nome della configurazione dell'accesso.Per rimuovere l'IP esterno, esegui questo 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 accedere tramite SSH dall'esterno del VPC. Puoi accedervi da un'altra VM nella stessa rete. Nel resto di questa sezione, facciamo riferimento a VM intermedia.
Prerequisiti
- Una VM intermedia con accesso alla subnet della VM host. Se non ne hai già una, crea una VM per questo scopo.
- L'indirizzo IP interno della VM intermedia.
- Una chiave pubblica SSH dalla VM intermedia. Per scoprire di più, consulta 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
. Sostituisce la regola di negazione con un valorepriority
pari a0
.Connettiti alla VM in quarantena utilizzando l'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.
Esegui di nuovo il deployment di un container
Se esegui nuovamente il deployment del container, avvii una nuova copia del container ed elimini il container compromesso.
Esegui nuovamente il deployment di un container eliminando il pod che lo ospita. Se il pod è gestito da un costrutto Kubernetes di livello superiore (ad esempio un oggetto Deployment o DaemonSet), l'eliminazione del pod pianifica un nuovo pod. Questo pod esegue nuovi container.
Eseguire nuovamente il deployment ha senso quando:
- Conosci già la causa della vulnerabilità.
- Ritieni che sia necessario uno sforzo significativo o molto tempo da parte di un utente malintenzionato per compromettere nuovamente il tuo container.
- Pensi che il container possa essere compromesso di nuovo rapidamente e non vuoi metterlo offline, quindi ti consigliamo di inserirlo in una sandbox per limitarne l'impatto.
Quando riesegui il deployment del carico di lavoro, se la possibilità di un altro problema è elevato, valuta la possibilità di posizionare il carico di lavoro in un ambiente sandbox come GKE Sandbox. La limitazione tramite sandbox limita l'accesso al kernel del nodo host se un utente malintenzionato 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 carico di lavoro.
Per eseguire nuovamente il deployment del container all'interno di una sandbox, segui le istruzioni in Rafforzare l'isolamento dei carichi di lavoro con GKE Sandbox.
Elimina un carico di lavoro
L'eliminazione di un carico di lavoro, ad esempio un oggetto Deployment o DaemonSet, determina l'eliminazione di tutti i relativi pod di membri. L'esecuzione di tutti i container all'interno di questi pod viene interrotta. L'eliminazione di un carico di lavoro può avere senso quando:
- Vuoi fermare un attacco in corso.
- Hai intenzione di portare il carico di lavoro offline.
- L'arresto immediato dell'attacco è più importante dell'uptime delle applicazioni 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 carico di lavoro non comporta l'eliminazione di tutti i pod o i container associati, puoi eliminare manualmente i container utilizzando lo strumento dell'interfaccia a riga di comando del runtime dei container, in genere docker
. Se i nodi vengono eseguiti
containerd, utilizza crictl
.
Docker
Per arrestare un container utilizzando il runtime del container Docker, puoi usare
docker stop
o docker kill
.
docker stop
arresta il container inviando un segnale SIGTERM
al processo principale e attende 10 secondi l'uscita del processo per impostazione predefinita. Se il processo non è uscito nel periodo di tempo specificato, viene inviato un indicatore SIGKILL
.
Puoi specificare questo periodo di tolleranza tramite l'opzione --time
.
docker stop --time TIME_IN_SECONDS CONTAINER
docker kill
è il metodo più veloce per arrestare un container. Invia immediatamente il segnale SIGKILL
.
docker kill CONTAINER
Puoi anche arrestare e rimuovere un container in un 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 arrestare un container in containerd
, esegui questo 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 container, puoi eliminare la macchina virtuale che ospita il container interessato.
Se il pod è ancora visibile, puoi trovare il nome della VM host con il comando seguente:
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
Se abbandoni l'istanza dal gruppo di istanze gestite, le dimensioni del gruppo vengono ridotte di una VM. Puoi aggiungere di nuovo 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