Este documento descreve mitigações e respostas comuns a potenciais incidentes de segurança nos seus clusters e contentores do Google Kubernetes Engine (GKE).
Este documento destina-se a especialistas de segurança que procuram orientações para responder a incidentes de segurança do GKE. Para saber mais sobre as funções comuns e as tarefas de exemplo que referimos no conteúdo, consulte o artigo Funções e tarefas comuns do utilizador do GKE. Google Cloud
As sugestões em Reforçar a segurança do cluster podem melhorar a segurança das suas cargas de trabalho do GKE. No entanto, podem ocorrer incidentes de segurança mesmo quando existem medidas para proteger as suas cargas de trabalho.
Detete incidentes
Para detetar potenciais incidentes, recomendamos que configure um processo que recolha e monitorize os registos da sua carga de trabalho. Em seguida, configure alertas com base em eventos anormais detetados a partir dos registos. Os alertas notificam a sua equipa de segurança quando é detetado algo invulgar. Em seguida, a sua equipa de segurança pode rever o potencial incidente.
Pode personalizar os alertas com base em métricas ou ações específicas. Por exemplo, os alertas sobre a utilização elevada da CPU nos seus nós do GKE podem indicar que estão comprometidos para a mineração de criptomoedas.
Os alertas devem ser gerados onde agrega os registos e as métricas. Por exemplo, pode usar o registo de auditoria do GKE em combinação com alertas baseados em registos no Cloud Logging.
Para saber mais sobre as consultas relevantes para a segurança, consulte a documentação de Registo de auditoria.
Responda a um incidente de segurança
Depois de receber um alerta sobre um incidente, tome medidas. Corrija a vulnerabilidade, se possível. Se não souber a causa principal da vulnerabilidade ou não tiver uma correção pronta, aplique mitigações.
As mitigações que pode tomar dependem da gravidade do incidente e da sua certeza de que identificou o problema.
Este guia aborda as ações que pode realizar depois de detetar um incidente numa carga de trabalho em execução no GKE. Pode, por ordem crescente de gravidade:
- Crie um instantâneo do disco da VM anfitriã. Uma captura instantânea permite-lhe realizar alguma análise forense no estado da VM no momento da anomalia após a nova implementação ou a eliminação da carga de trabalho.
Inspeção da VM enquanto a carga de trabalho continua a ser executada. A ligação à VM anfitriã ou ao contentor de carga de trabalho pode fornecer informações sobre as ações do atacante. Recomendamos que reduza o acesso antes de inspecionar a VM em direto.
Volte a implementar um contentor. A nova implementação termina os processos atualmente em execução no contentor afetado e reinicia-os.
Elimine uma carga de trabalho. A eliminação da carga de trabalho termina os processos atualmente em execução no contentor afetado sem um reinício.
Estas mitigações são descritas nas secções seguintes.
Antes de começar
Os métodos usados neste tópico usam as seguintes informações:
- O nome dos Pods que considera terem sido comprometidos ou
POD_NAME
. - O nome da VM anfitriã que executa o contentor ou os pods, ou
NODE_NAME
.
Além disso, antes de tomar qualquer uma das medidas, pondere se o atacante terá uma reação negativa se for descoberto. O atacante pode decidir eliminar dados ou destruir cargas de trabalho. Se o risco for demasiado elevado, considere mitigações mais drásticas, como eliminar uma carga de trabalho antes de realizar uma investigação mais aprofundada.
Crie um instantâneo do disco da VM
A criação de uma captura instantânea do disco da VM permite a investigação forense após a reimplementação ou a eliminação da carga de trabalho. É possível criar instantâneos enquanto os discos estão associados a instâncias em execução.
Para criar uma imagem instantânea do disco persistente, comece por encontrar os discos associados à VM. Execute o seguinte comando e consulte o campo
source
:gcloud compute instances describe NODE_NAME --zone COMPUTE_ZONE \ --format="flattened([disks])"
Procure as linhas que contêm
disks[NUMBER].source
. O resultado é semelhante ao seguinte:disks[0].source: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/zones/COMPUTE_ZONE/disks/DISK_NAME
O nome do disco é a parte do nome de origem após a barra final. Por exemplo, o nome do disco é
gke-cluster-pool-1-abcdeffff-zgt8
.Para concluir a captura de ecrã, execute o seguinte comando:
gcloud compute disks snapshot DISK_NAME
Para mais informações, consulte o artigo Criar instantâneos de discos persistentes na documentação do Compute Engine.
Inspecione a VM
Pondere o acesso que um atacante pode ter antes de tomar medidas. Se suspeitar que um contentor foi comprometido e tiver preocupações em informar o atacante, pode estabelecer ligação ao contentor e inspecioná-lo sem interromper as suas cargas de trabalho. A inspeção é útil para uma investigação rápida antes de tomar medidas mais disruptivas. A inspeção também é a abordagem menos disruptiva para a carga de trabalho, mas não impede o incidente.
Em alternativa, para evitar iniciar sessão numa máquina com uma credencial privilegiada, pode analisar as suas cargas de trabalho configurando a análise forense em direto (como o GRR Rapid Response), agentes no nó ou filtragem de rede.
Reduza o acesso antes de inspecionar a VM em direto
Ao isolar, esvaziar> e limitar o acesso à rede à VM que aloja um contentor comprometido, pode isolar parcialmente> o contentor comprometido do resto do cluster. A limitação do acesso à VM reduz o risco, mas não impede que um atacante se mova lateralmente no seu ambiente se tirar partido de uma vulnerabilidade crítica.
Isolar o nó e remover as outras cargas de trabalho do mesmo
Isolar e esvaziar um nó move as cargas de trabalho localizadas com o contentor comprometido para outras VMs no cluster. A restrição e a drenagem reduzem a capacidade de um atacante afetar outras cargas de trabalho no mesmo nó. Não impede necessariamente que inspecionem o estado persistente de uma carga de trabalho (por exemplo, inspecionando os conteúdos da imagem do contentor).
Use
kubectl
para isolar o nó e garantir que não são agendados outros pods no mesmo:kubectl cordon NODE_NAME
Depois de isolar o nó, esvazie o nó de outros pods.
Etiquete o pod que está a colocar em quarentena:
kubectl label pods POD_NAME quarantine=true
Substitua
POD_NAME
pelo nome do Pod que quer isolar.Esvazie o nó dos pods que não estão etiquetados com
quarantine
:kubectl drain NODE_NAME --pod-selector='!quarantine'
Restrinja o acesso à rede do nó
Recomendamos que bloqueie o acesso ao VM anfitrião por parte do tráfego interno e externo. Em seguida, permita ligações de entrada de uma VM específica na sua rede ou VPC para estabelecer ligação à VM em quarentena.
O primeiro passo é abandonar a VM do grupo de instâncias geridas que é proprietário da mesma. O abandono da VM impede que o nó seja marcado como não saudável e reparado automaticamente (recriado) antes de a sua investigação estar concluída.
Para abandonar a VM, execute o seguinte comando:
gcloud compute instance-groups managed abandon-instances INSTANCE_GROUP_NAME \
--instances=NODE_NAME
Proteja a VM com um firewall
Criar uma firewall entre o contentor afetado e outras cargas de trabalho na mesma rede ajuda a impedir que um atacante se mova para outras partes do seu ambiente enquanto realiza uma análise mais detalhada. Uma vez que já esgotou a VM de outros contentores, isto só afeta o contentor em quarentena.
As seguintes instruções sobre a configuração de firewalls na VM impedem:
- Novas ligações de saída a outras VMs no cluster através de uma regra de saída.
- Ligações de entrada à VM comprometida através de uma regra de entrada.
Para proteger a VM com uma firewall das outras instâncias, siga estes passos para o nó que aloja o pod que quer colocar em quarentena:
Etiquete a instância para poder aplicar uma nova regra de firewall.
gcloud compute instances add-tags NODE_NAME \ --zone COMPUTE_ZONE \ --tags quarantine
Crie uma regra de firewall para recusar todo o tráfego TCP de saída de instâncias com a etiqueta
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
Crie uma regra de firewall para recusar todo o tráfego TCP de entrada para instâncias com a etiqueta
quarantine
. Dê a esta regra de entrada umapriority
de1
, o que lhe permite substituí-la por outra regra que permita o SSH a partir de uma VM especificada.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
Remova o endereço IP externo da VM
A remoção do endereço IP externo da VM interrompe as ligações de rede existentes fora da sua VPC.
Para remover o endereço externo de uma VM, siga estes passos:
Encontre e elimine a configuração de acesso que associa o IP externo à VM. Primeiro, encontre a configuração de acesso descrevendo a VM:
gcloud compute instances describe NODE_NAME \ --zone COMPUTE_ZONE --format="flattened([networkInterfaces])"
Procure as linhas que contêm
name
enatIP
. Têm o seguinte aspeto:networkInterfaces[0].accessConfigs[0].name: ACCESS_CONFIG_NAME networkInterfaces[0].accessConfigs[0].natIP: EXTERNAL_IP_ADDRESS
Encontre o valor de
natIP
que corresponde ao IP externo que quer remover. Tome nota do nome da configuração de acesso.Para remover o IP externo, execute o seguinte comando:
gcloud compute instances delete-access-config NODE_NAME \ --access-config-name "ACCESS_CONFIG_NAME"
Faça SSH para a VM anfitriã através de uma VM intermédia
Depois de remover o IP externo da VM anfitriã, não pode fazer SSH a partir do exterior da sua VPC. Aceder a partir de outra VM na mesma rede. No resto desta secção, referimo-nos a isto como a VM intermédia.
Pré-requisitos
- Uma VM intermédia com acesso à sub-rede da VM anfitriã. Se ainda não tiver uma, crie uma MV para este fim.
- O endereço IP interno da VM intermédia.
- Uma chave pública de SSH da VM intermédia. Para saber mais, consulte o artigo Gerir chaves SSH
Estabelecer ligação à VM anfitriã
- Adicione a chave pública da VM intermédia à VM anfitriã. Para mais informações, consulte Adicionar e remover chaves SSH na documentação do Compute Engine.
Adicione uma etiqueta à VM intermédia.
gcloud compute instances add-tags INTERMEDIATE_NODE_NAME \ --zone COMPUTE_ZONE \ --tags intermediate
Adicione uma regra de autorização de entrada para substituir a regra de recusa que adicionou anteriormente. Para adicionar a regra, execute o seguinte 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
Esta regra permite o tráfego recebido na porta 22 (SSH) de VMs na sua rede com a etiqueta
intermediate
. Substitui a regra de recusa por uma regra de permissão de0
.priority
Estabeleça ligação à VM em quarentena através do respetivo IP interno:
ssh -i KEY_PATH USER@QUARANTINED_VM_INTERNAL_IP
Substitua o seguinte:
KEY_PATH
: o caminho para a sua chave privada de SSH.USER
: o endereço de email da sua conta Google Cloud .QUARANTINED_VM_INTERNAL_IP
: o endereço IP interno.
Volte a implementar um contentor
Ao voltar a implementar o contentor, inicia uma nova cópia do contentor e elimina o contentor comprometido.
Volta a implementar um contentor eliminando o pod que o aloja. Se o pod for gerido por uma construção do Kubernetes de nível superior (por exemplo, uma implementação ou um DaemonSet), a eliminação do pod agenda um novo pod. Este pod executa novos contentores.
A nova implementação faz sentido quando:
- Já conhece a causa da vulnerabilidade.
- Considera que um atacante precisa de um esforço ou tempo significativo para comprometer novamente o seu contentor.
- Acha que o contentor pode ser comprometido rapidamente novamente e não quer desativá-lo. Por isso, planeia colocá-lo numa sandbox para limitar o impacto.
Ao reimplementar a carga de trabalho, se a possibilidade de outro comprometimento for elevada, considere colocar a carga de trabalho num ambiente de sandbox, como o GKE Sandbox. A colocação em sandbox limita o acesso ao kernel do nó anfitrião se o atacante comprometer novamente o contentor.
Para voltar a implementar um contentor no Kubernetes, elimine o pod que o contém:
kubectl delete pods POD_NAME --grace-period=10
Se os contentores no pod eliminado continuarem a ser executados, pode eliminar a carga de trabalho.
Para reimplementar o contentor num sandbox, siga as instruções em Reforce o isolamento da carga de trabalho com o GKE Sandbox.
Elimine uma carga de trabalho
A eliminação de uma carga de trabalho, como uma implementação ou um DaemonSet, faz com que todos os respetivos pods membros sejam eliminados. Todos os contentores nesses pods deixam de ser executados. A eliminação de uma carga de trabalho pode ser útil quando:
- Quer parar um ataque em curso.
- Está disposto a colocar a carga de trabalho offline.
- Parar o ataque imediatamente é mais importante do que o tempo de atividade da aplicação ou a análise forense.
Para eliminar uma carga de trabalho, use kubectl delete CONTROLLER_TYPE
.
Por exemplo, para eliminar uma implementação, execute o seguinte comando:
kubectl delete deployments DEPLOYMENT
Se a eliminação da carga de trabalho não eliminar todos os pods ou contentores associados, pode eliminar manualmente os contentores através da ferramenta CLI dos tempos de execução de contentores, normalmente docker
. Se os seus nós executarem o containerd, use o crictl
.
Docker
Para parar um contentor que usa o tempo de execução do contentor Docker, pode usar docker stop
ou docker kill
.
O docker stop
para o contentor enviando um sinal SIGTERM
para o processo raiz e aguarda 10 segundos para que o processo termine por predefinição. Se o processo não tiver terminado nesse período, envia um sinal SIGKILL
.
Pode especificar este período de tolerância com a opção --time
.
docker stop --time TIME_IN_SECONDS CONTAINER
docker kill
é o método mais rápido para parar um contentor. Envia o sinal SIGKILL
imediatamente.
docker kill CONTAINER
Também pode parar e remover um contentor num único comando com docker rm -f
:
docker rm -f CONTAINER
containerd
Se usar o tempo de execução containerd
no GKE, para ou remove contentores com crictl
.
Para parar um contentor no containerd
, execute o seguinte comando:
crictl stop CONTAINER
Para remover um contentor no containerd
, execute o seguinte comando:
crictl rm -f CONTAINER
Elimine a VM anfitriã
Se não conseguir eliminar nem remover o contentor, pode eliminar a máquina virtual que aloja o contentor afetado.
Se o pod ainda estiver visível, pode encontrar o nome da VM anfitriã com o seguinte comando:
kubectl get pods --all-namespaces \
-o=custom-columns=POD_NAME:.metadata.name,INSTANCE_NAME:.spec.nodeName \
--field-selector=metadata.name=POD_NAME
Para eliminar a VM anfitriã, execute o seguinte comando gcloud
:
gcloud compute instance-groups managed delete-instances INSTANCE_GROUP_NAME \
--instances=NODE_NAME
Abandonar a instância do grupo de instâncias geridas reduz o tamanho do grupo em uma VM. Pode adicionar manualmente uma instância novamente ao grupo com o seguinte comando:
gcloud compute instance-groups managed resize INSTANCE_GROUP_NAME \
--size=SIZE
O que se segue?
- Realizar análises forenses em contentores
- Reforçar a segurança do cluster
- Análise forense para aplicações GKE