Questo documento descrive le mitigazioni e le risposte comuni a potenziali incidenti di sicurezza nei cluster e nei container di Google Kubernetes Engine (GKE).
Questo documento è rivolto agli 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 Google Cloud contenuti, consulta Ruoli e attività comuni degli utenti di GKE Enterprise.
I suggerimenti riportati in Rafforzamento della sicurezza del cluster possono migliorare la sicurezza dei carichi di lavoro GKE. Tuttavia, gli incidenti di sicurezza possono verificarsi anche quando sono in atto misure per proteggere i carichi di lavoro.
Rileva gli incidenti
Per rilevare potenziali incidenti, ti consigliamo di configurare un processo che raccolga e monitori i log del tuo carico di lavoro. Poi, configura gli avvisi in base agli eventi anormali rilevati 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.
Puoi personalizzare gli avvisi in base a metriche o azioni specifiche. Ad esempio, gli avvisi sull'utilizzo elevato della CPU sui tuoi nodi GKE possono indicare che sono compromessi per il mining di criptovalute.
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 la vulnerabilità, se possibile. 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. In ordine crescente di gravità, puoi:
- Crea uno snapshot del disco della VM host. Uno snapshot consente di eseguire alcune analisi forensi sullo stato della VM al momento dell'anomalia dopo il ricollocamento o l'eliminazione del carico di lavoro.
Controlla la VM mentre il workload continua a funzionare. La connessione alla VM host o al contenitore del workload può fornire informazioni sulle azioni dell'attaccante. Ti consigliamo di ridurre l'accesso prima di ispezionare la VM in produzione.
Esegui il redeployment di un contenitore. La riesecuzione del deployment termina le procedure attualmente in esecuzione nel contenitore interessato e le riavvia.
Elimina un carico di lavoro. L'eliminazione del carico di lavoro termina le procedure attualmente in esecuzione nel contenitore interessato senza un riavvio.
Queste misure di mitigazione 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 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, valuta la possibilità di adottare misure di mitigazione più drastiche, come l'eliminazione di un carico di lavoro, prima di eseguire ulteriori accertamenti.
Crea uno snapshot del disco della VM
La creazione di uno snapshot del disco della VM consente di eseguire indagini forensi dopo il nuovo deployment o l'eliminazione del carico di lavoro. Gli snapshot possono essere creati mentre i dischi sono collegati a istanze in esecuzione.
Per acquisire uno 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])"
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
.Per completare lo snapshot, esegui il seguente comando:
gcloud compute disks snapshot DISK_NAME
Per ulteriori informazioni, consulta la sezione Creare snapshot dei dischi permanenti nella documentazione di Compute Engine.
Ispeziona la VM
Valuta l'accesso di cui potrebbe disporre un utente malintenzionato prima di intervenire. Se sospetti che un contenitore sia stato compromesso e temi di informare l'attaccante, puoi connetterti al contenitore e ispezzionarlo senza interrompere i tuoi carichi di lavoro. L'ispezione è utile per effettuare indagini rapide prima di intraprendere azioni più invasive. L'ispezione è anche l'approccio meno perturbante per il carico di lavoro, ma non interrompe l'incidente.
In alternativa, per evitare di accedere a una macchina con una credenziale con privilegi, puoi analizzare i tuoi carichi di lavoro configurando la forensistica in tempo reale (ad esempio GRR Rapid Response), agenti on-node 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 il rischio, ma non impedisce a un malintenzionato di muoversi lateralmente nel tuo ambiente se sfrutta una vulnerabilità critica.
Isola il nodo e rimuovi gli altri carichi di lavoro
Il cordone e lo svuotamento di un nodo spostano i carichi di lavoro colocalizzati con il contenitore compromesso su altre VM del cluster. Il cordone e lo svuotamento riducono la capacità di un malintenzionato di influire su altri workload 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).
Utilizza
kubectl
per mettere in isolamento il nodo e assicurarti che non siano pianificati altri pod su di esso:kubectl cordon NODE_NAME
Dopo aver messo in sicurezza il nodo, rimuovi gli altri pod.
Etichetta il pod in quarantena:
kubectl label pods POD_NAME quarantine=true
Sostituisci
POD_NAME
con il nome del pod che vuoi mettere in quarantena.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 o VPC 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 funzionante e riparato automaticamente (ricreato) prima del completamento dell'indagine.
Per abbandonare la VM, esegui il seguente 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. Dato che hai già svuotato la VM da altri container, questo problema riguarda solo il container messo in quarantena.
Le seguenti istruzioni per il firewall della VM impediscono:
- Nuove connessioni in uscita ad altre VM del cluster utilizzando una regola di uscita.
- Connessioni in entrata alla VM compromessa utilizzando una regola di ingresso.
Per bloccare la VM dalle altre istanze tramite il firewall, segui questi passaggi per il nodo che ospita il pod da 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 di ingresso unpriority
di1
, che ti consente di sostituirla con un'altra regola che consenta l'accesso 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 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
. Sono simili ai seguenti:networkInterfaces[0].accessConfigs[0].name: ACCESS_CONFIG_NAME networkInterfaces[0].accessConfigs[0].natIP: EXTERNAL_IP_ADDRESS
Trova il valore di
natIP
corrispondente all'IP esterno che vuoi rimuovere. Prendi nota del nome della configurazione di accesso.Per rimuovere l'IP esterno, esegui il seguente 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 eseguire SSH dall'esterno della 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 sottorete della VM host. Se non ne hai già uno, 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 Gestire le 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 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 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 chiave privata SSH.USER
: l'indirizzo email del tuo Google Cloud account.QUARANTINED_VM_INTERNAL_IP
: l'indirizzo IP interno.
Eseguire nuovamente il deployment di un contenitore
Se esegui il rieseguire il deployment del container, avvii una nuova copia del container ed elimini quello compromesso.
Esegui il redeployment di un container eliminando 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 ricollocamento è consigliabile quando:
- Conosci già la causa della vulnerabilità.
- Riteniamo che un malintenzionato debba impiegare molto tempo o fare un grande sforzo per compromettere nuovamente il tuo contenitore.
- Pensi che il contenitore possa essere compromesso di nuovo rapidamente e non vuoi metterlo offline, quindi prevedi di inserirlo in una 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. La sandbox limita l'accesso al kernel del nodo host se l'utente malintenzionato compromette nuovamente il contenitore.
Per eseguire nuovamente il deployment di un contenitore 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 workload.
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 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 interrompono l'esecuzione. L'eliminazione di un workload può essere utile quando:
- Vuoi interrompere un attacco in corso.
- Sei disposto a mettere 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 workload 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 tuoi nodi eseguono
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 contenitore inviando un segnale SIGTERM
al processo di root e attende 10 secondi per l'uscita del processo per impostazione predefinita. Se il processo non è terminato in questo periodo di tempo, viene inviato 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 immediatamente il segnale SIGKILL
.
docker kill CONTAINER
Puoi anche arrestare e rimuovere un contenitore in un unico 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 contenitore in containerd
, esegui il seguente comando:
crictl rm -f CONTAINER
Elimina la VM host
Se non riesci a eliminare o rimuovere il contenitore, puoi eliminare la macchina virtuale che ospita il contenitore interessato.
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 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
- Eseguire analisi forensi sui container
- Rafforzamento della sicurezza del cluster
- Analisi forense per le applicazioni GKE